美文网首页
快排、双路快排、三路快排(java版)

快排、双路快排、三路快排(java版)

作者: 小毛1221 | 来源:发表于2019-11-27 23:15 被阅读0次
    import java.util.Date;
    import java.util.Random;
    
    /**
     * Created by maopengyu on 2019/11/27.
     * 快排、双路快排、三路快排
     * 参考:https://a1049145827.github.io/2018/10/15/Swift-%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F%E3%80%81%E5%8F%8C%E8%B7%AF%E5%BF%AB%E6%8E%92%E5%92%8C%E4%B8%89%E8%B7%AF%E5%BF%AB%E6%8E%92/
     */
    public class QuickSort {
        private Random random = new Random();
        private int[] quickSort3Arr = new int[2];
    
        private void swap(int[] arr, int i, int j) {
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    
        /**
         * 普通快排,时间复杂度O(nlogn),在数组有序或者重复元素较多时会退化到O(n2)
         * 当数组重复元素较多时,partition过程会将数组分成两个不平衡的部分(重复元素都在一边)
         * @param arr
         * @param start
         * @param end
         */
        public void quickSort(int[] arr, int start, int end) {
            if (start >= end) {
                return;
            }
            int mid = partition(arr, start, end);
            quickSort(arr, start, mid - 1);
            quickSort(arr, mid + 1 , end);
        }
    
        private int partition(int[] arr, int start, int end) {
            int r = start + random.nextInt(end - start + 1);
            swap(arr, r, start);
            int j = start;
            for (int i = start + 1; i <= end; i++) {
                if (arr[i] < arr[start]) {
                    swap(arr, i, ++j);
                }
            }
            swap(arr, j, start);
            return j;
        }
    
        /**
         * 双路快排,优化重复元素多的情况,指针i和j从两端向中间逼近,
         * 将小于arr[mid]的值,放在左边;大于arr[mid]的值,放在右边,不会将重复元素放在一边,左右两变都可能包含相等的元素
         * @param arr
         * @param start
         * @param end
         */
        public void quickSort2(int[] arr, int start, int end) {
            if (start >= end) {
                return;
            }
            int mid = partition2(arr, start, end);
            quickSort(arr, start, mid - 1);
            quickSort(arr, mid + 1 , end);
        }
    
        private int partition2(int[] arr, int start, int end) {
            int r = start + random.nextInt(end - start + 1);
            swap(arr, r, start);
            int i = start + 1;
            int j = end;
    
            while (true) {
                // 这里不能arr[i] <= arr[start] 否则如果连续出现多个==的情况,则会把这些值归到一边
                while (i <= end && arr[i] < arr[start]) {
                    i++;
                }
                // 这里不能arr[j] >= arr[start] 否则如果连续出现多个==的情况,则会把这些值归到一边
                while (j >= start + 1 && arr[j] > arr[start]) {
                    j--;
                }
                if (i >= j) {
                    break;
                }
                swap(arr, i, j);
                i++;
                j--;
            }
    
            swap(arr, j, start);
            return j;
        }
    
        /**
         * 三路快排,将数据按arr[mid]分为,小于、等于、大于三个区域,
         * 递归时,只需处理小于和大于的区域,减少了一次处理的元素
         * @param arr
         * @param start
         * @param end
         */
        public void quickSort3(int[] arr, int start, int end) {
            if (start >= end) {
                return;
            }
            int[] mid = partition3(arr, start, end);
            quickSort3(arr, start, mid[0]);
            quickSort3(arr, mid[1], end);
        }
    
        private int[] partition3(int[] arr, int start, int end) {
            int r = start + random.nextInt(end - start + 1);
            swap(arr, r, start);
    
            int lt = start; //arr[start+1, lt] < arr[start]
            int i = start + 1; //arr[lt+1, i] < arr[start]
            int gt = end + 1; //arr[gt, end] > arr[start]
    
            while (i < gt) {
                if (arr[i] < arr[start]) {
                    swap(arr, i, lt + 1);
                    i++;
                    lt++;
                }else if (arr[i] > arr[start]) {
                    swap(arr, i, gt - 1);
                    gt--;
                }else {
                    i++;
                }
            }
            swap(arr, lt, start);
    
            quickSort3Arr[0] = lt - 1;
            quickSort3Arr[1] = gt;
    
            return quickSort3Arr;
        }
    
        public static void main(String[] args) {
            Random random1 = new Random();
            int[] arr1 = new int[50000];
            int[] arr2 = new int[50000];
            int[] arr3 = new int[50000];
            for (int i = 0; i < 50000; i++) {
                int num = random1.nextInt(10);
                arr1[i] = num;
                arr2[i] = num;
                arr3[i] = num;
            }
    
            QuickSort quickSort = new QuickSort();
    
            Date start1 = new Date();
            quickSort.quickSort(arr1, 0, arr1.length - 1);
            Date end1 = new Date();
            System.out.println((end1.getTime() - start1.getTime()));
            StringBuilder sb1 = new StringBuilder();
            for (int i : arr1) {
                sb1.append(i);
            }
    
            Date start2 = new Date();
            quickSort.quickSort2(arr2, 0, arr3.length - 1);
            Date end2 = new Date();
            System.out.println((end2.getTime() - start2.getTime()));
            StringBuilder sb2 = new StringBuilder();
            for (int i : arr2) {
                sb2.append(i);
            }
    
            Date start3 = new Date();
            quickSort.quickSort3(arr3, 0, arr3.length - 1);
            Date end3 = new Date();
            System.out.println((end3.getTime() - start3.getTime()));
            StringBuilder sb3 = new StringBuilder();
            for (int i : arr3) {
                sb3.append(i);
            }
    
            if (sb1.toString().equals(sb2.toString()) && sb2.toString().equals(sb3.toString())) {
                System.out.println("true");
            }
            /**
             * 结果:
             * 108
             * 70
             * 7
             * true
             */
        }
    }
    
    

    相关文章

      网友评论

          本文标题:快排、双路快排、三路快排(java版)

          本文链接:https://www.haomeiwen.com/subject/uwtvwctx.html