【问题标题】:haskell quick sort, why the first let uses <= instead of <?haskell快速排序,为什么第一个让使用<=而不是<?
【发布时间】:2015-03-08 02:45:20
【问题描述】:
quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
    let smallerOrEqual = [a | a <- xs, a <= x]
        larger = [a | a <- xs, a > x]
    in quicksort smallerOrEqual ++ [x] ++ larger

main = do
    let a = [ 5, 1, 9, 4, 6, 7, 3]
    print  $ quicksort a

在 Haskell 快速排序中,为什么第一个 let 使用 &lt;= 而不是 &lt;?我认为&lt;= 会重复x 很多次。为什么不呢?

【问题讨论】:

  • 因为它试图稳定。
  • 如果您使用&lt; 而不是&lt;=,则生成的列表将是原始列表的升序版本但删除了所有重复项。然而,消除欺骗并不是排序的目的。
  • @Jubobs 但是,它是否继续包含“x”?我不明白那部分。如何每次摆脱一个。
  • @BufBills 不知道你的意思...严格来说,排序不是丢掉骗子;结果列表应该只是您传递给quicksort 的列表的排序版本;这两个列表应该具有相同的长度。顺便说一句,你错过了一个函数调用;应该是quicksort smallerOrEqual ++ [x] ++ quicksort larger
  • 感谢朱博斯。我明白了!

标签: list sorting haskell


【解决方案1】:

我认为

不,不会。让我们了解这里到底发生了什么。您基本上是将列表分为三个部分。

  1. 小于或等于枢轴元素的数字列表(不包括第一个元素,因为那是枢轴元素)

  2. 枢轴元素本身(列表中的第一个元素)

  3. 大于枢轴元素的数字列表

所以,在你的情况下,分区列表变成了这样

[1, 4, 3] ++ [5] ++ [9, 6, 7]

考虑这样的情况,quicksort [5, 1, 5, 9, 8, 5, 3, 6, 4]。然后,您的程序会将其划分为类似这样的内容

smallerOrEqual ++ [x] ++ larger

由于smallerOrEquallarger 与没有xxs 一起使用,因此没有这样的重复。现在,分区列表,经过过滤,变成了

[1, 5, 5, 3, 4] ++ [5] ++ [9, 8, 6]

看到了吗?没有重复,只有分区。

注意:您的程序存在严重错误。检查这一行

quicksort smallerOrEqual ++ [x] ++ larger

基本上是这样的

(quicksort smallerOrEqual) ++ [x] ++ larger

因此,larger 列表永远不会排序。您必须递归地对较小的列表和较大的列表进行排序,最后将它们合并为一个。所以,应该是

(quicksort smallerOrEqual) ++ [x] ++ (quicksort larger)

不用括号也可以这样写

quicksort smallerOrEqual ++ [x] ++ quicksort larger

【讨论】:

  • 你不需要那些括号:quicksort smallerOrEqual ++ [x] ++ quicksort larger 工作正常,因为函数应用程序的优先级高于中缀运算符++
  • @Jubobs 是的,我们不需要它们。但这可能有助于他理解错误,对吧?无论如何,我现在也包括了无括号版本:)
  • “小于或等于枢轴元素的数字列表”有点误导,因为它暗示它包含枢轴本身,然后在第 2 点再次添加,从而导致重复。关键部分是这个列表是作为尾部 xs 的过滤器获得的,而不是整个原始列表 x:xs 的过滤器。
  • @chi 你说得对。我想清楚地说明这一点。这就是我添加这些点的原因。我现在编辑了它们。请检查是否正常。
  • @thefourtheye 好多了。
猜你喜欢
  • 1970-01-01
  • 2013-02-15
  • 1970-01-01
  • 2022-11-02
  • 1970-01-01
  • 2018-03-28
  • 1970-01-01
  • 1970-01-01
  • 2017-05-13
相关资源
最近更新 更多