[英]How does quicksort in Haskell work?
在Haskell網站上 ,這個示例是quicksort實現 :
quicksort :: Ord a => [a] -> [a]
quicksort [] = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
where
lesser = filter (< p) xs
greater = filter (>= p) xs
該網站有一個解釋,但我有幾個問題,我沒有看到解決...
lesser
和greater
的創建,以<
, >=
- Ord
是一個類型類限制a
要訂購-如果沒有使用它,你就不能使用<
或>=
。 xs
一部分 - 模式匹配將輸入列表拆分為p
和xs
。 這是糟糕的ASCII可視化:
qs [5, 5, 6, 3, 1]
|
qs [3, 1] ++ [5] ++ qs [5, 6]
| | |
qs [1] ++ [3] ++ qs [] | qs [] ++ [5] ++ qs [6]
| | |
[1, 3] ++ [5] ++ [5, 6]
\ | /
\-------------------/
|
[1, 3, 5, 5, 6]
對於重新訂購,兩個元素的實際比較/交換在哪里? 這是由
Ord
(有序)類型定義本身處理的。 那么類型強制執行這個被命令的條件?
Ord
是什么意思? Ord
只是意味着a
應該與自身相比或者更嚴格的術語,例如>
, <
和==
應該為a
定義。 您可以將其視為該方法的約束。
答案是最后一種模式:
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
where
lesser = filter (< p) xs
greater = filter (>= p) xs
在運行時,程序將獲得一個數組,並且數組必須滿足以下兩種模式之一:
模式1#:它是空的,在這種情況下,該函數返回相同的空數組並停止。
模式2#:它不是空的,換句話說,有一個頭元素p
附加到尾部數組xs
。 在這樣的情況下,函數被告知把p
在中間,放的所有元素xs
是小於p
的左(通過定義lesser
)的p
和的所有元素xs
是大於或等於p
在右邊的p
。 此外,最后告訴函數將自身(即,相同的函數quicksort
)應用於lesser
(如上所述,是p
的左側的數組)和greater
(正如我們在上面定義的那樣,是數組)在p
)的右側。 正如您所看到的,這將持續到您留下零大小的數組並且模式1#終止該函數。
最后,每當這些遞歸調用終止時,函數都將返回數組:
sortedlesser ++ p ++ sortedgreater
其中sortedlesser
是起因於應用的陣列quicksort
上lesser
並且sortedgreater
是起因於應用的陣列quicksort
上greater
。
'更大'的謂詞定義了項'> = p'(樞軸),所以這並不意味着我們最終會在函數的結果列表中得到一個額外的pivot [p],因為'++ [p ]'項目?
不,這不是模式匹配的工作原理。 它說xs
中的所有元素都大於或等於p
。 根據定義, p
本身不在xs
。 如果在xs
有重復的p
,那么它們將落在右側。 請注意,此選擇將保留原始數組的自然順序。
請注意,您可以使用更短更高效的內容(因為partition
僅掃描原始列表一次)
quicksort [] = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
where (lesser, greater) = partition (< p) xs
如果您只想要一行:
qsortOneLine s = case s of{[]->[];(x:xs)->qsortOneLine [y | y<-xs, y<x] ++ x : qsortOneLine [y | y<-xs, y>=x]}
如果您想要更高性能的代碼:
qsort3 :: Ord a => [a] -> [a]
qsort3 x = qsort3' x []
qsort3' [] y = y
qsort3' [x] y = x:y
qsort3' (x:xs) y = part xs [] [x] []
where
part [] l e g = qsort3' l (e ++ (qsort3' g y))
part (z:zs) l e g
| z > x = part zs l e (z:g)
| z < x = part zs (z:l) e g
| otherwise = part zs l (z:e) g
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.