SIGSEGV信号在排序具有大量元素的数组时

时间:2016-03-31 23:13:34

标签: c sorting

我有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;
}

1 个答案:

答案 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