【问题标题】:Quick Sort - Middle Pivot implementation strange behaviour快速排序 - 中间枢轴实现奇怪的行为
【发布时间】:2015-11-20 23:25:31
【问题描述】:

我正在尝试使用在线提供的各种教程以枢轴值作为向量的中间元素来实现快速排序。 即使它适用于某些样本,也有一个我无法获得已排序的向量。

示例 - 输入 {5,3,8,6,1,0,4} 但输出为 {0,3,4,5,1,6,8}

快速排序实现

void quickSortMiddle(vector<int> &a, int left, int right)
{
    if(left >=right) return;

    int leftI = left;
    int rightI = right;

    int pivot = left + (right - left)/2;

    while(leftI<=rightI)
    {
        while(a[leftI] < a[pivot] )leftI++;
        while(a[rightI] > a[pivot])rightI--;

        if(leftI <=rightI)
        {
            swap(a[leftI], a[rightI]);
            leftI++;
            rightI--;
        }
    }

    if(left <= rightI)quickSortMiddle(a,left,rightI);
    if(leftI <= right)quickSortMiddle(a,leftI,right);
}

以下是我在每次实施后得到的输出

5340168

0345168

0345168

0345168

final : 
0345168

【问题讨论】:

  • 你试过调试了吗?
  • 是的。我认为当左右索引在同一个元素上时,即 1,那就是它不起作用的时候。
  • 问题是一旦leftI或rightI等于pivot,交换[leftI]和[rightI]会改变[pivot]的值。您需要将 [pivot] 复制到单独的变量中。 (或者,如果复制数组元素的成本很高,请修改枢轴以指向交换后枢轴所在的位置)。
  • 是的,我后来被@rcgldr 指出后才意识到这一点。我会记住的。感谢您的帮助。

标签: c++ algorithm sorting quicksort


【解决方案1】:

问题在于使用 a[pivot] 而不是设置 pivot = a[left + (right - left)/2]。您使用此修复的版本:

void quickSortMiddle(vector<int> &a, int left, int right)
{
    if(left >=right) return;
    int leftI = left;
    int rightI = right;
    int pivot = a[left + (right - left)/2]; // set pivot to value
    while(leftI<=rightI)
    {
        while(a[leftI]  < pivot )leftI++;   // use pivot by value
        while(a[rightI] > pivot )rightI--;  // use pivot by value
        if(leftI <=rightI)
        {
            swap(a[leftI], a[rightI]);
            leftI++;
            rightI--;
        }
    }
    if(left < rightI)quickSortMiddle(a,left,rightI); // < not <=
    if(leftI < right)quickSortMiddle(a,leftI,right); // < not <=
}

标准 Hoare 分区方案,尽管您的版本与枢轴修复一起工作正常:

void quickSortMiddle(vector<int> &a, int left, int right)
{
    if(left >= right) return;
    int pivot = a[left + (right - left)/2];
    int leftI = left-1;
    int rightI = right+1;
    while(1)
    {
        while(a[++leftI] < pivot);
        while(a[--rightI] > pivot);
        if(leftI >= rightI)break;
        swap(a[leftI], a[rightI]);
    }
    quickSortMiddle(a,left,rightI);
    quickSortMiddle(a,rightI+1,right);
}

【讨论】:

  • 是的。非常感谢。这花了很多时间。
猜你喜欢
  • 2011-08-31
  • 2018-11-14
  • 1970-01-01
  • 2017-03-12
  • 2021-04-19
  • 1970-01-01
  • 2010-09-14
  • 1970-01-01
  • 2019-11-23
相关资源
最近更新 更多