C++ 计算快速排序中的元素比较数
我已经收到了这个预定义的快速排序代码,该代码不会做太多修改: 我知道我们在这方面已经有问题了,但这是不同的,因为这里预先定义了逻辑C++ 计算快速排序中的元素比较数,c++,sorting,C++,Sorting,我已经收到了这个预定义的快速排序代码,该代码不会做太多修改: 我知道我们在这方面已经有问题了,但这是不同的,因为这里预先定义了逻辑 void quicksort(int a[], int l, int r) { if (r <= l) return; /* call for partition function that you modify */ quicksort(a, l, i-1); quicksort(a, i+1, r); } int
void quicksort(int a[], int l, int r)
{
if (r <= l) return;
/* call for partition function that you modify */
quicksort(a, l, i-1);
quicksort(a, i+1, r);
}
int partition(int a[], int l, int r)
{ int i = l-1, j = r; int v = a[r];
for (;;)
{
while (a[++i] < v) ;
while (v < a[--j]) if (j == l) break;
if (i >= j) break;
exch(a[i], a[j]);
}
exch(a[i], a[r]);
return i;
}
void快速排序(int a[],int l,int r)
{
如果(r=j)断裂;
exch(a[i],a[j]);
}
exch(a[i],a[r]);
返回i;
}
我们只需要稍作修改,以便快速排序返回它在对给定数组a进行排序时与分区函数一起(总共)执行的比较次数**在这些比较中,仅计算涉及数组元素的比较。在计算这些比较时,不允许使用任何全局变量**
我已按如下方式实施,如果我在某个地方出错,请告知我:
int partition(int a[], int l, int r, int& count) {
int i = l - 1, j = r; int v = a[r];
for (;;) {
while (a[++i] < v) count++;
while (v < a[--j]) {
count++;
if (j == l) break;
}
if (i >= j) break;
swap(a[i], a[j]);
}
swap(a[i], a[r]);
return i;
}
int quickSort(int a[], int l, int r) {
int count = 0;
if (r <= l) return 0;
int i = partition(a, l, r, count);
return count + quickSort(a, l, i - 1) + quickSort(a, i + 1, r);
}
int分区(inta[],intl,intr,int&count){
inti=l-1,j=r;intv=a[r];
对于(;;){
而(a[++i]=j)断裂;
掉期(a[i],a[j]);
}
掉期(a[i],a[r]);
返回i;
}
int快速排序(int a[],int l,int r){
整数计数=0;
如果(rricis)comment作为一种解决方案可以很好地工作。有一种替代方法可以推广到std::sort和其他算法,那就是制作一个计数比较器
类似于
struct CountingComparer{
CountingComparer():count(0){}
CountingComparer(const CountingComparer& cc):count(cc.count){}
bool operator()(int lhs, int rhs){
count;
return lhs < rhs;
}
size_t count;
};
呼叫排序
您需要确保在模板参数中有对比较器的引用
CountingComparer comp;
quicksort(... , std::ref(comp));
确保未复制组件
排序后,您可以在comp.count中找到比较的数量
关于你对计数的评论
wikipedia页面上广泛讨论了快速排序的行为。预计排序数组的行为会很差,而随机元素的行为会很好
关于配分函数的巧妙性
(;;)的
{
而(a[++i]=j)断裂;
exch(a[i],a[j]);
}
exch(a[i],a[r]);
没有枢轴的保证。相反,它检查最左边的限制
交换(a[i],a[r]);
将枢轴元素安排到正确的位置这显然是不正确的,因为您丢弃了对快速排序的递归调用的返回值。最外层的快速排序只返回它自己对分区的单个调用的比较计数。胜利的全局变量!@CaptainGiraffe:Pfah。
返回计数+快速排序(a,l,i-1)+快速排序(a,i+1,r)
@CaptainGiraffe:哦,是的,我的错。真的很抱歉。在这个问题中不允许使用全局变量。对不起。我的道歉。我的评论是开玩笑的。我明白了。谢谢。但是,在我的分区函数中,计数递增器的位置正确吗?好的……你能让我看看分区代码吗。我一点也不懂。我知道一个普通的配分函数应该做什么,但这个函数有一个空for循环和一个while循环,它什么都不做……我很困惑。我认为它来自Robert Sedgewick的书。@GuptillGunther它看起来和Sedgewick中的代码一模一样。我会在答案中对它进行评论。这是一种聪明的方式,不必在每段时间进行两次比较。谢谢太多了。你真的让我开心。:@GuptillGunther做了一些编辑,进一步解释了分区。祝你愉快=)
while (comp(a[++i],v)) and
while (comp(v, a[--j])) respectively.
CountingComparer comp;
quicksort(... , std::ref(comp));
for (;;)
{
while (a[++i] < v) ;
while (v < a[--j]) if (j == l) break;
if (i >= j) break;
exch(a[i], a[j]);
}
exch(a[i], a[r]);