简化selectionsort和mergesort

时间:2012-10-06 14:44:45

标签: sorting haskell implementation mergesort simplify

我已经设法在几行中实现了insertionsort和quicksort,但是selectionsort和mergesort仍让我感到头痛;)

selectionsort [] = []

selectionsort (x:xs) =
    let (minimum, greater) = extractMinimum x [] xs
    in  minimum : selectionsort greater

extractMinimum minimumSoFar greater [] = (minimumSoFar, greater)

extractMinimum minimumSoFar greater (x:xs)
    | x < minimumSoFar = extractMinimum x (minimumSoFar:greater) xs
    | otherwise        = extractMinimum minimumSoFar (x:greater) xs

类似于标准库中的extractMinimum函数吗?我试着在(a -> a -> Bool/Ordering) -> [a] -> (a, [a])没有任何运气的情况下唠叨。

mergesort [ ] = [ ]

mergesort [x] = [x]

mergesort xs =
    let (left, right) = splitAt (length xs `div` 2) xs
    in  merge (mergesort left) (mergesort right)

merge xs [] = xs

merge [] ys = ys

merge xxs@(x:xs) yys@(y:ys)
    | x < y     = x : merge  xs yys
    | otherwise = y : merge xxs  ys

同样,我是否必须自己编写merge,还是可以重用现有组件? Hoogle没有给我(a -> a -> Bool/Ordering) -> [a] -> [a] -> [a]的有用结果。

2 个答案:

答案 0 :(得分:2)

标准库中没有任何内容,但merge上的包提供了至少hackage,但我不确定是否值得为这样一个简单的函数提供依赖。

然而,

merge xxs@(x:xs) yys@(y:ys)
    | x < y     = x : merge  xs yys
    | otherwise = y : merge xxs  ys

生成不稳定的排序,为了获得稳定的排序,放置x的条件应为x <= y

对于extractMinimum,我也没有找到任何东西,但我可以提供另一种定义,

extractMinimum :: Ord a => a -> [a] -> (a,[a])
extractMinimum x = foldl' select (x, [])
  where
    select (mini, greater) y
      | y < mini  = (y, mini:greater)
      | otherwise = (mini, y:greater)

selectionSort的一个很好的定义是

import Data.List -- for unfoldr

selectionSort :: Ord a => [a] -> [a]
selectionSort = unfoldr getMin
  where
    getMin [] = Nothing
    getMin (x:xs) = Just $ extractMinimum x xs

答案 1 :(得分:0)

我对选择排序的建议:

import Data.List

selectionsort xs = unfoldr f xs where
    f [] = Nothing
    f xs = Just $ extractMinimum xs

extractMinimum (x:xs) = foldl' f (x,[]) xs where
  f (minimum, greater) x | x < minimum = (x, minimum : greater)
                         | otherwise = (minimum, x : greater)