Haskell Quicksort efficiency [duplicate]

江枫思渺然 提交于 2019-12-22 11:28:41

问题


Here's an example from Learn you a Haskell:

quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
    let smallerSorted = quicksort [a | a <- xs, a <= x]
        biggerSorted  = quicksort [a | a <- xs, a > x]
    in smallerSorted ++ [x] ++ biggerSorted

It seems that the list is iterated twice for each recursion, once for each list comprehension. Is there some magic in the compiler that optimizes this? If not, how can this be fixed?

Edit: I don't care if this is a real quicksort. Ignore the quicksort. My question is about the efficiency of the two list comprehensions, and how you can modify this specific algorithm (quicksort or not) in order to avoid iterating xs twice per recursion.


回答1:


No. As of now, GHC 7.8.2 is not smart enough to figure out the clever in place quicksort algorithm from the above quicksort definition. You can do the same thing in a single pass by defining quicksort as

import Data.List (partition)
quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) = let (psx1, psx2, psx3) = partition3 x (x:xs) in
                   quicksort psx1 ++ psx2 ++ quicksort psx3

partition3 _ [] = ([], [], [])
partition3 a (x:xs)
    | a == x = (pxs1, x:pxs2, pxs3)
    | a < x = (pxs1, pxs2, x:pxs3)
    | a > x = (x:pxs1, pxs2, pxs3)
    where (pxs1, pxs2, pxs3) = partition3 a xs

But you should check is it possible to do quicksort of a list with only one passing? as it is more efficient than the above version.



来源:https://stackoverflow.com/questions/23318948/haskell-quicksort-efficiency

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!