我想检查数组中不同数据的性能时间(随机,已排序,按降序排序)。
void Quicksort(int *T, int Lo, int Hi)
{
if (Lo<Hi){
int x=T[Lo];
int i=Lo, j=Hi;
do
{
while (T[i] < x) ++i;
while (T[j] > x) --j;
if (i<=j)
{
int tmp = T[i];
T[i] = T[j];
T[j] = tmp;
++i; --j;
}
} while(i < j);
if (Lo < j) Quicksort(T, Lo, j);
if (Hi > i) Quicksort(T, i, Hi);
}
}
以下是用于生成和填充测试数组的函数:
int* createArr(int length){
int* Arr= new int[length];
return Arr;
}
void Random(int *A, int length){
for (int i=0;i<length;i++){
A[i]=rand();
}
}
void Order(int *A, int length){
for (int i=0;i<length;i++){
A[i]=i;
}
}
void Backwards(int *A, int length){
for (int i=0;i<length;i++){
A[i]=length-i;
}
}
它适用于随机数,但是当我尝试按升序填充它并进行排序时,它会因堆栈溢出而崩溃。任何人都可以告诉我为什么会这样吗?
答案 0 :(得分:0)
当您选择[Lo]项作为分区值(数据透视),并且数组已经排序时,您将得到1到(length-1)的分区。这会导致对数组较长部分的下一个(递归)调用只处理一个比前一个级别少的项目。因此,正如@AlexanderM所指出的那样,您将获得与数组长度一样深的递归。如果数组很大,几乎肯定会导致堆栈溢出。
尝试使用尾部重复:检查哪个部分较短并使用强行呼叫对其进行排序,然后使用较长部分继续当前级别。为此,请将第一个if
替换为while
并替换
if (Lo < j) Quicksort(T, Lo, j);
if (Hi > i) Quicksort(T, i, Hi);
与
if (j-Lo < Hi-i)
{
Quicksort(T, Lo, j);
Lo = i;
}
else
{
Quicksort(T, i, Hi);
Hi = j;
}
这不会使程序更快 - 它在仍然排序的数组上仍然需要O(n ^ 2)时间,但是将防止线性堆栈内存使用,使其保持在最差O(log n)。
有关更好表现的进一步指示,请参阅维基百科文章Quicksort,支点选择。