【问题标题】:qsort algorithm in CC中的qsort算法
【发布时间】:2013-12-31 21:20:09
【问题描述】:

我正在阅读《C 编程语言》这本书。在其中,它使用了自己的 qsort 实现:

/* qsort: sort v[left]...v[right] into increasing order */
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);
}

/* swap: interchange v[i] and v[j] */
void swap(int v[], int i, int j)
{
    int temp;
    temp = v[i];
    v[i] = v[j];
    v[j] = temp;
}

我试图通过一个简单的用例来理解这一点,一个包含以下数字的数组:0123456789。

第一次调用 swap 时,它将中间的元素替换为第一个元素。在我们的例子中,0 与 4 交换,所以我们的数组现在看起来像:4123056789。

然后是令人困惑的部分。我们将 i 设置为第一个元素之后的下一个元素(记住第一个元素包含交换后的中间值)。我们的测试一直运行,直到我们达到最后一个索引。我们检查第二个元素是否小于第一个,如果是我们交换它们。在我们的例子中,i 是 1,我们使用预增量运算符将 last 设置为 1(因为 last 被初始化为 0)。所以看起来当我们在第一次循环运行中调用 swap 时,swap 函数的 i 和 j 参数值将被复制为 1。因此我们甚至没有交换任何东西。我错过了什么吗?

【问题讨论】:

  • 你可以在每一步插入一些printfs 来打印出 i 和 j 以及 v 的状态,然后你就可以跟随所有的事情了。仅仅因为它在书中并不意味着它是完美的代码。 :)
  • gdb 是你的朋友...

标签: c quicksort


【解决方案1】:

你没有错过任何东西。对于您考虑的输入,对 swap() 的第 2 次到第 5 次调用确实将具有相等的 ij,导致数组没有变化。

虽然您可能很想将这些调用封装在 if (i != j) 测试中以“节省时间”,但您可能会发现对于大多数输入,这会导致整体速度变慢,因为这是最内层循环中的额外测试,并且在随机排序的输入上,它很少触发(意味着不会节省太多时间)并且无法预测(意味着分支预测会混淆)。

编辑:从这段代码中删除的一般原则是,让一段代码无害地什么都不做比测试它什么都不做然后跳过它的条件更简单,有时更快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    • 2011-08-31
    • 1970-01-01
    相关资源
    最近更新 更多