简体   繁体   English

Haskell中的quicksort如何工作?

[英]How does quicksort in Haskell work?

On the Haskell website , there's this example quicksort implementation : Haskell网站上 ,这个示例是quicksort实现

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

There is an explanation on the site, but I have a couple of questions that I didn't see were addressed ... 该网站有一个解释,但我有几个问题,我没有看到解决...

  • where is the actual comparison/swap done on two elements for a re-order? 对于重新订购,两个元素的实际比较/交换在哪里? Is this handled by the 'Ord' (ordered) type definition itself. 这是由'Ord'(有序)类型定义本身处理的。 So the type enforces this condition of being ordered? 那么类型强制执行这个被命令的条件?
  • the 'greater' filter defines items '>= p' (the pivot), so doesn't this mean we'll end up with an extra pivot [p] in resulting list of the function, due to the '++ [p]' item? “更大”的过滤器定义了项目'> = p'(枢轴),所以这并不意味着我们最终会在函数的结果列表中有一个额外的pivot [p],因为'++ [p ]'项目?
  1. There is no swap, because this is not the (almost-)in-place version of QS. 没有交换,因为这不是QS的(几乎)就地版本。 Instead, new lists are built and then concatenated — comparison is done when lesser and greater are created, with < , >=Ord is a typeclass restricting a to be orderable — if it wasn't used, you wouldn't be able to use < or >= . 相反,新的名单是建立,然后再连接-当比较完成lessergreater的创建,以<>= - Ord是一个类型类限制a要订购-如果没有使用它,你就不能使用<>=
  2. No, because the pivot is not part of xs — pattern match splits input list into p and xs . 不,因为枢轴不是xs一部分 - 模式匹配将输入列表拆分为pxs

Here's crappy ASCII visualisation: 这是糟糕的ASCII可视化:

                                qs [5, 5, 6, 3, 1]
                                          |
                         qs [3, 1]   ++  [5] ++ qs [5, 6]
                             |            |       |
                  qs [1] ++ [3] ++ qs []  |    qs [] ++ [5] ++ qs [6]
                             |            |       |
                           [1, 3]    ++  [5]  ++ [5, 6]
                             \            |        /
                              \-------------------/
                                        |
                                  [1, 3, 5, 5, 6]

where is the actual comparison/swap done on two elements for a re-order? 对于重新订购,两个元素的实际比较/交换在哪里? Is this handled by the Ord (ordered) type definition itself. 这是由Ord (有序)类型定义本身处理的。 So the type enforces this condition of being ordered? 那么类型强制执行这个被命令的条件?

What does Ord mean? Ord是什么意思?

Ord just means that a should be comparable with itself or in stricter terms operations such as > , < , and == should be defined for a . Ord只是意味着a应该与自身相比或者更严格的术语,例如><==应该为a定义。 You can think of it as a constraint on the method. 您可以将其视为该方法的约束。

So, where is the ordering done? 那么,订购在哪里完成?

And the answer is the last pattern: 答案是最后一种模式:

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

At run time, the program is going to get an array and the array must meet either of these two patterns: 在运行时,程序将获得一个数组,并且数组必须满足以下两种模式之一:

Pattern 1#: It is empty, in which case the function returns that same empty array and stops. 模式1#:它是空的,在这种情况下,该函数返回相同的空数组并停止。

Pattern 2#: It is not empty or in other words, there is a head element p appended to a tailing array xs . 模式2#:它不是空的,换句话说,有一个头元素p附加到尾部数组xs In such a case, the function is told to put p in the middle, put all elements of xs that are less than p on the left (as defined by lesser ) of p and all elements of xs that are greater than or equal to p on the right of p . 在这样的情况下,函数被告知把p在中间,放的所有元素xs是小于p的左(通过定义lesser )的p和的所有元素xs是大于或等于p在右边的p Furthermore, the function is finally told to apply itself (ie, the same function quicksort ) on lesser (which as we defined above, is the array on the left hand side of p ) and greater (which as we defined above, is the array on the right hand side of p ). 此外,最后告诉函数将自身(即,相同的函数quicksort )应用于lesser (如上所述,是p的左侧的数组)和greater (正如我们在上面定义的那样,是数组)在p )的右侧。 As you can see, this will go on till you are left with a zero sized array and pattern 1# terminates the function. 正如您所看到的,这将持续到您留下零大小的数组并且模式1#终止该函数。

Finally, whenever those recursive calls terminate the function shall return the array: 最后,每当这些递归调用终止时,函数都将返回数组:

sortedlesser ++ p ++ sortedgreater 

where sortedlesser is the array that resulted from the application of quicksort on lesser and sortedgreater is the array that resulted from the application of quicksort on greater . 其中sortedlesser是起因于应用的阵列quicksortlesser并且sortedgreater是起因于应用的阵列quicksortgreater

Wait… are we not duplicating p again and again? 等等......我们不是一次又一次地复制p吗?

the 'greater' predicate defines items '>= p' (the pivot), so doesn't this mean we'll end up with an extra pivot [p] in resulting list of the function, due to the '++ [p]' item? '更大'的谓词定义了项'> = p'(枢轴),所以这并不意味着我们最终会在函数的结果列表中得到一个额外的pivot [p],因为'++ [p ]'项目?

No, this is not how pattern matching works. 不,这不是模式匹配的工作原理。 It is saying all elements in xs that are greater than or equal to p . 它说xs中的所有元素都大于或等于p By definition p itself is out of xs . 根据定义, p本身不在xs If there are duplicates of p in xs then they will fall on the right hand side. 如果在xs有重复的p ,那么它们将落在右侧。 Note that this choice will preserve the natural ordering of the original array. 请注意,此选择将​​保留原始数组的自然顺序。

Note that you can write this even shorter and more performant (as partition scans the original list only once) using 请注意,您可以使用更短更高效的内容(因为partition仅扫描原始列表一次)

quicksort [] = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
    where (lesser, greater) = partition (< p) xs

If you want only one line: 如果您只想要一行:

qsortOneLine s = case s of{[]->[];(x:xs)->qsortOneLine [y | y<-xs, y<x] ++ x : qsortOneLine [y | y<-xs, y>=x]}

If you want more performant code: 如果您想要更高性能的代码:

qsort3 :: Ord a => [a] -> [a]
qsort3 x = qsort3' x []
qsort3' [] y     = y
qsort3' [x] y    = x:y
qsort3' (x:xs) y = part xs [] [x] []  
      where
         part [] l e g = qsort3' l (e ++ (qsort3' g y))
         part (z:zs) l e g 
             | z > x     = part zs l e (z:g) 
             | z < x     = part zs (z:l) e g 
             | otherwise = part zs l (z:e) g

http://en.literateprograms.org/Quicksort_(Haskell ) http://en.literateprograms.org/Quicksort_(Haskell

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM