#include <stdio.h>
int Partition (int * A, int p, int r)
{
printf("PARTITION\n");
int x=0;
x=A[r];
int i=p-1, j=r+1;
int temp;
int k=0;
while(1)
{
printf("\tLOOP\n");
do
{
j=j-1;
} while(A[j]>x) ;
do
{
i=i+1;
} while(A[i]<x);
if (i<j)
{
temp=A[i];
A[i]=A[j];
A[j]=temp;
}
else
{
printf ("ARRAY: ");
for (k=p; k<=r; k++)
printf ("%d,",A[k]);
printf ("\nRETURNING : %d \n", j);
return j;
}
}
}
void QuickSort(int * A, int p, int r)
{
int q;
if (p<r)
{
q = Partition (A,p,r);
QuickSort(A,p,q);
QuickSort(A,q+1,r);
}
}
int main()
{
int A[9] = {9,2,4,1,7,8,3,5,6};
int i;
QuickSort(A,0,8);
for (i=0;i<=8;i++)
{
printf("%d ", A[i]);
}
return 0;
}
在GDB上花了一个小时后,我把这个程序的问题缩小到了这个范围:
我的数组的索引从0到9。
它首先被分区为0-5和6-9。
然后0-5部分被分区为0-2和3-5
然后0-2部分被分区为0-0和1-2
现在由于if (p<r)
条件而跳过0-0部分,但是程序为另一部分调用分区(A,1,2)。现在这里是程序卡住的地方,它继续一次又一次地调用分区(A,1,2),因为它一直返回'2'作为枢轴索引。
为什么会这样?我无法理解逻辑上我在程序中出错的地方,我遵循了在互联网上各个地方给出的确切伪代码。
编辑:我能够在if (i<=j)
中使用if (i<j)
代替Partition
来解决问题。它迫使j
再次递减,但这只是因为我有幸选择了do while
而不是while
。我仍然很困惑为什么直接实现Quicksort伪代码不起作用。
答案 0 :(得分:1)
你的代码中犯了很多错误。
QuickSort(A,p,q);
是QuickSort(A,p,q-1)
;
int i=p-1, j=r+1;
不是必需的。
您的partition()
需要一个额外的变量才能保留支点。
while(A[i]<x) ;
应为while(A[i] <= x[piv] && i<r )
;
在你的程序中,你错过了一个算法步骤,其中数据库中的数组变量与你的最后一个数组变量交换,没有这个关键步骤,没有进行排序。
这是您的计划,并进行了更正
#include <stdio.h>
int Partition (int *A, int p, int r)
{
printf("PARTITION\n");
int i=p, j=r ,piv=p ;
int temp;
while(i<j)
{
printf("\tLOOP\n");
while(A[i] <= A[piv] && i<r)
i++;
while(A[j]>A[piv])
j--;
if (i<j)
{
temp=A[i];
A[i]=A[j];
A[j]=temp;
}
}
/*Crucial step that you happen to miss*/
temp=A[piv];
A[piv]=A[j];
A[j]=temp;
return j;
}
void QuickSort(int *A, int p, int r)
{
int q;
if (p<r)
{
q = Partition (A,p,r);
QuickSort(A,p,q-1);
QuickSort(A,q+1,r);
}
}
int main()
{
int A[9] = {9,2,4,1,7,8,3,5,6};
int i;
QuickSort(A,0,8);
for (i=0;i<=8;i++)
{
printf("%d ", A[i]);
}
return 0;
}