简体   繁体   English

在java中解决我的快速排序算法?

[英]trouble-shooting my quicksort algorithm in java?

while trouble-shooting my method for quicksort algorithm, this problem popped up; 在解决我的quicksort算法方法时出现问题,这个问题突然出现了;

consider this simple example of printing an array elements individually: 考虑这个单独打印数组元素的简单示例:

public static void print1(int[] arr, int start, int end){
        for (int k = start; k<end;k++){
            System.out.println(arr[k]);
        }
    }
    public static void print2(int[] arr, int start, int end){
        for (int k=start; k<=end;k++){
            System.out.println(arr[k]);
        }
    }

In the main, if I call: 总的来说,如果我打电话:

public static void main(String[] args) {
        int[] data2 = new int[]{10,11,9,7,5};
       print1(data2,0,data2.length);
       System.out.println("___________");
       print2(data2,0,data2.length-1);
    }

both prints the same content, which is well and good; 两者都打印相同的内容,这是好的和好的; (Note, I pass data2.length and data2.length-1 as arguments to my print1 and print2 methods and the for-loop in each method changes accordingly) (注意,我将data2.lengthdata2.length-1作为参数传递给我的print1print2方法,并且每个方法中的for-loop相应地改变)

Now comes the problem with quicksort regime: consider this code: 现在出现了快速排序制度的问题:考虑以下代码:

public static void quickSort2(int[] arr, int i, int j){
        if (i<j){
            int part =partition(arr, i, j);
            quickSort2(arr, i, part-1);
            quickSort2(arr, part+1, j); 
        }
    }

public static int partition(int[] arr, int start, int end){
        int pivot = arr[start];
        int i = start;
        for (int j = start+1;j<=end;j++){ // ******
            if (arr[j]<pivot){
                    i++;
                    int temp=arr[i];
                    arr[i]=arr[j];
                    arr[j]=temp;
            }
        }
        arr[start]=arr[i];
        arr[i]=pivot;
        return i;
    }

In the main; 在主;

public static void main(String[] args) {
       //int[] data = new int[]{5,10,1,9,4,4,8,3,6,2,7,4};
        int[] data = new int[]{3,4,1,2};
        int[] data2 = new int[]{10,11,9,7,5};
       System.out.print("Unsorted array data ");
       display(data);
       System.out.print("\nUnsorted array data2 :");
       display(data2);
       quickSort2(data, 0, data.length-1);
       System.out.println("_____________");
       quickSort2(data2,0,data2.length-1);
       System.out.print("\nSorted array data: ");
       display(data);
       System.out.print("\nSorted array data2:");
       display(data2);
}

works fine and good; 工作得很好,很好; now If I change the call to quickSort(data, 0, data.length) and change the for-loop line (marked in the code with ******* ) to for (int j = start+1;j<end;j++) , I get entirely different result: ie: first two elements are not sorted, but rest rest of it is sorted. now如果我将调用更改为quickSort(data, 0, data.length)并将for-loop行(在代码中标记为******* )更改for (int j = start+1;j<end;j++) ,我得到了完全不同的结果:即:前两个元素没有排序,但其余的元素被排序。 I get 我明白了

Sorted array data: [2, 1, 3, 4]

Sorted array data2:[5, 9, 7, 10, 11]

I need some help 我需要协助

After a quick look, I think there are two separate bugs - I discovered one for each of your quickSort2() calls in 'main`. 快速浏览后,我认为有两个独立的错误 - 我在'main`中为每个quickSort2()调用发现了一个错误。 Each was triggered because of the nature of the array you were trying to sort. 由于您尝试排序的数组的性质,每个都被触发。

Bug 1: at line 9 in your main, you call: 错误1:在您的主要第9行,您致电:

quickSort(data, 0, data.length);

So, this is when you try to quickSort() {3,4,1,2}. 所以,这是当你尝试quickSort() {3,4,1,2}时。 The error occurs on the first recursive call to quickSort2() , the exact call with its arguments being 在对quickSort2()的第一次递归调用时发生错误,其参数的确切调用是

quickSort2({2,1,3,4}, 0, 1);

which then calls partition() with the same parameters 然后使用相同的参数调用partition()

partition({2,1,3,4}, 0, 1);

This is where the error occurs. 这是发生错误的地方。 Look at the terms of your for-loop : 看看你的for-loop术语:

 for (int j = start+1; j< end;j++)

j will immediately be set to 1. End already equals 1. 1 < 1 is false, so the loop never triggers. j将立即设置为1. End已等于1. 1 < 1为false,因此循环永远不会触发。 Solution: just get rid of the +1 when assigning j a value. 解决方案:在为j赋值时,只需删除+1。 Your loop will look like this: 你的循环将如下所示:

for (int j = start; j< end;j++) 

The initial case where i == j is will never trigger the if-statement so I believe it should be fine. i == j的初始情况永远不会触发if-statement所以我认为应该没问题。

Bug 2: at line 11 in main, you call: 错误2:在主要的第11行,你打电话:

quickSort2(data2,0,data2.length-1);

The eventual error occurs at the same place as it did in the first bug - in partition() during the first recursive call to quickSort2() , which ends up having these parameters: 发生最终误差在同一个地方,因为它在该第一故障没有-在partition()的第一递归调用期间quickSort2()这最终具有以下参数:

partition({5,9,7,10,11}, 0, 2);

The if-statement in your for-loop is never triggered, because 5 is the pivot and 9 and 7 are both larger. 永远不会触发for-loopif-statement ,因为5是数据透视表,9和7都是较大的。 Thus i returns as zero, and this half of the array is never sorted again. 因此, i返回零,这个数组的一半永远不会再次排序。 As for a quick solution to this, I can't say there is one I can readily think of. 至于快速解决这个问题,我不能说有一个我能想到的。 You'd have to alter the logic of your sort. 你必须改变你的逻辑。

Some notes/pointers that may help you out. 一些可能会帮助你的笔记/指针。

Quicksort algorithms, in general, aren't typically called all the way down the array. 通常,Quicksort算法通常不会在数组中一直调用。 There is usually a base case in which sorting switches over to a different algorithm. 通常存在一种基本情况,其中排序切换到不同的算法。 Example, you have only 5 objects left to sort on this call. 例如,您只有5个对象可以对此调用进行排序。 That's not that many, so let's switch to something simpler, such as insertion sort. 那不是那么多,所以让我们切换到更简单的东西,比如插入排序。 Even though insertion sort is generally less efficient on large collections, when you get down to only having 5 or fewer objects to rearrange, it's not such a big deal. 尽管插入排序通常对大型集合的效率较低,但当您只需要重新排列5个或更少的对象时,这并不是什么大问题。

Quicksort implementations also typically don't call the very first object in the collection the pivot. Quicksort实现通常也不会将集合中的第一个对象称为pivot。 This is a bad method in general, as what if your list was already sorted, or reverse sorted? 这通常是一种糟糕的方法,如果您的列表已经排序或反向排序,该怎么办? The time complexity would be pretty mediocre ( O(N 2 )). 时间复杂度将非常平庸(O(N 2 ))。 Instead, there is a method called "Median-Of-Three", which not only just might solve the second bug you have, but give you a better time-complexity. 相反,有一种称为“三个中位数”的方法,它不仅可以解决您的第二个错误,而且可以为您提供更好的时间复杂性。

While calling the first partition in your quicksort function you will also have to change: 在快速排序功能中调用第一个分区时,您还必须更改:

quickSort2(arr, i, part-1);

to

quickSort2(arr, i, part);

This is because you are not using the last index (end). 这是因为您没有使用最后一个索引(结束)。 Hence your quicksort will be incomplete since you are not placing the last element before the pivot even if it has a lower value than pivot. 因此,您的快速排序将不完整,因为您没有将最后一个元素放在枢轴之前,即使它的值低于数据透视表。

quickSort(data, 0, data.length-1);
//...
quickSort2(data2,0,data2.length-1);

I see the two quickSort is not the same, maybe you have a another function named quickSort you forget?Or just wrong written? 我看到两个quickSort是不一样的,也许你有另一个名为quickSort的函数你忘了吗?或者只是写错了?

had a look at the code added some prints and found out, that after your modification is in the second run your pivot element 0, what is obviously wrong. 看看代码中添加了一些打印件并发现,经过修改后,在第二次运行你的pivot元素0时,显然是错误的。 I added some numbers to be the unsorted array data this: 3 4 1 2 7 5 6 我添加了一些数字作为未排序的数组数据:3 4 1 2 7 5 6

3 4 1 2 7 5 6 3 4 1 2 7 5 6

pivot: 2 枢轴:2
2 1 3 4 7 5 6 2 1 3 4 7 5 6

pivot: 0 pivot:0
2 1 3 4 7 5 6 2 1 3 4 7 5 6

2 1 3 4 7 5 6 2 1 3 4 7 5 6

2 1 3 4 7 5 6 2 1 3 4 7 5 6

pivot: 3 枢轴:3
2 1 3 4 7 5 6 2 1 3 4 7 5 6

2 1 3 4 7 5 6 2 1 3 4 7 5 6

pivot: 6 枢轴:6
2 1 3 4 6 5 7 2 1 3 4 6 5 7

pivot: 4 枢轴:4
2 1 3 4 6 5 7 2 1 3 4 6 5 7

2 1 3 4 6 5 7 2 1 3 4 6 5 7

2 1 3 4 6 5 7 2 1 3 4 6 5 7

Sorted array data: 2 1 3 4 6 5 7 排序数组数据:2 1 3 4 6 5 7

package quicksort;

public class Quicksort {

public static void main(String[] args) {
        int[] data = new int[]{3,4,1,2,7,5,6};
       System.out.print("Unsorted array data:\n");
       display(data);
       quickSort2(data,0,data.length);
       System.out.print("\nSorted array data:\n");
       display(data);
}

public static void quickSort2(int[] arr, int i, int j){
    display(arr);
    if (i<j){
        int part =partition(arr, i, j);
        quickSort2(arr, i, part-1);
        quickSort2(arr, part+1, j); 
    }
}

public static int partition(int[] arr, int start, int end){
    int pivot = arr[start];
    //System.out.println(pivot);
    int i = start;
    int temp;
    for (int j = start;j<end;j++){ // ******
        if (arr[j]<pivot){
                i++;
                temp=arr[i];
                arr[i]=arr[j];
                arr[j]=temp;
        }
    }
    arr[start]=arr[i];
    arr[i]=pivot;
    System.out.println("pivot: "+i);
    return i;
}

public static void display(int[] data){
for(int i=0;i<data.length;i++){
    System.out.print(data[i]+" ");
}
System.out.println("\n");
}}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM