是否是原地(就地)命令式快速排序?

Posted

技术标签:

【中文标题】是否是原地(就地)命令式快速排序?【英文标题】:Is imperative Quicksort in situ (in-place) or not? 【发布时间】:2012-02-24 04:33:42 【问题描述】:

快速排序通常被描述为原位(就地)算法,尽管它需要 O(log n) 堆栈空间。那么 in situ 是否意味着“需要少于 O(n) 的额外空间”,或者堆栈空间通常不算作空间复杂度(但为什么会这样呢?),或者 Quicksort 实际上不是原位算法?

【问题讨论】:

之前有人问过这个问题:cstheory.stackexchange.com/q/9563/6586。基本上,它是一个带有许多相互矛盾的论点的火焰诱饵。 请注意,这实际上取决于您希望如何定义 in-situ。如果您只是比较排序算法,那么不考虑快速排序是非常挑剔的,但是如果您有一个更正式的定义(希望有一个理由),那么停止忽略小 O(log n) 细节是有意义的. 这只是“O(log n) 也可能是一个较大的常数”的特例,不是吗?原则上,快速排序使用 O(log n) 额外空间。在实践中,您通常将其实现为将数组之类的东西作为参数。大多数语言中的数组具有基于用于地址和/或索引的固定宽度类型的自然大小上限,并且快速排序只需要在每个log n 深度存储几个地址。因此,对于您实际编写和使用的几乎所有 Quicksort 实现,堆栈使用都是有界的,即使它不是“理想”版本。 ... 所以剩下的就是关于“原位”的适当定义的争论 - 快速排序的属性很简单,但例如 C 的 qsort 具有任何体面实现的属性它有一个固定的最大堆栈使用量。 @Jason:当然存在争议,因为定义只有在有用时才有意义。我认为如果您所做的只是将快速排序与合并排序之类的东西进行比较,那么将快速排序考虑在原位是完全可以接受的。如果您要定义复杂性类或执行类似形式的操作,那么应该在原位给出精确的 O(1) 定义的唯一原因。 【参考方案1】:

***提供以下definition:

在计算机科学中,就地算法(或拉丁文in situ)是一种算法,它使用具有少量恒定额外存储空间的数据结构来转换输入。

根据这个定义,典型的基于堆栈的快速排序显然不是原位算法。

事实上,***的文章明确讨论了这一点:

一个算法有时被非正式地就地调用,只要它用它的输出覆盖它的输入。实际上,这还不够(如快速排序的例子所示),也没有必要;输出空间可能是恒定的,或者甚至可能不被计算在内,例如,如果输出是流。

快速排序通常被描述为一种就地算法,但实际上并非如此。大多数实现需要 O(log n) 空间来支持其分而治之的递归。

但是,正如@Jason 在他的出色回答中指出的那样,似乎存在只需要 O(1) 额外空间的快速排序变体。任何此类算法都将被视为原位

【讨论】:

【参考方案2】:

Quicksort 实际上不是原位算法吗?

它的标准实现是不是 原位。这是一个非常普遍的误解,但由于堆栈空间消耗,您正确地注意到,这个概念是错误的。

我说它的“标准实现”是因为人们已经修改了算法以使其成为O(1)-space 算法。这是一个例子:Quicksort without a stack。

当然,与经典的space-time tradeoff 一致,此类版本的快速排序性能不如标准实现。

【讨论】:

以上是关于是否是原地(就地)命令式快速排序?的主要内容,如果未能解决你的问题,请参考以下文章

排序算法(快速排序)

传说中的快速排序是怎样的?

快速排序详解与各种线性时间排序对比

排序优化

各种排序算法的时间复杂度

技术回忆录02|搞懂快速排序