quicksort特殊情况 - 似乎是K& R的错误算法

时间:2012-08-13 17:19:04

标签: c quicksort

我在理解来自K& R的快速排序算法(没有指针的简化版本)时遇到了问题。 Dave Gamble已经在explanation提供了详尽的解释。 但是我注意到,从稍微改变的字符串开始,我们可以在for循环的许多循环中获得没有交换。 首先是代码:

void qsort(int v[], int left, int right)
{
    int i, last;

    void swap(int v[], int i, int j);

    if (left >= right) /* do nothing if array contains */
            return;         /* fewer than two elements */
    swap(v, left, (left + right)/2); /* move partition elem */
    last = left;                    /* to v[0] */
    for (i = left + 1; i <= right; i++) /* partition */
            if (v[i] < v[left])
                    swap(v, ++last, i);
    swap(v, left, last);                  /* restore partition elem */
    qsort(v, left, last-1);
    qsort(v, last+1, right);
}

我的观点中的演练:

我们从CADBE开始;左= 0;右= 4; D是枢轴 所以根据算法我们用D交换D得到DACBE

last = left = 0

i = 1 if if(v 1&lt; v [0])这是真的所以我们用v 1交换v 1(因为last在运行前增加)所以没有变化,最后= 1,仍然有DACBE;

现在i = 2 if(v [2]&lt; v [0]) - &gt;是的,所以我们用v [2]交换v [2]再没有改变; last = 2

现在i = 3 if(v [3]&lt; v [0]) - &gt;是的,所以我们用v [3]交换v [3]没有改变AGAIN(!),last = 3

显然有些事情是错误的,算法什么都不做。 你的意见非常赞赏。我一定是错的,作者比我好; D 提前谢谢!

2 个答案:

答案 0 :(得分:3)

循环从left + 1,包括 righti=4时,测试失败,last不会增加。

然后递归调用BACDEleft=0,right=2排序left=4,right=4。 (当D是支点时,这是正确的。)

答案 1 :(得分:2)

嗯,恰好您的输入子数组ACBE已经被D分区(ACB小于DE是大于D),因此分区周期不会实际交换任何值也就不足为奇了。

实际上,说它“无所作为”是不正确的。它不会对周期中的任何内容重新排序,因为您的输入数据不需要额外的重新排序。但它仍然做了一件事:它找到了last的值,它表示较小的元素结束,较大的元素开始,即它将ACBE分成ACBE部分。循环以last == 3结束,这是进一步递归步骤​​的分区点。