【问题标题】:Haskell's quicksort - what is it really? [duplicate]Haskell 的快速排序 - 它到底是什么? [复制]
【发布时间】:2013-02-09 09:57:43
【问题描述】:

正如他们所说,"true quicksort sorts in-place"。所以quicksort的标准short Haskell code

quicksort :: Ord a => [a] -> [a]
quicksort []     = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
  where
    lesser  = filter (< p) xs
    greater = filter (>= p) xs

它到底描述的是什么算法/计算过程

肯定不是what Tony Hoare devised,它缺少其最具定义性的功能,即就地分区算法。

(答案可能是众所周知的,但还没有在这里)。


更正:这个问题实际上是重复的:答案 毕竟在 SO 上是已知的:cf。 Pseudo-quicksort time complexity.

【问题讨论】:

  • 描述的是快速排序。
  • 在您链接到的文章中没有证据表明 Hoare 认为它不是快速排序,除非它是就地的。
  • @AndrewC 是的,那篇文章可能不是支持我的案例的最佳选择。但是,这就是WP。我的意思是(我看到它争论了很多次)是它在原始论文中的描述 - 并且分区算法非常具体,具有交换和移动边界。根据这种观点,(不可变的)链表没有快速排序之类的东西。 (对于可变的,我们可以创建一个单元格地址数组并交换单元格内容 - (当然不是在 Haskell 中)。
  • 根据the wikipedia article that you've linked中的文字描述,代码是快速排序算法的实现。

标签: algorithm haskell quicksort


【解决方案1】:

它是链表的快速排序。

是的,这是快速排序,只是不是就地排序。它匹配快速排序的高级算法,同时更改低级实现以匹配链表的数据结构。这就是为什么它对链表进行快速排序。

我更愿意说“快速排序最初是为就地工作而开发的”,而不是“真正的快速排序是就地完成的”。快速排序有许多变体,包括随机选择枢轴以避免更坏的情况等。这是对链表快速排序的明智、清晰的定义。

这个定义与我们在英国向 16 岁数学学生教授快速排序的方式完全一致。 (我们教的是算法,而不是编程。)就地非常模糊了目的和设计,这就是为什么我们不教那些细节,尽管距离教函数式编程或链表有一百万英里。 (这并没有改变这样一个事实,即当您有破坏性更新数组时,就地对交换技巧是最好的算法。)

此定义存在时间损失,因为它为两个子列表遍历列表两次。当然可以将其重写为分区而不是过滤,但我断言这是优化而不是更改这里的基本算法,快速排序。

【讨论】:

  • Tony Hoare 的快速排序由其就地分区算法定义。我已经编辑了问题。
  • @WillNess 这个是定义的,它使用了过滤?我不这么认为。
  • 这是通过过滤创建临时列表来定义的。否则,您对它的看法太高了,而忽略了基本细节。当然,这样做是完全可以的,只是不是为了这个问题的目的。 :) IOW 我确实更专注于操作细节,在这里。如果我的措辞不清楚,我很抱歉。
  • 甚至是遍历列表一次的重写,它们仍然没有就地分区,而是通过创建临时列表。 ...partition 在操作上仍然在做同样的事情 - 它将一个列表分成两个新的。
  • @MariusKavansky 就地意味着不制作列表的新副本。如果您在内存较少的机器上拥有大量数据,这很重要。
【解决方案2】:

所有就地算法都需要在 Haskell 中进行一些“仪式”,其中可变状态隐藏在 monad 后面。上面的算法快速排序,只是不是就地排序。

【讨论】:

  • Tony Hoare 的快速排序由其就地分区算法特别定义。抱歉没有再强调,我已经编辑了问题。
  • 如果您已经知道自己想听什么(“这不是 Tony Hoare 定义的不是快速排序”),为什么还要问?但是,由于您不能使用 Haskell 列表编写就地算法,因此您的代码尽可能接近快速排序的 idea,只要选择了数据结构即可。
  • 我看不出矛盾。问题是:“它不是 X,而是什么?”。 AFAIK 当您(认为您)已经知道答案时,可以在 SO 上提出问题,以便在 SO 上知道。我没想到真的会发生争执。
【解决方案3】:

预期的答案(来自here)是“真的是砍伐森林的树种”。原来,haskellwiki 上也提到过。

【讨论】:

  • 如果将树从树排序中取出,那么使用名称树排序的理由肯定比从快速排序中交换出来的要少吗?按照这个逻辑,你可以称之为去交换快速排序。
  • @AndrewC 我真的不知道在这里做什么,安德鲁。我应该不接受吗? reddit 讨论的论点在某种程度上对我很有吸引力。但是看,我认为是这样的:我们可以将类型视为标记列表(来自 Lisp 角度)。树只是一个标签;当我们创建一棵树时,我们真正要做的是,较小的在左侧,而较大的在右侧。因此,当我们分成两组时,它基本上与我们将它们放入树的两个分支 - 左和右时相同。 IOW 树与三元组“同构”。
  • @AndrewC 但在原始算法中,分区的完成方式不同,带有交换。在树排序的任何一步中,我们都没有考虑将较小的放在右边,然后将它们交换到左边——当我们创建树时,一开始是空的,然后当我们一个接一个地插入它时,每个都去向左,或向右。 ...顺便说一句,我认为,deswappinged quicksort 这个名字实际上非常好。很高兴你回来顺便说一句。 :)
  • 接受认为是最好的答案,而不是认为是最简单的答案!这就是它的用途!
  • 我喜欢你的 essentially the same 论点,但我断言我们正在谈论的算法也 essentially the same(在较高水平推理)作为快速排序,所以在它的名字中使用快速排序是可以的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-10
  • 1970-01-01
  • 2013-05-29
  • 1970-01-01
  • 2013-04-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多