快速排序示例中的错误(K&R C 书)?

Posted

技术标签:

【中文标题】快速排序示例中的错误(K&R C 书)?【英文标题】:Bug in quicksort example (K&R C book)? 【发布时间】:2011-09-23 03:17:18 【问题描述】:

这种快速排序应该将“v[left]...v[right] 排序为升序”;从 K&R 的 The C Programming Language (Second Edition) 复制(没有 cmets):

void qsort(int v[], int left, int right)

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

    if (left >= right)
        return;
    swap(v, left, (left + right) / 2);
    last = left;
    for (i = left+1; i <= right; i++)
        if (v[i] < v[left])
            swap(v, ++last, i);
    swap(v, left, last);
    qsort(v, left, last-1);
    qsort(v, last+1, right);

我认为这里有一个错误

(left + right) / 2

假设左 = INT_MAX - 1,右 = INT_MAX。由于整数溢出,这不会导致未定义的行为吗?

【问题讨论】:

它可能是在假设数组在运行时不会那么大的情况下进行编程的。 :) 这是一个很好的假设,因为您的快速排序程序没有内存空间 另见:googleresearch.blogspot.com/2006/06/… @functionptr 你能回答这个问题吗? ***.com/questions/24534487/quick-sort-programmed-in-c 【参考方案1】:

K&R 在使用无符号和有符号参数时总是有点草率。我想使用只有 16 KB 内存的 PDP 会产生副作用。那是前一阵子修好的。目前qsort的定义是

void qsort(
   void *base,
   size_t num,
   size_t width,
   int (__cdecl *compare )(const void *, const void *) 
);

注意使用 size_t 而不是 int。当然还有 void* base 因为你不知道你在排序什么类型。

【讨论】:

__cdecl 疣不是标准定义的一部分。 我确定这是真的,当时他们可能只有 一个 调用约定。以 two 下划线开头的关键字要少得多。让供应商让它变得复杂。必然如此,标准的有点sux。【参考方案2】:

是的,你是对的,虽然它可能只是为了简单起见才这样写——毕竟这是一个示例,而不是生产代码。

【讨论】:

【参考方案3】:

您不会想象一个包含 INT_MAX 个元素的数组,是吗?

【讨论】:

假设为 32 位整数,这还不到 8 GB 的地址空间。在现代硬件上不仅仅是可行的。 :) 我们可能不得不原谅 K&R 没有考虑将内存从 kB 增加到 GB。并且“640k 应该对每个人都足够了”? @Bo 有 16 位的平台 ints,你知道,我很确定其中一些有超过 64Kb 的内存。 int != intptr_t.【参考方案4】:

是的,你是对的。您可以使用left - (left - right) / 2 来避免溢出。

【讨论】:

@Jerry / Paul:由于(right - left) == - (left - right),与此答案的表述相同。 @caf:啊,我没有这么想,但你是对的。我撤销我原来的评论,并为我的迟钝道歉。

以上是关于快速排序示例中的错误(K&R C 书)?的主要内容,如果未能解决你的问题,请参考以下文章

C程序设计语言 (K&R)

在 K&R 中找到的 C 问题中的二叉树实现

快速排序应用--第K小的数

C语言快排

快速选择算法(求解第k大)

需要帮助理解 K&R C 第 2 章中的“getbits()”方法