在解决quicksort
算法的问题时遇到了问题,这个问题突然出现了;
考虑这个单独打印数组元素的简单示例:
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]);
}
}
主要是,如果我打电话:
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);
}
两者都打印相同的内容,这是好的和好的;
(注意,我将data2.length
和data2.length-1
作为参数传递给我的print1
和print2
方法,并且每种方法中的for-loop
都会相应更改。
现在出现了快速排序制度的问题: 考虑这段代码:
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;
}
在主;
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);
}
工作得很好;
现在如果我将呼叫更改为quickSort(data, 0, data.length)
并将for-loop
行(在代码中标有*******
)更改为for (int j = start+1;j<end;j++)
,我会得到完全不同的结果:
即:前两个元素未排序,但其余的元素已排序。
我得到了
Sorted array data: [2, 1, 3, 4]
Sorted array data2:[5, 9, 7, 10, 11]
我需要一些帮助
答案 0 :(得分:1)
快速浏览后,我认为有两个不同的错误 - 我在'main`中为每个quickSort2()
调用发现了一个错误。由于您尝试排序的数组的性质,每个都被触发了。
错误1:在您的主要第9行,您致电:
quickSort(data, 0, data.length);
所以,这是当你尝试quickSort()
{3,4,1,2}时。第一次递归调用quickSort2()
时发生错误,其参数的确切调用为
quickSort2({2,1,3,4}, 0, 1);
然后使用相同的参数调用partition()
partition({2,1,3,4}, 0, 1);
这是发生错误的地方。查看for-loop
的条款:
for (int j = start+1; j< end;j++)
j
将立即设置为1. End已等于1. 1 < 1
为false,因此循环永远不会触发。
解决方案:在为j
赋值时,只需删除+1。你的循环将如下所示:
for (int j = start; j< end;j++)
i == j
的初始情况永远不会触发if-statement
因此我认为应该没问题。
错误2:在主要的第11行,您致电:
quickSort2(data2,0,data2.length-1);
最终错误发生在与第一个错误相同的地方 - 在partition()
的第一次递归调用期间quickSort2()
,最终有这些参数:
partition({5,9,7,10,11}, 0, 2);
if-statement
中的for-loop
永远不会被触发,因为5是枢轴,9和7都是较大的。因此i
返回零,并且该数组的这一半永远不会再次排序。
至于快速解决这个问题,我不能说有一个我能想到的。你必须改变你的逻辑。
可能会帮助您的一些注释/指示。
一般来说,Quicksort算法通常不会在数组中一直调用。通常存在一种基本情况,其中排序切换到不同的算法。例如,您只有5个对象可以对此调用进行排序。那不是那么多,所以让我们切换到更简单的东西,比如插入排序。尽管插入排序通常对大型集合的效率较低,但当您只需要重新排列5个或更少的对象时,这并不是什么大问题。
Quicksort实现通常也不会调用集合中的第一个对象。这通常是一种糟糕的方法,如果您的列表已经排序或反向排序,该怎么办?时间复杂度相当平庸(O(N 2 ))。相反,有一种称为“三个中位数”的方法,它不仅可以解决你的第二个错误,而且可以为你提供更好的时间复杂性。
答案 1 :(得分:1)
在快速排序功能中调用第一个分区时,您还必须更改:
quickSort2(arr, i, part-1);
到
quickSort2(arr, i, part);
这是因为您没有使用最后一个索引(结束)。因此,您的快速排序将不完整,因为您没有将最后一个元素放在枢轴之前,即使它的值比枢轴值低。
答案 2 :(得分:0)
quickSort(data, 0, data.length-1);
//...
quickSort2(data2,0,data2.length-1);
我看到两个quickSort是不一样的,也许你有另一个名为quickSort的函数你忘记了吗?或者只是写错了?
答案 3 :(得分:0)
3 4 1 2 7 5 6
枢轴:2
2 1 3 4 7 5 6
枢轴:0
2 1 3 4 7 5 6
2 1 3 4 7 5 6
2 1 3 4 7 5 6
枢轴:3
2 1 3 4 7 5 6
2 1 3 4 7 5 6
枢轴:6
2 1 3 4 6 5 7
枢轴: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
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");
}}