常见算法

排序算法

package DataStructureAndAlgorithm;

import java.util.Arrays;

public class SortTest {
    public static void main(String[] args) {
        int[] a = {1,2,3,4,5,6,7,8,9,0};
        quickSort(a, 0, a.length-1);
        for (int i : a){
            System.out.print(i + "");
        }
        System.out.println();

        a = new int[]{1,2,3,4,5,6,7,8,9,0};
        mergeSort(a, 0, a.length-1);
        for (int i : a){
            System.out.print(i + "");
        }
        System.out.println();

        a = new int[]{1,2,3,4,5,6,7,8,9,0,};
        heapSort(a);
        for (int i : a){
            System.out.print(i + "");
        }
        System.out.println();
    }

    public static void quickSort(int[] a, int low, int high){
        //分治算法:将原数组划分为两部分
        if(low < high){
            //确定pivot最终的位置,然后将数组划分为两部分递归计算
            int pivotPos = partition(a, low, high);
            quickSort(a, low, pivotPos-1);
            quickSort(a, pivotPos+1, high);
        }
    }

    public static int partition(int[] a, int low, int high){
        int pivot = a[low];

        while (low < high){
            //从右边选出比pivot小的,放在左边
            while (low < high && a[high] >= pivot)
                high--;
            a[low] = a[high];

            //从左边选出比pivot大的,放在右边
            while (low < high && a[low] <= pivot)
                low++;
            a[high] = a[low];
        }
        a[low] = pivot;

        return low;
    }

    public static void mergeSort(int[] a, int low, int high){
        //分治算法:将原数组划分为两部分
        if(low < high){
            //划分为相同大小的两部分,经过mergeSort后是两个内部有序的子数组,
            //然后调用merge就可以合成一个有序数组了
            int mid = (low + high) / 2;
            mergeSort(a, low, mid);
            mergeSort(a, mid+1, high);
            merge(a, low, mid, high);
        }
    }

    public static void merge(int[] a, int low, int mid, int high){
        //需要额外的空间,这里可以优化,只需要high-low+1的长度
        //copyA保存了a的副本,后面就可以直接对a进行赋值操作
        int[] copyA = Arrays.copyOf(a, a.length);
        int i = low;
        int j = mid+1;
        int k = low;
        while (i <= mid && j <= high){
            if(copyA[i] < copyA[j]){
                a[k++] = copyA[i++];
            }else {
                a[k++] = copyA[j++];
            }
        }
        while (i <= mid){
            a[k++] = copyA[i++];
        }
        while (j <= high){
            a[k++] = copyA[j++];
        }
    }

    public static void heapSort(int[] a){
        //思路:构建最大堆,每次取出堆顶,然后维护堆。这样取出的数字就是从大到小的有序序列。

        //构建最大堆:从中间的元素开始向下调整
        for(int i = a.length/2-1; i >= 0; i--){
            adjustDown(a, i, a.length-1);
        }

        //取出堆顶交换数组最后,并维护堆
        //这里i=a.length-1是堆最后一个节点的父节点的索引,不信你画个图
        for(int i = a.length - 1; i > 0; i--){
            //交换
            int temp = a[0];
            a[0] = a[i];
            a[i] = temp;

            adjustDown(a, 0, i-1);
        }
    }

    public static void adjustDown(int[] a, int i, int end){
        //保存当前值
        int temp = a[i];

        //沿i较大的子节点一直向下交换,直到出界或者后面的都比当前节点小
        for(int j = 2*i+1; j <= end; j *= 2){
            //j是两个孩子中关键字大的那个孩子的索引
            if(j+1 <= end && a[j] < a[j+1]){
                j++;
            }
            //a[i]值保存在temp中,比a[j]大则不用维护堆了,已经好了
            if(temp >= a[j]){
                break;
            }else {
                a[i] = a[j];
                i = j;
            }
        }
        //现在i已经到了最底层,把最开始的值赋给它
        a[i] = temp;
    }
}

二叉树构建

package DataStructureAndAlgorithm;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

public class TreeTraversals {
    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();

        String pre = "ABDEFC";
        String in = "DBFEAC";
        String post = "";
        String level = "";

        TreeNode root = CreateTreeByPreAndIn(pre, in);
        System.out.println("后序遍历");
        System.out.println(TraversalsByPost(root));
    }

    static TreeNode CreateTreeByPreAndIn(String pre, String in){
        if(pre.equals("") && in.equals("")){
            return null;
        }
        int indexOfRootAtIn = 0;
        int length = pre.length();
        for(; indexOfRootAtIn < length; indexOfRootAtIn++){
            //获取根节点在中序序列的值
            if(in.charAt(indexOfRootAtIn) == pre.charAt(0)){
                break;
            }
        }
        TreeNode root = new TreeNode(in.charAt(indexOfRootAtIn));
        root.left = CreateTreeByPreAndIn(pre.substring(1, indexOfRootAtIn + 1), in.substring(0, indexOfRootAtIn));
        root.right = CreateTreeByPreAndIn(pre.substring(indexOfRootAtIn + 1, length), in.substring(indexOfRootAtIn + 1, length));

        return root;
    }

    static TreeNode CreateTreeByInAndPost(String in, String post){
        if(post.equals("") && in.equals("")){
            return null;
        }
        int indexOfRootAtIn = 0;
        int length = post.length();
        for(; indexOfRootAtIn < length; indexOfRootAtIn++){
            //获取根节点在中序序列的值
            if(in.charAt(indexOfRootAtIn) == post.charAt(length-1)){
                break;
            }
        }
        TreeNode root = new TreeNode(in.charAt(indexOfRootAtIn));
        root.left = CreateTreeByInAndPost(in.substring(0, indexOfRootAtIn), post.substring(0, indexOfRootAtIn));
        root.right = CreateTreeByInAndPost(in.substring(indexOfRootAtIn + 1, length), post.substring(indexOfRootAtIn, length-1));

        return root;
    }

    static TreeNode CreateTreeByInAndLevel(String in, String level){
        if(level.equals("") && in.equals("")){
            return null;
        }
        int indexOfRootAtIn = 0;
        int length = in.length();
        for(; indexOfRootAtIn < length; indexOfRootAtIn++){
            //获取根节点在中序序列的值
            if(in.charAt(indexOfRootAtIn) == level.charAt(0)){
                break;
            }
        }

        //问题的关键在于如何用根节点层序和中序序列构建出左子树和右子树的层序序列
        String leftTreeOfIn = in.substring(0, indexOfRootAtIn);
        String rightTreeOfIn = in.substring(indexOfRootAtIn+1, length);

        StringBuffer leftTreeOfLevel = new StringBuffer();
        StringBuffer rightTreeOfLevel = new StringBuffer();
        Set<Character> set = new HashSet<Character>();
        for(int i = 0; i < leftTreeOfIn.length(); i++){
            set.add(leftTreeOfIn.charAt(i));
        }
        for(int i = 1; i < length; i++){
            if(set.contains(level.charAt(i))){
                leftTreeOfLevel.append(level.charAt(i));
            }else {
                rightTreeOfLevel.append(level.charAt(i));
            }
        }
        TreeNode root = new TreeNode(level.charAt(0));
        root.left = CreateTreeByInAndLevel(leftTreeOfIn, leftTreeOfLevel.toString());
        root.right = CreateTreeByInAndLevel(rightTreeOfIn, rightTreeOfLevel.toString());

        return root;
    }

    static String TraversalsByPre(TreeNode root){
        if(root == null)
            return "";
        StringBuffer stringBuffer = new StringBuffer();

        stringBuffer.append(root.val);
        stringBuffer.append(TraversalsByPre(root.left));
        stringBuffer.append(TraversalsByPre(root.right));

        return stringBuffer.toString();
    }

    static String TraversalsByIn(TreeNode root){
        if(root == null)
            return "";
        StringBuffer stringBuffer = new StringBuffer();

        stringBuffer.append(TraversalsByIn(root.left));
        stringBuffer.append(root.val);
        stringBuffer.append(TraversalsByIn(root.right));

        return stringBuffer.toString();
    }

    static String TraversalsByPost(TreeNode root){
        if(root == null)
            return "";
        StringBuffer stringBuffer = new StringBuffer();

        stringBuffer.append(TraversalsByPost(root.left));
        stringBuffer.append(TraversalsByPost(root.right));
        stringBuffer.append(root.val);

        return stringBuffer.toString();
    }

    static String TraversalsByLevel(TreeNode root){
        StringBuffer stringBuffer = new StringBuffer();

        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);

        while ( !queue.isEmpty() ){
            TreeNode cur = queue.poll();
            stringBuffer.append(cur.val);
            if(cur.left != null)
                queue.add(cur.left);
            if(cur.right != null)
                queue.add(cur.right);
        }
        return stringBuffer.toString();
    }

}

class TreeNode{
    char val;
    TreeNode left = null;
    TreeNode right = null;
    TreeNode(char val){
        this.val = val;
    }
}

链表环入口

public ListNode EntryNodeOfLoop(ListNode pHead){
    //相遇的节点并不是入口节点
    //fast节点比slow节点多走的步数是环长度L的倍数,所以slow节点的步数也是L的倍数
    //所以pHead节点和相遇节点距离入口节点的距离相同,result和slow会相遇在入口节点
    ListNode fast = pHead, slow = pHead, result = pHead;
    while(fast != null  &&  fast.next != null){
        fast = fast.next.next;
        slow = slow.next;
        if(fast == slow){
            while(result != slow){
                result = result.next;
                slow = slow.next;
            }
            return result;
        }
    }
    //如果fast遇到了null,表示没有环,则返回一个null就行了
    return null;
}

图遍历、最短路径

这里用二维数组weight表示图的邻接矩阵

package DataStructureAndAlgorithm;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

public class GraphTest {

    //距离为M表示不相邻,
    static int M = 10000;

    public static void main(String[] args) {
        int[][] weight = {
                {0,10,M,30,100},
                {M,0,50,M,M},
                {M,M,0,M,10},
                {M,M,20,0,60},
                {M,M,M,M,0}
        };

        BfsTraverse(weight);

        DFSTraverse(weight);

        int start=0;
        int[] shortestPathLength = dijkstra(weight,start);

        for(int i = 0;i < shortestPathLength.length;i++){
            System.out.print(shortestPathLength[i] + "\t");
        }
    }

    public static int[] dijkstra(int[][] weight, int start){
        //检查null和长度0
        if(weight == null || weight.length == 0){
            return null;
        }

        int n = weight.length;
        //shortestPathLength表示长度,path路径
        int[] shortestPathLength = new int[n];
        int[] path = new int[n];
        boolean[] visited = new boolean[n];
        visited[start] = true;

        for(int i = 0; i < n; i++){
            path[i] = start;
            shortestPathLength[i] = weight[start][i];
        }

        //循环n-1次,因为start结果不用
        System.out.println("循环n-1次");
        for(int i = 1; i < n; i++){
            int min = Integer.MAX_VALUE;
            int nextVertex = n;

            for(int j = 0; j < n; j++){
                if(!visited[j] && shortestPathLength[j] < min){
                    min = shortestPathLength[j];
                    nextVertex = j;
                }
            }

            visited[nextVertex] = true;


            for(int j = 0; j < n; j++){
                if(!visited[j] && (shortestPathLength[nextVertex] + weight[nextVertex][j]) < shortestPathLength[j]){
                    shortestPathLength[j] = shortestPathLength[nextVertex] + weight[nextVertex][j];
                    path[j] = nextVertex;
                }
            }
        }
        return shortestPathLength;
    }

    public static void BfsTraverse(int[][] weight){

        if(weight == null){
            return;
        }

        //节点个数
        int n = weight.length;

        boolean[] visited = new boolean[n];
        Queue<Integer> queue = new LinkedList<Integer>();
        ArrayList<Integer> list = new ArrayList<Integer>();

        //对每个节点进行一次BFS,用于处理非连通图
        //连通图一次BFS可以访问结束
        for (int i = 0; i < n; i++){

            //BFS主代码
            if(!visited[i]){
                //访问,visited设置true,入队列三件事同时进行
                list.add(i);
                visited[i] = true;
                queue.add(i);

                while (!queue.isEmpty()){
                    //访问队头节点
                    int current = queue.poll();

                    for (int j = 0; j < n; j++){
                        //添加下一个节点到队列中
                        //条件:要相邻;未访问过
                        if(!visited[j] && weight[current][j] != M){
                            //BFS要在这里设置true,不设置的话可能会被再次访问。
                            // 因为DFS和层序不会,因为DFS马上就会递归去执行,而层序是不会往上走的
                            queue.add(j);
                            list.add(j);
                            visited[j] = true;
                        }
                    }
                }//一次BFS结束

            }
        }
        System.out.println(list);
    }

    public static void DFSTraverse(int[][] weight){
        if(weight == null){
            return;
        }
        int n = weight.length;
        boolean[] visited = new boolean[n];
        ArrayList<Integer> list = new ArrayList<Integer>();

        for(int i = 0; i < n; i++){
            if(!visited[i]){
                DFS(weight, i, visited, list);
            }
        }
        System.out.println(list);
    }

    public static void DFS(int[][] weight, int i, boolean[] visited, ArrayList<Integer> list) {
        visited[i] = true;
        list.add(i);

        for(int j = 0; j < weight.length; j++){
            if(!visited[j] && weight[i][j] != M){
                DFS(weight, j, visited, list);
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值