归并排序
【题目】归并排序是在两个已经排序的队列中,不断取队头最小的来完成排序的一种算法。试模拟其 merge 算法。
这个问题用 haskell 解决很容易。haskell 的惰性又可以免去我们考虑队列过大的问题。
因为焦点是在列表上进行运算,haskell写起来更容易看出算法的本质,而不被无关的语法细节所遮避。
----简单归并排序
import Data.List (splitAt)
gui_bing :: Ord a => [a] -> [a]
gui_bing [] = []
gui_bing [x] = [x]
gui_bing da = f (gui_bing partA) (gui_bing partB)
where
n = length da `div` 2
(partA, partB) = splitAt n da
f [] ys = ys
f xs [] = xs
f (x:xs) (y:ys) | x < y = x : f xs (y:ys)
| otherwise = y : f (x:xs) ys
main = getLine >>= putStrLn . gui_bing
列表被对分成两半,分别排序后,再进行 merge过程。
merge的时候,如一边为空,则另一边直接为结果。
否则取出两队中头元素的较小者,剩下的递归 merge 过程。
这里的 getLine 取出的是一个字符串。而在 haskell 中字符串只是字符的列表,即: String = [Char], 而 Char 是可比较的类型,因而字符串可以对其中的字符重新排序。每个字符的比较则按它们的 unicode 码序。