Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 计算快速排序中的元素比较数_C++_Sorting - Fatal编程技术网

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]);
  • 第一个for语句并不是真的计算任何东西,所以这只是伪装的一段时间(true)。它将以break语句结束
  • 找到要交换的第一个大元素:
    while(a[++i]
    语句利用了pivot`v或a[r]'元素是最右边的元素这一事实。因此pivot元素在这里起到了保护作用
  • 找到要交换的第一个小元素:while(v
没有枢轴的保证。相反,它检查最左边的限制
  • 最后一个检查就是看看分区是否完成了,如果是这样,打破无限循环,最后
  • 交换(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]);