ではminimum = head . sort
、事前sort
に行われないため、完全には行われません。は、 によって要求された最初の要素を生成するために必要なだけ実行されます。sort
head
たとえば、マージソートでは、最初n
にリストの番号がペアごとに比較され、次に勝者がペアになって比較され (n/2
番号)、次に新しい勝者が ( n/4
) というようにO(n)
比較されます。
mergesortBy less [] = []
mergesortBy less xs = head $ until (null.tail) pairs [[x] | x <- xs]
where
pairs (x:y:t) = merge x y : pairs t
pairs xs = xs
merge (x:xs) (y:ys) | less y x = y : merge (x:xs) ys
| otherwise = x : merge xs (y:ys)
merge xs [] = xs
merge [] ys = ys
上記のコードを拡張して、生成された各数値に、その生成に使用された多数の比較でタグを付けることができます。
mgsort xs = go $ map ((,) 0) xs where
go [] = []
go xs = head $ until (null.tail) pairs [[x] | x <- xs] where
....
merge ((a,b):xs) ((c,d):ys)
| (d < b) = (a+c+1,d) : merge ((a+1,b):xs) ys -- cumulative
| otherwise = (a+c+1,b) : merge xs ((c+1,d):ys) -- cost
....
g n = concat [[a,b] | (a,b) <- zip [1,3..n] [n,n-2..1]] -- a little scrambler
いくつかのリストの長さで実行すると、実際に であることが~ n
わかります。
*Main> map (fst . head . mgsort . g) [10, 20, 40, 80, 160, 1600]
[9,19,39,79,159,1599]
ソートコード自体が~ n log n
であるかどうかを確認するために、生成された各数値がそれ自体のコストだけを運ぶように変更し、ソートされたリスト全体の合計によって合計コストが求められるようにします。
merge ((a,b):xs) ((c,d):ys)
| (d < b) = (c+1,d) : merge ((a+1,b):xs) ys -- individual
| otherwise = (a+1,b) : merge xs ((c+1,d):ys) -- cost
これは、さまざまな長さのリストの結果です。
*Main> let xs = map (sum . map fst . mgsort . g) [20, 40, 80, 160, 320, 640]
[138,342,810,1866,4218,9402]
*Main> map (logBase 2) $ zipWith (/) (tail xs) xs
[1.309328,1.2439256,1.2039552,1.1766101,1.1564085]
上記は、リストの長さが増加するための経験的な成長の順序をn
示しています。通常、~ n log n
計算によって示されるように、リストは急速に減少します。このブログ投稿も参照してください。簡単な相関チェックは次のとおりです。
*Main> let xs = [n*log n | n<- [20, 40, 80, 160, 320, 640]] in
map (logBase 2) $ zipWith (/) (tail xs) xs
[1.3002739,1.2484156,1.211859,1.1846942,1.1637106]
編集:遅延評価は、比喩的には一種の生産者/消費者のイディオム1と見なすことができ、仲介者として独立したメモ化ストレージを使用します。私たちが書いた生産的な定義は、消費者の要求に応じて少しずつ出力を生成するプロデューサーを定義しますが、すぐには生成されません。生成されたものはすべてメモ化されるため、別の消費者が同じ出力を異なるペースで消費した場合、以前に満たされた同じストレージにアクセスします。
ストレージの一部を参照するコンシューマがなくなると、ガベージ コレクションが行われます。最適化により、コンパイラーは中間ストレージを完全に排除し、仲介者を排除できる場合があります。
1参照: Simple Generators v. Lazy Evaluation (Oleg Kiselyov、Simon Peyton-Jones、Amr Sabry 著)。