我正在进行一项我们应该实现quicksort的任务,第一个元素是pivot。我的代码中存在一个小错误,导致列表元素(用于测试)排序不正确。输出应 1 3 7 8 9 10 但最终 1 7 3 8 9 10 (7和3应切换位置)。我怀疑错误可能在第15-26行之间,但我似乎无法找到它,尽管许多人试图修复它。
任何人都可以看到任何错误?
(在第一个while循环中,我尝试过i< = j而不是i< j但这似乎导致无限循环。已经看到其他示例中的工作但不知道为什么在我的情况下,这不起作用)
public static void quickSort(int[] a, int lo, int hi) {
if (!(hi > lo)) {
return;
}
int pivot = a[lo];
int i = lo;
int j = hi + 1;
int temp;
i++;
j--;
while (i < j) {
while (a[i] < pivot) {
i++;
}
while (a[j] > pivot) {
j--;
}
if (i <= j) {
switchPlace(a, i, j);
i++;
j--;
}
}
switchPlace(a, lo, j);
quickSort(a, lo, j - 1);
quickSort(a, j + 1, hi);
}
public static void switchPlace(int[] a, int x, int y) {
int temp = a[x];
a[x] = a[y];
a[y] = temp;
}
public static void printList(int[] a) {
String res = "";
for (int i = 0; i < a.length; i++) {
res += a[i] + " ";
}
System.out.println(res);
}
public static void main(String[] args) {
int[] a = { 9, 3, 10, 1, 8, 7 };
quickSort(a, 0, a.length - 1);
printList(a);
}
感谢任何帮助!
答案 0 :(得分:1)
我将在这里描述一种调试此类算法的简单方法,包括:
第一点涉及详细了解代码尝试做什么,而第二点则意味着使用某些工具进行检查。 &#34;工具&#34;在这个特定的答案中举例说明的是使用print
消息,但一般来说它可能是其他东西(例如一个步调试器)。
qsort算法的主要操作是围绕枢轴交换元素,以便较小的值在之前,较大的值在其之后。
此过程适用于lo
和hi
索引之间的各种子序列。
现在让我们检查每个子序列是否正确完成此操作。 为此,我们可以显示初始子序列以及交换发生后的子序列,以便我们可以手动检查此操作是否正确执行。
我们可以在交换部分之前使用类似这样的代码:
System.out.print("before: ");
for (int k = lo; k <= hi; k++) {
System.out.print(a[k] + ", ");
}
System.out.println();
交换部分后的类似内容:
System.out.print("after: ");
for (int k = lo; k <= hi; k++) {
System.out.print(a[k]);
if (k == j) {
System.out.print(" (pivot)");
}
System.out.print(", ");
}
System.out.println();
System.out.println();
示例中序列的输出如下所示:
之前:9,3,10,1,8,7,
之后:8,3,7,1,9(枢轴),10,之前:8,3,7,1,
之后:1,3,7,8(支点),之前:1,3,7,
之后:1(枢轴),3,7,之前:3,7,
之后:7,3(枢轴),
我们可以看到长度为2的最后一个子序列出现问题。 优点是我们现在只能专注于这种情况并准确理解会发生什么。
例如,我们甚至可以直接传递给算法int[] a = {3, 7};
。
在仔细考虑在这种情况下会发生什么后,我们可以看到问题包括j
索引没有跳过大于枢轴的元素,因为while (i < j)
在这种情况下立即退出(我们从一开始就有i == j)。有多种解决方案,似乎有效的方法是在相应条件下使用while (i <= j)
- 尽管您明确提到它可能会导致无限循环,但实际上似乎并非如此。
以下是包含此修复程序的代码(以及上述其他print
):
public static void quickSort(int[] a, int lo, int hi) {
if (!(hi > lo)) {
return;
}
int pivot = a[lo];
int i = lo;
int j = hi + 1;
int temp;
i++;
j--;
System.out.print("before: ");
for (int k = lo; k <= hi; k++) {
System.out.print(a[k] + ", ");
}
System.out.println();
while (i <= j) {
while (a[i] < pivot) {
i++;
}
while (a[j] > pivot) {
j--;
}
if (i <= j) {
switchPlace(a, i, j);
i++;
j--;
}
}
switchPlace(a, lo, j);
System.out.print("after: ");
for (int k = lo; k <= hi; k++) {
System.out.print(a[k]);
if (k == j) {
System.out.print(" (pivot)");
}
System.out.print(", ");
}
System.out.println();
System.out.println();
quickSort(a, lo, j - 1);
quickSort(a, j + 1, hi);
}
public static void switchPlace(int[] a, int x, int y) {
int temp = a[x];
a[x] = a[y];
a[y] = temp;
}
public static void printList(int[] a) {
String res = "";
for (int i = 0; i < a.length; i++) {
res += a[i] + " ";
}
System.out.println(res);
}
public static void main(String[] args) {
//int[] a = {3, 7};
//int[] a = { 9, 3, 10, 1, 8, 7 };
int[] a = {24, 2 , 45 ,20 ,56 ,75 ,2 ,56 ,99 ,53 ,12};
quickSort(a, 0, a.length - 1);
printList(a);
}
答案 1 :(得分:0)
这可以解决您的问题:
public static void quickSort(int[] a, int lo, int hi) {
if (!(hi > lo)) {
return;
}
int pivot = a[lo];
int i = lo - 1;
int j = hi + 1;
int temp;
while (i < j) {
do {
i++;
} while (a[i] < pivot);
do {
j--;
} while (a[j] > pivot);
if (i < j) {
switchPlace(a, i, j);
i++;
j--;
}
}
switchPlace(a, lo, j);
quickSort(a, lo, j - 1);
quickSort(a, j + 1, hi);
}