我正在学习haskell,我看到的函数定义是:
quickSort (x : xs) = (quickSort less) ++ (x : equal) ++ (quickSort more)
where less = filter (< x) xs
equal = filter (== x) xs
more = filter (> x) xs
是否可以只用一次遍历列表而不是3?
来编写它答案 0 :(得分:13)
你的意思是这样的吗?
quicksort [] = []
quicksort (x:xs) = quicksort less ++ (x : equal) ++ quicksort more
where (less, equal, more) = partition3 x xs
partition3 _ [] = ([], [], [])
partition3 x (y:ys) =
case compare y x of
LT -> (y:less, equal, more)
EQ -> (less, y:equal, more)
GT -> (less, equal, y:more)
where (less, equal, more) = partition3 x ys
请注意,这并不是真正的快速排序,因为真正的快速排序就位。
答案 1 :(得分:9)
除了:
之外似乎没什么改进qs (x:xs) = let (a,b) = partition (< x) xs in (qs a) ++ [x] ++ (qs b)
答案 2 :(得分:7)
虽然很晚,但是这个版本应该不泄漏空间(并且似乎比其他3路版本快两倍):
qsort3 xs = go xs []
where
go (x:xs) zs = part x xs zs [] [] []
go [] zs = zs
part x [] zs a b c = go a ((x : b) ++ go c zs)
part x (y:ys) zs a b c =
case compare y x of
LT -> part x ys zs (y:a) b c
EQ -> part x ys zs a (y:b) c
GT -> part x ys zs a b (y:c)
这解决了使用元组可能出现的问题,其中let (a,b) = ...
实际上已转换为let t= ...; a=fst t; b=snd t
,这导致即使在a
被消费和处理之后,仍然会保留作为元组t
的一部分,在活着的周围,可以从中读取b
- 尽管当然完全没有必要。这被称为“Wadler pair space leak”问题。或许GHC(-O2
)比这更聪明。 :)
此外,这显然使用差异列表方法(谢谢,hammar),这也使它更有效(大约比使用元组的版本快两倍)。我认为part
使用累加器参数,因为它以相反的顺序构建它们。