【问题标题】:Quick sort algorithm to sort the array by using the Hoare Partitioning in Java使用Java中的Hoare Partitioning对数组进行排序的快速排序算法
【发布时间】:2020-03-17 23:34:18
【问题描述】:

我正在尝试通过快速排序对这个数组进行排序:

int[] arr = {25,23,21,29,28,22,24,27};

我的快速排序功能:

public static void quickSort(int[] arr) { // sorts array using quick sort algorithm
    if (arr[0] < arr[arr.length-1]) {
        int s = hoarePartitioning(arr);
        quickSort(Arrays.copyOfRange(arr, 0, s-1));
        quickSort(Arrays.copyOfRange(arr, s+1, arr.length));
    }
}

我使用了霍尔分区:

public static int hoarePartitioning(int[] arr) {
    int pivot = arr[0];
    int i = 0;
    int j = arr.length;
    do {
        do {i++;} while(pivot >= arr[i] && i < arr.length);
        do {j--;} while(pivot <= arr[j] && j >= 0);
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }while(i <= j);

    int temp = arr[i];  //undo last swap when i >= j
    arr[i] = arr[j];
    arr[j] = temp;

    temp = arr[0];
    arr[0] = arr[j];
    arr[j] = temp;

    return j;
}

但是,当我打印出数组时,结果如下:

22 23 21 24 25 28 29 27 

我的 Hoare 分区功能工作正常,但我仍然不明白为什么数组没有排序。我在这里做错了什么? 谢谢。

【问题讨论】:

    标签: java quicksort


    【解决方案1】:

    quicksort 方法根本上是错误的:

        quickSort(Arrays.copyOfRange(arr, 0, s-1));
        quickSort(Arrays.copyOfRange(arr, s+1, arr.length));
    

    每次递归时,为左右子数组创建一个新数组,(尝试)对新数组进行排序,然后将它们扔掉。最终结果:原始数组没有改变。

    不要复制子数组。传递原始数组,以及要在每个递归调用中排序的子数组的开始和结束。如有必要,使用辅助功能;例如

     public void quicksort(int[] array) {
         quicksort(array, 0, array.length - 1);
     }
    
     public void quicksort(int[] array, int start, int end) {
         ...
     }
    

    还有其他一些问题:

    1. if 测试看起来错误。为什么你会在这种情况下跳过对数组/子数组进行排序?实际测试应该是正在排序的子数组的大小......而不是子数组的内容。

    2. 子数组的上限计算看起来错误; s - 1 是包含范围,但 arr.length 是排他范围。其中一个肯定是错的。

    【讨论】:

    • 感谢第一个建议。但是,当我调试时,两个子数组似乎都适合我的界限。
    • 我不明白你在说什么。您指的是哪个“第一个建议”?主要问题还是“其他问题”#1?
    【解决方案2】:

    作为单个函数的通用 Hoare 分区代码。使用中间值作为主元可以避免已排序或反向排序数据的最坏情况 O(n^2) 时间复杂度。除了 a[hi] 之外的任何元素都可以用作此特定代码的枢轴。不需要对索引进行边界检查,因为最坏的情况是,到达枢轴将停止初始内部循环,并且任何交换都将允许内部循环重复而不进行边界检查。

        public static void qsort(int[] a, int lo, int hi)
        {
            if(lo >= hi)
                return;
            int  p = a[lo+(hi-lo)/2];
            int  i = lo-1;
            int  j = hi+1;
            int t;
            while(true){
                while(a[++i] < p);
                while(a[--j] > p);
                if(i >= j)
                    break;
                t     = a[i];
                a[i] = a[j];
                a[j] = t;
            }
            qsort(a, lo, j);
            qsort(a, j+1, hi);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-27
      • 2020-06-17
      • 2019-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-07
      • 2020-01-08
      相关资源
      最近更新 更多