大小为 500000 的部分排序数组的快速排序分段错误
Posted
技术标签:
【中文标题】大小为 500000 的部分排序数组的快速排序分段错误【英文标题】:quicksort segmentation fault for partly sorted arrays of size 500000 【发布时间】:2014-04-08 13:21:15 【问题描述】:我必须为按 25%、50%、75%、95%、99% 和 99.7% 排序以及随机填充的数组编写和测试快速排序。当我使用大小为 500k 的数组时,我的程序通过随机数组和 25% 的排序数组没有任何问题(但 25% 的排序数组需要 158 秒),但对于 50% 的排序数组,它会引发分段错误和“进程返回 139(0x8b)。 " 对于较小的数组,例如 100k,即使已排序,一切正常。 我如何生成我的数组(我知道不需要参数“zakres”):
void generujTablice(int zakres,float sorted, int size_of_array)
Tablica = new int[size_of_array]; //allocating space for array
if(sorted == -1) //when array have to be sorted, but inverted
for(int i=0;i<size_of_array;i++)
Tablica[i] = size_of_array-i;
else
for(int i=0;i<sorted * size_of_array;i++) //example: if sorted is 0.25 array have to be sorted in 25% from beginning
Tablica[i] = i;
for(int i=sorted * size_of_array;i<size_of_array;i++) //rest of array is filled randomly but values have to be bigger than these in sorted part of array
Tablica[i] = rand()%int(size_of_array)+sorted * size_of_array;
还有我的快速排序: (注意:我选择第一个元素作为枢轴,因为我想检查算法的最坏情况。我已经评论了将第一个元素与另一个元素随机混合的行,当我使用这个交换时,一切正常并且非常非常快. lewy == left, prawy == right)
#include <algorithm>
void quicksort(int * Tablica, int lewy, int prawy)
if(lewy<prawy)
//swap( Tablica[lewy], Tablica[rand()%(prawy-lewy)+lewy]);
int x = Tablica[lewy];
int i = lewy, j = prawy;
do
while(Tablica[i] < x ) i++;
while(Tablica[j] > x ) j--;
if( i<=j ) swap( Tablica[i++], Tablica[j--] );
while(i<=j);
quicksort(Tablica,lewy,j);
quicksort(Tablica,i,prawy);
我正在使用 ubuntu。我试图用谷歌搜索出了什么问题,但在我看来,我的算法与我发现的一些算法几乎相同,所以我不知道如何修复它。 对不起,我的英语很抱歉,我不经常使用它。
感谢您帮助我。
【问题讨论】:
尝试对 Tablica 使用 std::vector,而不是动态分配的数组。 你怎么打电话给quicksort
?
while(i<=j);
- 我认为这需要<
,而不是<=
。
我这样称呼它:quicksort(Tablica,0,size_of_array-1);
【参考方案1】:
由于您选择第一个元素作为枢轴,因此您的递归太深了;你用完了堆栈并崩溃和燃烧。大部分数据按排序顺序排列,您正在对数组中的最小元素进行分区,因此您的快速排序将在二次时间中工作。您可以通过在较小的分区上递归然后循环对较大的分区进行排序来提高代码存活的机会。
您可以通过检测您的排序代码、每次输入排序时递增和打印计数器以及在您离开时递减计数器来证明这一点。使用较小的阵列尺寸和较少的预分类材料,您不会走得那么深;使用大数组大小和更多有序数据,您只会溢出堆栈。
这是一个 C 快速排序函数,它使用最小元素作为枢轴并迭代和递归:
/* Fat pivot algorithm with tail recursion replaced by loop */
/* Pivot is low element */
static void fpquicksort3(Data a[], size_t low, size_t high)
sort_enter(__func__, a, low, high);
while (low + 1 < high)
Data pivot = a[low];
size_t i = low + 1;
size_t j = high;
size_t k = high;
while (i < j)
inc_comps();
if (a[i] < pivot)
i++;
else if (a[i] > pivot)
if (--j != --k || i != k || i != k)
sort_swap3(__func__, a, i, j, k);
else
if (i != --j)
sort_swap2(a, i, j);
if (low != --i)
sort_swap2(a, low, i);
if (i - low <= high - k)
if (i - low > 1)
fpquicksort3(a, low, i);
low = k;
else
if (k - high > 1)
fpquicksort3(a, k, high);
high = i;
sort_exit(__func__, a, low, high);
sort_enter
、sort_exit
、sort_swap2
、sort_swap3
和 inc_comps
函数是代码中的检测挂钩(它们会计算递归深度)。
【讨论】:
有趣的是,如果我使用 Code::Blocks 编译它并运行,它会引发分段错误。但我刚刚在控制台中编译它并使用 gdb 运行它:它甚至适用于完全排序的 500k 数组!我没有对代码进行任何更改。对我来说没关系,因为现在我拥有了我想要的东西,但我对此更加困惑。感谢您的回复。【参考方案2】:我在这里缺少范围检查或sentinel value
while(Tablica[i] < x ) i++;
while(Tablica[j] > x ) j--;
因此,离开分配的边界可能会发生分段错误。
【讨论】:
枢轴不会充当哨兵吗? 嗯,好的,我会试试 while(Tablica[i]以上是关于大小为 500000 的部分排序数组的快速排序分段错误的主要内容,如果未能解决你的问题,请参考以下文章