任何人都可以通过下面的快速排序实现发现问题吗?它似乎在具有10个以上元素的数组上失败。
void swap(int *p1, int *p2)
{
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
void generateRandom(int arr[], int size)
{
srand(time(NULL));
int i;
for (i = 0; i < size; i++)
{
arr[i] = rand() % 100;
}
}
int partition(int arr[], int start, int end)
{
int i = start, j = end;
int pivot = arr[start];
for (;;)
{
for (; arr[i] < pivot; i++);
for (; arr[j] > pivot; j--);
if (i < j)
{
swap(&arr[i], &arr[j]);
}
else
{
return j;
}
}
}
void quickSort(int arr[], int start, int end)
{
int part;
if (start < end)
{
part = partition(arr, start, end);
quickSort(arr, start, part);
quickSort(arr, part + 1, end);
}
}
int main()
{
generateRandom(arr, 100);
for (i = 0; i < 100; i++)
{
printf("%d ", arr[i]);
}
printf("\n\n");
quickSort(arr, 0, 99);
for (i = 0; i < 100; i++)
{
printf("%d ", arr[i]);
}
printf("\n\n");
return 0;
}
答案 0 :(得分:2)
首先,您的代码无法编译。当我进行更正以使其编译时(在main中添加stdio.h和arr和i的定义),它会无限循环,如果分区以枢轴开始和结束,它将执行此操作。您需要在比较之前而不是之后递增和递减。您可以通过从i = start-1和j = end + 1开始并将内部循环更改为先增加或减少来实现,或者您可以将它们保留为原样并在交换后执行i ++和j--我做到了,排序有效。
请注意,对于已排序的数组,您的数据透视选择较差;你真的应该选择3或甚至9值的中位数。
P.S。其他理想的优化:1)切换到小分区的插入排序 - 最佳截止点取决于机器。另一种方法是不对低于特定大小的分区进行排序,然后在快速排序完成后对整个阵列执行插入排序。如果仔细进行,也可以使用heapsort而不是插入排序; google introsort。 2)quicksort做两个递归调用;通过设置start = part + 1和循环来消除第二个。 3)首先快速分配较大的分区,避免堆栈溢出的可能性。 4)通过使用显式堆栈消除第一次递归调用。 5)内联swap()和分区()。 6)不要打扰其中任何一个,只需调用qsort库例程。 : - )
答案 1 :(得分:0)
我有同样的问题,
但是我将while循环更改为do..while
并且它有效。
这是我现在的新代码。
int partition(int a[], int lo, int hi) {
int v = a[lo], i = lo, j = hi;
do {
do {
i++;
} while(a[i] < v) ;
do {
j--;
}while(a[j] > v) ;
if(i < j) interchange(&a[i], &a[j]);
}while(i < j);
interchange(&a[lo], &a[j]);
return j;
}