【发布时间】:2016-11-03 12:34:37
【问题描述】:
我正在学习 C,并尝试了递归快速排序算法。在较小的输入尺寸下,它按预期工作;对于随机生成的数组,所有测试大小(最多 100,000)都没有问题。对于降序数组,它以某种数组大小 (32,506) 以某种方式中断(Windows 给我一条消息,程序已停止工作)。我的代码中是否有任何错误(例如任何错误的内存分配 - 我不确定我是否正确)或者 C 在递归调用或其他方面是否有限制?
编辑: 我知道我的 Quicksort 实现是相当幼稚的,并且它在这种输入中表现得非常糟糕,但我没想到它会崩溃。
我在 Windows 10 的命令提示符下使用 GCC 和 MinGW。我不确定如何找出究竟发生了什么,因为尽管 Windows 告诉我我的程序已停止,但我并没有真正收到任何指定的错误消息工作。
#include <stdio.h>
#include <stdlib.h>
int partition(int *a, int lo, int hi) {
int i = lo; int j = hi+1; int v,t;
v = a[lo]; //partition element
while (1) {
while (a[++i] < v) {if (i == hi) break;}
while (v < a[--j]) {if (j == lo) break;}
if (i >= j) break;
t = a[j]; a[j] = a[i]; a[i]= t; //swap
}
t = a[lo]; a[lo] = a[j]; a[j]= t;//swap
return j;
}
void quicksort(int a[], int lo, int hi) {
int j;
if (hi <= lo) return;
j = partition(a, lo, hi);
quicksort(a, lo, j-1);
quicksort(a, j+1, hi);
}
int main() {
int len;
for (len = 32000;len < 40000;len+=100) {
printf("New Arr with len = %d\n",len);
int *arr;
arr = (int*) calloc(len,sizeof(int));
int j;
//create descending Array
for (j = 0; j < len; ++j) {
arr[j] = len-j;
}
printf("start sorting\n");
quicksort(arr,0,len-1);
free(arr);
}
}
【问题讨论】:
-
你用的是什么编译器?程序停止时错误是否提到堆栈溢出?之所以问,是因为递归程序的一个典型问题是堆栈溢出。
-
calloc可能会失败。 -
降序数组是带有第一个元素枢轴的“升序”快速排序的最坏情况输入;这是它具有二次复杂性的地方,你很可能递归太深。您需要一种不同的枢轴选择方法。
-
如果@molbdnilo 确实认为递归深度是问题所在(这很合理),那么改变枢轴选择的替代方法是切换到半递归算法。也就是说,不是递归地对两个子分区进行排序,而是递归地对较小的子分区进行排序,而只是循环回对较大的子分区进行排序。在不利的情况下,它仍然会有二次运行时间,但在所有情况下都会有对数递归深度和开销。