剛剛在排序算法與Haskell溼了我的腳。我實現了插入排序和合並排序合併排序的方式比插入排序更快謎題
insert_sort :: (Ord a, Show a) => [a] -> [a]
insert_sort keys = foldr f [] keys
where f key [] = [key]
f key acc = insert key acc
insert y [] = [y]
insert y (x:xs)
| x < y = x : insert y xs
| otherwise = y : x : xs
merge_sort :: (Ord a, Show a) => [a] -> [a]
merge_sort (x:[]) = [x]
merge_sort keys = merge (merge_sort (take len keys)) (merge_sort (drop len keys))
where len = length keys `div` 2
merge :: [a] -> [a] -> [a]
merge (x:xs) [] = (x:xs)
merge [] (y:ys) = (y:ys)
merge (x:xs) (y:ys) = if x <= y
then x : merge (xs) (y:ys)
else y : merge (x:xs) ys
以下是我比較了它們的效率:
insert_sort $ take 100000 $ randomRs (1,100000) $ mkStdGen 1 ::[Int]
merge_sort $ take 100000 $ randomRs (1,100000) $ mkStdGen 1 ::[Int]
他們都開始多在短暫的延遲後,打印出結果,但合併排序打印更快。我們知道,合併排序比大數據集的插入排序快得多。我認爲這將表現在他們如何給出結果(如長時間延遲與短時延遲),而不是他們如何輸出結果。是因爲我使用foldr
進行插入排序嗎?現場背後是什麼?
編輯:Thx guys。自從我開始學習Haskell以來,我聽說過懶惰的評估,但還沒有掌握它。有人會用一個小數據集說明一點,比如[5,2,6,3,1,4]?自從第一個元素終於出現以後,如何在使用foldr
完成排序之前輸出結果?
歡迎來到懶惰的世界! – 2012-01-19 01:05:06
如果你想打印結果,他們首先必須計算。因此,計算結果更快的算法也可以更快地打印出結果。這令人驚訝嗎?或者,也許我不明白你在問什麼。 – sth 2012-01-19 01:07:20
添加了插圖。 – 2012-01-19 02:27:10