【问题标题】:quicksort special case - seems to be a faulty algorithm from K&R快速排序特例 - 似乎是 K&R 的错误算法
【发布时间】:2012-08-13 17:19:04
【问题描述】:

我在理解 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与C交换以获得DACBE

最后一个=左=0

i = 1 if ( v1 1 (因为 last 在操作之前递增)与 v1 交换所以没有任何变化,last = 1,仍然有 DACBE;

现在 i = 2 if ( v[2] true 所以我们将 v[2] 与 v[2] 交换,没有任何改变;最后一个 = 2

现在 i = 3 if ( v[3] true 所以我们用 v[3] 交换 v[3] 没有任何改变 AGAIN (!), last = 3

显然有些地方出了问题,算法什么也没做。 非常感谢您的意见。我一定是错的,作者比我好;D 提前致谢!

【问题讨论】:

  • 您还没有完成演练。在最后一次交换之后,就在第一次递归调用 qsort 之前会发生什么?

标签: c quicksort


【解决方案1】:

循环从left + 1并包括 right。当i=4 时,测试失败,last 不会递增。

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

【讨论】:

  • 谢谢。但是当涉及到递归调用时,我们不是从 BACDE 开始,left=0 和 right=2 (last-1) 吗?
【解决方案2】:

好吧,碰巧您的输入子数组ACBE 已经被D 分区(ACB 小于D 并且E 大于D),所以它是分区周期不会物理交换任何值也就不足为奇了。

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

【讨论】:

    猜你喜欢
    • 2011-09-23
    • 2021-09-21
    • 1970-01-01
    • 2017-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-05
    相关资源
    最近更新 更多