我有100000个元素(整数),我想用quicksort对它进行排序。当我用随机数填充这个数组时,它可以工作,但当我像这样填充它时
for(i=0; i<size/2; i++)
{
tablica[i]= i;
}
for(i=size/2; i<size; i++)
{
tablica[i]=size-i-1;
}
我收到SIGSEGV信号,我的应用程序崩溃了。我确定我的快速排序功能很好。当我用随机,升序或降序数字填充此数组时,一切都可以工作,即使数组中有更多元素(如100000000)。我将这样的数组理解为:
int *tablica = calloc(size, sizeof (int));
这是我的快速排序代码
void quicksort(int tab[], int lewy, int prawy)
{
int pivot = tab[(prawy+lewy)/2];
int p = prawy;
int l = lewy;
do
{
while (tab[l] < pivot)
{
l++;
}
while (tab[p] > pivot)
{
p--;
}
if (l <= p)
{
int temp = tab[l];
tab[l] = tab[p];
tab[p] = temp;
l++; p--;
}
} while (l <= p);
if(p>lewy)
{
quicksort(tab,lewy,p);
}
if(l<prawy)
{
quicksort(tab,l,prawy);
}
}
主要功能的例子
int main()
{
srand(time(NULL));
int i;
int *tablica;
float start, stop, czas;
tablica = calloc(size, sizeof (int));
int *tab = calloc(size, sizeof (int));
for(i=0; i<size/2; i++)
{
tablica[i]= i;
}
for(i=size/2; i<size; i++)
{
tablica[i]=size-i-1;
}
start = clock();
quicksort(tablica,0,size-1);
stop = clock();
czas = (stop-start)/CLOCKS_PER_SEC;
free(tablica);
free(tab);
return 0;
}
答案 0 :(得分:2)
我确信我的快速排序功能很好。
它可能是递归的,不是吗?您看到的内容很可能是堆栈溢出,这是由于嵌套过多的递归引起的。在这方面,快速排序尤其薄弱,具体取决于枢轴的选择和值的分布。
示例:大小为8
的数组,按您指定的方式填充:
0 1 2 3 3 2 1 0
让我们将第一个值作为枢轴,因此在分配后我们可能得到:
0|0|1 2 3 3 2 1
看看发生了什么?我们只设法在左侧部分输入一个数字。对正确的部分进行快速排序不会更好:
1 2 3 3 2 1
我们将第一个像以前一样作为枢轴并进行分区:
1|1|2 3 3 2
等等。
在每个步骤中,您只需要排序2个元素(枢轴和左侧部分的单个元素)...因此,对于100000个数字的数组,您需要50000个步骤才能对其进行排序。每个步骤都是递归调用。这对于(调用)堆栈来说太过分了。
为了减轻发生此类模式的危险,您应该调整choice of your pivot value。
从添加的快速排序代码:
int pivot = tab[(prawy+lewy)/2];
您总是选择正在排序范围中间的值。在第一次迭代中,这将是size/2 -1
,并且因为没有大于该值的值(由于数组的初始化方式),正确的部分将(几乎)为空,从而产生与上面所示类似的模式。
提示:只需尝试使用较小尺寸的代码(例如8
),并在每次调用时打印快速排序所使用的数组:
0, 1, 2, 3, 3, 2, 1, 0 // (1)
0, 1, 2, 0, 1, 2
0, 1, 2, 0, 1
0, 1, 1, 0 // (2)
0, 0 // right part from (2)
3, 3 // right part from (1)
(Ideone)