嗯,我正在尝试学习快速排序并为其实现了以下代码。但是,当我把最左边或最右边的元素作为枢轴时,它似乎在O(n ^ 2)而不是O(nlogn)中运行...
我无法弄清楚我的代码有什么问题,但我很可能犯了一些非常基本的愚蠢错误;谁能请帮助并解释我哪里出错了?
提前多多感谢!这是我的代码:
#include <iostream>
#include <vector>
typedef int64_t int64;
int64 numberOfComparisons;
using namespace std;
int partitionAroundPivot(vector<int64>& a, int l, int r) {
numberOfComparisons = numberOfComparisons + (r - l) - 1 ;
int ppos;
ppos = l;
int64 p = a[ppos]; //Gives pivot
if(ppos != l)
swap(a[ppos], a[l]);
int i = l + 1, j;
for(j = l + 1; j <= r; j++){
if(a[j] < p)
{
swap(a[j], a[i]); //Swap with leftmost element bigger than pivot, i.e. v[i]
i++;
}
}
//Now pivot needs to go to its proper place
swap(a[l], a[i - 1]);
return ppos; //WRONG, will return l always, need to return i-1
}
void quickSort(vector<int64>& a, int l, int r) //Inplace so no return stuff
{
if( r - l <= 0)
return ;
int pivotPosition = partitionAroundPivot(a, l, r);
cout << "Called Qsort with positions l " <<l << " r " << r << " Pivot pos " << pivotPosition << endl;
for (int i = l; i < r; i++)
cout << a[i] <<" " ;
cout << endl;
quickSort(a, l , pivotPosition - 1 );
quickSort(a, pivotPosition + 1 , r );
}
int main() {
vector<int64> x = {3, 2, 1, 8, 6, 7, 6, 4};
quickSort(x, 0, x.size() -1);
return 0;
}
部分输出如下:
Called Qsort with positions l 0 r 9 Pivot pos 0
1 2 3 4 6 10 9 5 7
Pivot: 2
Called Qsort with positions l 1 r 9 Pivot pos 1
2 3 4 6 10 9 5 7
Pivot: 3
编辑:我问这个的部分原因是因为我应该计算总理论上完成的比较次数,而我只是使用(每个分区调用的子阵列大小 - 1)作为值(实际的将是不同的,我知道,因为只有部分比较实际发生)。这可以在上面的numberOfComparisons变量中看到。
现在的问题是,为了排序100个数字,全部来自1-100,没有唯一且大部分是随机的,它显示计算的数量为4851,接近100 * 99/2又名n *( n-1)/ 2,其中n = 100.这使我相信它正在做O(n ^ 2)时间。这是正确的吗??
EDIT2:毕竟我真是太蠢了。 partitionAroundPivot总是返回l又名子阵列的第一个位置,导致其中一个分裂是零长度子阵列,另一个是阵列的其余部分。我需要传回[l]实际上去的位置,而不是l;在这种情况下,i-1。经验教训,我想。非常感谢你的帮助,伙计们!
答案 0 :(得分:2)
Qucksort是O(n log n)但平均而言,在最坏情况下为O(n ^ 2),在最佳情况下为O(nlogn)。获得良好效率的最重要方面是选择一个好的支点。
在你的程序中,你选择了一个最差的枢轴,因为如果选择第一个或最后一个,在有序(或反向排序)向量的情况下,你的算法效率最差。
这就是为什么你必须考虑你的算法来选择枢轴。最常用的方法之一是选择三个中值,例如,第一个,中间和最后一个元素。因此,应用于有序向量的算法是O(nlogn)。
更新:复杂性取决于增长情况,而不是特定情况。实际上,对于特定大小的问题,您可能具有非常高的值,而当问题大小变得非常大时,配置文件会更加平滑。在检查任何内容之前,运行程序,其中有几个单独的值达到非常大的n。