使用 HoarePartition 的快速排序得到不正确的输出

Quicksort using HoarePartition got incorrect output

提问人:ian 提问时间:5/29/2022 最后编辑:dani-vtaian 更新时间:5/29/2022 访问量:45

问:

我的作业要求我实现与教科书中的伪代码完全相同的 Quicksort 算法: 它指定使用 HoarePartition 进行分区。

pivot <- A[leftMost]
i <- leftMost; j <- rightMost+1

这是我的代码:

import java.util.Arrays;
public class Main{
   public static void main(String args[]){
      int[] array1 = {10, 4, 2, 8, 7, 3, 5, 9, 6, 1};
      int n1 = array1.length;
      System.out.print("Before sorting is: ");
      System.out.println(Arrays.toString(array1));
      System.out.printf("After sorting is: ");
      Quicksort(array1, 0, n1 -1);
      System.out.println(Arrays.toString(array1));
   } //end main

   public static void Quicksort(int[]array, int start, int end){
      if(start<end){
         int pivot = HoarePartition(array, start, end);
         Quicksort(array, start, pivot-1);
         Quicksort(array, pivot+1, end);
      }
   } //end Quicksort()

   public static int HoarePartition(int[] array, int start, int end){
      int pivot = array[start];
      int i = start;
      int j = end +1;
      while(true){
      while(array[i] < pivot)
         i++;
      do{j--}while(array[j] > pivot)

      if(i <= j)
         return j;
      int temp = array[i];
      array[i] = array[j];
      array[j] = temp;
      } //end while
   } //end HoarePartition()

输出为:

Before sorting is: [10, 4, 2, 8, 7, 3, 5, 9, 6, 1]
After sorting is: [1, 3, 2, 5, 7, 4, 8, 9, 6, 10]

显然,它没有正确排序,我一直在一遍又一遍地思考,但仍然不知道我的算法的哪一部分是错误的......

java 算法 输出 quicksort 分区

评论


答:

1赞 rcgldr 5/29/2022 #1

两个递归调用应为:

         Quicksort(array, start, pivot);   // (not pivot-1)
         Quicksort(array, pivot+1, end);

经典霍尔隔断

      // ...
      int i = start-1;
      int j = end +1;
      while(true){
          while(array[++i] < pivot);
          while(array[--j] > pivot);
      // ...
1赞 dani-vta 5/29/2022 #2

您编写的代码存在一些问题。

  • 在 的第一次递归调用中,应包含透视绑定,而不是传递 。quicksortpivot-1

  • 在您的方法中,您忘记移动索引并在交换后移动索引。HoarePartitionij

  • 返回条件不仅应检查两个索引是否相交,还应检查它们是否相互交叉ijif (i >= j) return j;

  • 最里面的循环应该写成两个循环,而不是 a 和 awhilewhiledo-while

public static void Quicksort(int[] array, int start, int end) {
    if (start < end) {
        int pivot = HoarePartition(array, start, end);
        Quicksort(array, start, pivot);
        Quicksort(array, pivot + 1, end);
    }
}

public static int HoarePartition(int[] array, int start, int end) {
    int pivot = array[start];
    int i = start;
    int j = end;

    //Iterating until the left index crosses the right index
    while (true) {

        //Looking for an element on the left side greater than the pivot
        while (array[i] < pivot) i++;
        
        //Looking for an element on the right side lower than the pivot
        while (array[j] > pivot) j--;

        //If the left index passed the right index, then there is no element on the left side greater then the pivot or a lower element on the right side
        if (i >= j) return j;

        //Swapping the elements greater than the pivot (left) and lower than the pivot (right) (the index haven't met yet)
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;

        i++;
        j--;
    }
}
输出
Before sorting is: [10, 4, 2, 8, 7, 3, 5, 9, 6, 1]
After sorting is: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

评论

0赞 ian 5/29/2022
谢谢你,对不起,先生,我太专注于思考我的新问题,忘记及时回复和投票你的答案,我的错误,你的答案真的很有帮助!
0赞 ian 5/29/2022 #3

谢谢!我发现了我犯的错误: 我把初始值设置错了,调整了i、j和我输入的循环后,它就可以正常工作了!HoarePartition()

    public static int HoarePartition(int[] array, int start, int end){
    int pivot = array[start];
    int i = start -1 ;
    int j = end + 1;

    while(true){
        do{i++;}while(array[i] < pivot);
        do{j--;}while(array[j] > pivot);
        
        if(i>=j)
            return j;
        /*swap(array[i], array[j])*/
        swapIJ(array, i, j);
    } //end while
} //end HoarePartition()