分而治之:合并排序

时间:2015-05-04 11:58:14

标签: haskell

我对Haskell相当陌生,并且不了解以下分而治之的构造:

{-     trivial        solve       split        combine       input/output-}
dc :: (a -> Bool) -> (a -> b) -> (a -> [a]) -> ([b] -> b) -> a -> b
dc trivial solve split combine = x
  where
    x y = if trivial y then solve y
           else (\_ z -> combine z) y (map x (split y))

现在我需要基于这个构造实现一个merge-sort函数。我试图实现一些功能,但我很确定它不应该如何工作:

trivial :: (Ord a, Num a) => [a] -> Bool
trivial [] = True
trivial (x:[]) = True
trivial (x:x':xs) = if x<=x' then trivial (x':xs) else False

split :: [a] -> [[a]]
split (x:[]) = [[x]]
split (x:xs) = [x] : split xs

combine :: [[a]] -> [a]
combine [[]] = []
combine ([]:ys) = combine ys
combine ((x:xs):ys) = x : combine (xs:ys)

那么上面的构造如何工作?什么&#34; x&#34;和&#34; y&#34;代表 ?什么应该&#34;琐事&#34;和&#34;解决&#34; (和拆分/合并)吗?

1 个答案:

答案 0 :(得分:4)

因此,dc的签名可以读作&#34;此函数接受4个参数并返回从ab&#34;的函数。在定义中,此函数称为xxwhere子句中定义为:

x y = if trivial y then solve y
       else (\_ z -> combine z) y (map x (split y))

您可以为x添加类型签名:

x :: a -> b

x的定义(执行实际划分和征服计算的函数)有点混淆,但可以理解为:

  • 如果x是一个微不足道的案例,那就解决它
  • 否则,将其拆分,分而治之(用x),然后合并结果。

注意:它可以写得更清楚:

x y = if trivial y then solve y
      else (combine . map x . split) y

此功能可以完成您需要的所有递归,因此您的功能不需要关心它。你的职能应该是:

  • trivial:如果在这种情况下solve可以解决问题,则为真。对于合并排序,简单的情况是只包含一个项目的列表。
  • solve:解决了一些小问题。对于合并排序,它只是身份(因为它只是一个项目列表)。
  • split:将大问题分解为较小的问题(这些问题会多次进行,直到它们变得微不足道。对于合并排序,它只是将列表分成两半。
  • combine:获取以前拆分的内容列表,然后合并它们。对于合并排序,合并魔法发生的地方:)

注意:合并排序算法可能与我提到的略有不同。例如,排序列表也可能是一个小问题。