基础算法(图与树)

1、快速排序
最快时间复杂度为O(nlogn)

public class QuickSort {
    public static void quickSort(int a[], int l, int r) {
        if(l>r) {
            return;
        }
        int i = l; int j = r; int key = a[l];
        while (i < j) {
            while (i key) 
                j--;
            if(i<j) {
                a[i] = a[j];
                i++;
            }
            while(i<j && a[i] < key)
                i++;
            if(i<j) {
                a[j] = a[i];
                j--;
            }
        }
        a[i] = key;
        quickSort(a,i+1,r);
        quickSort(a,l,i-1);
    }
}

2、堆排序

public class HeaoSort {
    public static int[] heapSort(int[] arr) {
        // 调整堆要从最后一个非叶子节点开始
        for (int i = arr.length/2-1; i >= 0; i--) {
            adjustHeap(arr, i, arr.length);
        }
        //交换,再调整
        for (int i = arr.length-1; i > 0 ; i++) {
            swap(arr, 0, i); // 每次都交换二叉树的最后一个元素和第一个元素。保持二叉树最后一个元素为当前排序的最大值
            adjustHeap(arr, 0, i); // 交换之后进行从上往下依次调整
        }
        return arr;
    }
    // 交换元素
    private static void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i]=arr[j];
        arr[j]=tmp;
    }
    // 从上往下依次调整
    private static void adjustHeap(int[] arr, int i, int length) { 
        int temp = arr[i];
        for (int j = i*2+1; j < length; j = j*2+1) {
            if(j+1 < length && arr[j] < arr[j+1]){ // j始终指向较大的那个子节点
                j++;
            }
            if(arr[j] > temp) { // 子节点比父节点大,则交换
                arr[i] = arr[j];
                i = j; 
            } else {
                break; // 直到满足父节点大于子节点的状态,则跳出循环
            }
        }
        arr[i] = temp; 
    }
    public static void main(String[] args) {
        int[] arr = {9,8,7,6,5,4,3,2,1};
        heapSort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

3、冒泡排序

public class BubbleSort {
    public static void main(String[] args) {
      int[] arr =  bubblesort(new int[]{9,6,2,3,4,1,5,0,7,8});
      for (Integer i: arr) {
          System.out.print(i + " ");
      }
    }
    public static int[] bubblesort(int[] arr) {
        int temp;
        for (int i = 1; i <= arr.length; i++) {
            for (int j = 0; j < arr.length-i; j++) {
                if(arr[j] > arr[j+1]) {
                    temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
        return arr;
    }
}

4、插入排序

public class InsertSort {
    public static void main(String[] args) {
       int[] arr = insertsort(new int[]{9,3,2,4,5,1,6,8,0,7});
        for (Integer i: arr) {
            System.out.println(i);
        }
    }
    public static int[] insertsort(int[] arr) {
        int temp;
        for (int i = 0; i < arr.length; i++) {
            for (int j = i; j > 0; j--) {
                if(arr[j] < arr[j-1]) {
                    temp = arr[j];
                    arr[j] = arr[j-1];
                    arr[j-1] = temp;
                }
            }
        }
        return arr;
    }
}

5、归并排序

public class MergeSort {
    public static void merge(int[] a, int left, int mid, int right) {
        int[] result = new int[a.length];
        int i = left, p1 = left, p2 = right;
        while(left = mid) {
            result[i++] = a[left] <= a[right] ? a[left++] : a[right--];
        }
        while(left <= mid) result[i++] = a[left++];
        while(right >= mid) result[i++] = a[right--];
        for (int j = p1; j <= p2; j++) {
            a[j] = result[j];
        }
    }
    public static void mergeSort(int[] a, int start, int end) {
        if(start < end) {
            int mid = (start + end) / 2;
            mergeSort(a, start, mid);
            mergeSort(a, mid+1, end);
            merge(a, start, mid, end);
        }
    }
    public static void main(String[] args) {
        int[] a = new int[]{8,4,5,6,2,3,1,7,9};
        mergeSort(a, 0, a.length);
        for (int e : a) {
            System.out.print(e + " ");
        }
    }
}

6、二叉树递归先序遍历

 class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    public TreeNode() {}

    public TreeNode(int val) {
        this.val = val;
    }

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
 }

 public void PreorderRaversal(TreeNode node) {
        System.out.println(node.val);
        PreorderRaversal(node.left);
        PreorderRaversal(node.right);
    }

7、二叉树非递归先序遍历

 public void nonPreorderRaverersalRecursion(TreeNode node) {
        Stack stack = new Stack();
        TreeNode T = node;
        while(T != null || !stack.empty()) {
            while (T != null) {
                System.out.println(T.val);
                stack.push(T);
                T = T.left;
            }
            if(!stack.empty()) {
                T = stack.pop();
                T = T.right;
            }
        }
    }

8、二叉树递归中序遍历

 public void PreorderRaversal(TreeNode node) {
        PreorderRaversal(node.left);
        System.out.println(node.val);
        PreorderRaversal(node.right);
    }

9、二叉树非递归中序遍历

public void nonInorderTraversalRecursion(TreeNode node) {
        Stack stack = new Stack();
        TreeNode T = node;
        while(T != null || !stack.empty()) {
            while (T != null) {
                stack.push(T);
                T = T.left;
            }
            if(!stack.empty()) {
                T = stack.pop();
                System.out.println(T.val);
                T = T.right;
            }
        }
    }

10、二叉树递归后序遍历

public void PreorderRaversal(TreeNode node) {
        PreorderRaversal(node.right);
        PreorderRaversal(node.left);
        System.out.println(node.val);
    }

11、二叉树非递归后续遍历

 public void nonPostorderraversalRecursion(TreeNode node) {
        Stack stack1 = new Stack();
        Stack stack2 = new Stack();
        TreeNode T = node;
        while(T != null || !stack1.empty()) {
            while (T != null) {
                stack2.push(T);
                stack1.push(T);
                T = T.right;
            }
            if(!stack1.empty()) {
                T = stack1.pop();
                T = T.left;
            }
        }
        while (!stack1.empty()) {
            T = stack1.pop();
            System.out.println(T.val);
        }
    }

12、二叉树层数遍历

public class LayerTraversal {
    public static void main(String[] args) {
        TreeNode node3 = new TreeNode(3);
        TreeNode node4 = new TreeNode(4);
        TreeNode node1 = new TreeNode(1, node3, node4);
        TreeNode node2 = new TreeNode(2);
        TreeNode node = new TreeNode(0, node1, node2);
        layerTraversal(node);
    }
    public static void layerTraversal(TreeNode node) {
        Queue queue = new LinkedList();
        if (node != null) {
            queue.add(node);
            while(!queue.isEmpty()) {
                TreeNode temp = queue.poll();
                System.out.println(temp.val);
                if(temp.left != null) queue.add(temp.left);
                if(temp.right != null) queue.add(temp.right);
            }
        }
    }
}

13、二叉树深度优先搜索(先序遍历)
14、二叉树广度优先搜素(层次遍历)
15、求二叉树的高度 ;

public class GetHigh {
    public static void main(String[] args) {
        TreeNode node5 = new TreeNode(3);
        TreeNode node6 = new TreeNode(4);
        TreeNode node3 = new TreeNode(3, node5, node6);
        TreeNode node4 = new TreeNode(4);
        TreeNode node1 = new TreeNode(1, node3, node4);
        TreeNode node2 = new TreeNode(2);
        TreeNode node = new TreeNode(0, node1, node2);
        System.out.println(gethigh(node));
    }
    public static int gethigh(TreeNode node) {
        if (node != null) {
            return gethigh(node.left) > gethigh(node.right) ? gethigh(node.left) + 1: gethigh(node.right) + 1;
        } else {
            return 0;
        }
    }
}

16、求二叉树的叶子节点的个数 ;

public class NumberOfLeafNodes {
    public static void main(String[] args) {
        TreeNode node8 = new TreeNode(8);
        TreeNode node7 = new TreeNode(7);
        TreeNode node5 = new TreeNode(5);
        TreeNode node6 = new TreeNode(6, node7, node8);
        TreeNode node3 = new TreeNode(3, node5, node6);
        TreeNode node4 = new TreeNode(4);
        TreeNode node1 = new TreeNode(1, node3, node4);
        TreeNode node2 = new TreeNode(2);
        TreeNode node = new TreeNode(0, node1, node2);
        int number = getNumberOfLeafNodes(node);
        System.out.println(number);
    }
    private static int flag = 0;
    public static int getNumberOfLeafNodes(TreeNode node) {
        if(node != null) {
            if(node.left == null && node.right == null)  flag++;
            getNumberOfLeafNodes(node.left);
            getNumberOfLeafNodes(node.right);
        }
        return flag;
    }
}

17、求二叉树第k层的节点个数 ;

public class NumberOfKLayerNode {
    public static int numberOfKLayerNode(TreeNode node, int k) {
        if(node == null || k < 0) {
            return 0;
        }
        if(k == 1) {
            return 1;
        }
        int left = numberOfKLayerNode(node.left, k-1);
        int right = numberOfKLayerNode(node.right, k-1);
        return left + right;
    }
}

18、判断一个节点是否在一棵二叉树中 ;

 public static boolean judgeNode(TreeNode node, TreeNode temp) {
        if(node == null || temp == null) return false;
        if(node == temp) return true;
        return judgeNode(node.left, temp) || judgeNode(node.right, temp);
    }

19、求二叉树的镜像;

  public static void binaryTreeImage(TreeNode node) {
        if(node != null) {
            TreeNode temp = node.left;
            node.left = node.right;
            node.right = temp;
            binaryTreeImage(node.left);
            binaryTreeImage(node.right);
        }
    }

20、判断两颗二叉树是否相等;

 public static boolean binaryTreeIsSame(TreeNode node1, TreeNode node2) {
        if(node1 != null && node2 != null) {
           if(node1 == node2) {
               return true;
           } else {
               return false;
           }
        }
        return binaryTreeIsSame(node1.left, node2.left) && binaryTreeIsSame(node1.right, node2.right);
    }

21、从二叉树中查找结点

public class FindNode {
    public static void main(String[] args) {
        TreeNode node5 = new TreeNode(5);
        TreeNode node6 = new TreeNode(6);
        TreeNode node3 = new TreeNode(3, node5, node6);
        TreeNode node4 = new TreeNode(4);
        TreeNode node1 = new TreeNode(1, node3, node4);
        TreeNode node2 = new TreeNode(2);
        TreeNode node = new TreeNode(0, node1, node2);
        TreeNode temp = findNode(node, 2);
        System.out.println(temp.val);
    }
    public static TreeNode findNode(TreeNode node, int aim) {
        TreeNode value = null;
        if(node != null) {
            if (node.val == aim) {
                value = node;
            } else {
                if(value == null) {
                    value = findNode(node.left, aim);
                }
                if(value == null) {
                    value = findNode(node.right, aim);
                }
            }
        }
        return value;
    }
}

22、构建二叉树

 public static TreeNode createTree(int[] aim) {
        TreeNode node = new TreeNode(aim[0]);
        Queue queue = new LinkedList();
        queue.add(node);
        for (int i = 1; i < aim.length-1; i++) {
            if(!queue.isEmpty()) {
                TreeNode temp = queue.poll();
                TreeNode left = new TreeNode(aim[i]);
                TreeNode right = new TreeNode(aim[++i]);
                temp.left = left;
                temp.right = right;
                queue.add(left);
                queue.add(right);
            }
        }
        return node;
    }

23、kruskal算法求最小生成树
24、prim算法求最小生成树
25、检查一颗二叉树是否平衡

public class IsBalanceTree {
    public static void main(String[] args) {
        TreeNode node4 = new TreeNode(4);
        TreeNode node3 = new TreeNode(3);
        TreeNode node2 = new TreeNode(2, node3, null);
        TreeNode node1 = new TreeNode(1,node2,node4);
        TreeNode root = new TreeNode(0, node1, null);

        IsBalanceTree isBalanceTree = new IsBalanceTree();
        Boolean bool = isBalanceTree.isBalanceTree(root);
        System.out.println(root.val);
        System.out.println(bool);
    }

    // 左右节点的高度不超过1
    public int calculate(TreeNode root, int tap) {
        if(root == null) return 0;
        int left = calculate(root.left, tap);
        int right = calculate(root.right, tap);
        tap = left >= right ? left - right : right - left;
        root.val = tap;
        return left > right? left + 1 : right +1;
    }

    public boolean isBalanceTree(TreeNode node) {
        if(node == null) return true;
        isBalanceTree(node.left);
        isBalanceTree(node.right);
        calculate(node, 0);
       return node.val > 1 ? false : true;
    }
}

26、图的遍历

有圈的是图,边没有指向性的图叫做无向图,边具有指向性的图叫做有向图,没有圈的连接图叫做树,没有圈的非连接图叫做森林。
图可以分为有向图和无向图,一般用G=(V,E)来表示图。经常用邻接矩阵或者邻接表来描述一副图。
图的遍历可分为广度优先搜索(BFS)和深度优先搜索(DFS)。

1)邻接表的定义

// 简单的无向图节点表示
// 邻接表
public class GraphNode<T> {
    T data;
    List<GraphNode<T>> neighborList;
    boolean visited;

    public GraphNode(T data) {
        this.data = data;
        neighborList = new ArrayList<GraphNode<T>>();
        visited = false;
    }

    public boolean equals(GraphNode<T> node){
        return this.data.equals(node.data);
    }

    public void restoreVisited() {
        restoreVisited(this);
    }

    private void restoreVisited(GraphNode<T> node) {
        if(node.visited) {
            node.visited = false;
        }

        List<GraphNode<T>> neighbors = node.neighborList;
        for (int i = 0; i < neighbors.size(); i++) {
            restoreVisited(neighbors.get(i));
        }
    }
}

2)邻接表实现图的深度优先遍历和广度优先遍历

package leetcode.graph;

import java.util.*;

public class SearchGraph<T> {
    StringBuffer  searchDFS = new StringBuffer();
    StringBuffer searchBFS = new StringBuffer();

    // 深度优先遍历
    public void searchDFS(GraphNode<T> root) {
        if(root == null)
            return;

        if(searchDFS.length() > 0) {
            searchDFS.append("->");
        }
        root.visited = true;
        searchDFS.append(root.data.toString());

        for (GraphNode<T> node : root.neighborList) {
            if(!node.visited) {
                searchDFS(node);
            }
        }
    }

    // 广度优先遍历
    public void setSearchBFS(GraphNode<T> root) {
        Queue queue = new LinkedList();
        queue.add(root);
        searchBFS.append(root.data.toString());
        while(!queue.isEmpty()) {
            GraphNode<T> node = (GraphNode<T>) queue.poll();
            for (GraphNode<T> elem : node.neighborList) {
                    if(!elem.visited) {
                        searchBFS.append("->");
                        searchBFS.append(elem.data.toString());
                        elem.visited = true;
                        queue.add(elem);
                    }
            }
        }
    }

    // 创建邻接表
    public GraphNode setup() {
        GraphNode root = new GraphNode(0);
        GraphNode node1 = new GraphNode(1);
        GraphNode node2 = new GraphNode(2);
        GraphNode node3 = new GraphNode(3);
        GraphNode node4 = new GraphNode(4);
        GraphNode node5 = new GraphNode(5);

        List<GraphNode> neighborList = Arrays.asList(node1, node2, node3, node4);
        root.neighborList = neighborList;
        List<GraphNode> neighborList2 = Arrays.asList(node4, node5);
        node1.neighborList = neighborList2;
        List<GraphNode> neighborList3 = Arrays.asList(node1, node4);
        node3.neighborList = neighborList3;
        return root;
    }

    public static void main(String[] args) {
        SearchGraph searchGraph = new SearchGraph();
        GraphNode root = searchGraph.setup();
        searchGraph.searchDFS(root);
        System.out.println(searchGraph.searchDFS);
        GraphNode root1 = searchGraph.setup();
        searchGraph.setSearchBFS(root1);
        System.out.println(searchGraph.searchBFS);
    }
}

3) 邻接矩阵的定义

// 邻接矩阵表示法
public class MGraph {
    int vexs; // 图中的节点数
    char data[]; // 存放节点数据
    int[][] weight; // 存放边
    boolean[] visit; // 记录节点是否访问过

    public MGraph(int vexs) {
        this.vexs = vexs;
        this.data = new char[vexs];
        this.weight = new int[vexs][vexs];
    }
}

4) 邻接矩阵实现图的深度优先遍历和广度优先遍历

public class GraphMetrix {
    //  创建图的邻接矩阵
    public void CreateGraph(MGraph graph, int vexs, char data[], int[][] weight){
        graph.visit = new boolean[vexs];
        for (int i = 0; i < vexs; i++) {
            graph.data[i] = data[i];
            graph.visit[i] = false;
            for (int j = 0; j < vexs; j++) {
                graph.weight[i][j] = weight[i][j];
            }
        }
    }

    //获取当前节点K的第一个邻接顶点的位置
    public int GetFirst(MGraph graph, int k) {
        if(k < 0 || k > graph.vexs -1) {
            return -1;
        }
        for (int i = 0; i < graph.vexs; i++) {
            if(graph.weight[k][i] == 1) {
                return i;
            }
        }
        return -1;
    }

    // 获取当前节点K的第t个邻接顶点下一个邻接顶点的位置
    public int GetNext(MGraph graph, int k, int t) {
        if(k < 0 || k > graph.vexs - 1 || t < 0 || t > graph.vexs -1) {
            return -1;
        }
        for (int i = t+1; i < graph.vexs; i++) {
            if(graph.weight[k][i] == 1) {
                return i;
            }
        }
        return -1;
    }

    // 递归方式深度遍历图的邻接矩阵, k表示图的起始点
    public void DFSGraph(MGraph graph, int k) {
        graph.visit[k] = true;
        System.out.print(graph.data[k] + " ");
        int u = GetFirst(graph, k);
        while(u != -1) {
            if(graph.visit[u] == false) {
                DFSGraph(graph, u);
            }
            u = GetNext(graph, k, u);
        }
    }

    // 递归方式广度优先遍历邻接矩阵
    public void BFSGraph(MGraph graph, int k) {
        Queue<Integer> queue = new LinkedList();
        if(graph.visit[k] == false) {
            graph.visit[k] = true;
            queue.add(k);
        }
        while(!queue.isEmpty()) {
            k = queue.poll();
            System.out.print(graph.data[k] + " ");
            int u = GetFirst(graph, k);
            while(u != -1) {
                if(graph.visit[u] == false) {
                    graph.visit[u] = true;
                    queue.add(u);
                }
                u = GetNext(graph, k, u);
            }
        }
    }

    public static void main(String[] args) {
        char[] data = new char[]{'A', 'B', 'C', 'D', 'E'};
        int vexs = data.length;
        int[][] weight = new int[][] {
                {0,1,0,0,1},
                {1,0,1,1,0},
                {0,1,0,0,0},
                {0,1,0,0,1},
                {1,0,0,1,0}
        };

        MGraph graph = new MGraph(vexs);
        GraphMetrix graphMetrix = new GraphMetrix();
        graphMetrix.CreateGraph(graph, vexs, data, weight);
        graphMetrix.DFSGraph(graph, 0);
        graphMetrix.BFSGraph(graph, 0);
    }
}

27、dijkstra求最短路径
28、floyd求最短路径

全部评论

相关推荐

11-22 16:49
已编辑
北京邮电大学 Java
美团 质效,测开 n*15.5
点赞 评论 收藏
分享
09-30 20:49
湖南工学院 Java
SP小夜:举报了哥,你什么都没做错,全怪我那令人作呕的嫉妒和卑微的自尊心,看见你的文字我完全破防了,我直接丢盔弃甲了,看见你这图的那一秒,我满头大汗,浑身发冷,亿郁症瞬间发作了,生活仿佛没了颜色,像是被抓住尾巴的赛亚人,带着海楼石的能力者,抽离尾兽的人柱力,像是没了光的奥特曼,彻底断绝了生的希望。我几乎都快羡慕得疯了,倒在床上蒙住被子就开始抱着枕头尖叫流泪,嘴里一边喊着卧槽卧槽,一边又忍着,我边发边哭,打字的手都是抖的,后来我的手抖得越来越厉害,从心头涌起的思想、情怀和梦想,这份歆羡和悔恨交织在一起,我的笑还挂在脸上,可是眼泪一下子就掉下来了。求你了别发了,我生活再难再穷我都不会觉得难过,只有你们发这种东西的时候,我的心里像被刀割一样的痛,打着字泪水就忍不住的往下流。每天早上7点起床晚上9点睡觉,年复一年地学到现在,憧憬着一个月赚上万块的幸福生活,憧憬着美好阳光的未来。我打开了手机,看到你的图,我感到了深深的差距,我直接跳进了家门口的井里。
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务