Я начинаю изучать Haskell, и я читал this страницу на вики Haskell, который сообщает эту реализацию QSort:Улучшение наивные реализации QSort
qsort :: (Ord a) => [a] -> [a]
qsort [] = []
qsort (x:xs) = qsort less ++ [x] ++ qsort more
where less = filter (<x) xs
more = filter (>=x) xs
с последующим предупреждением, что это не самый эффективный способ сделать это и связать article, который показывает невероятно подробную версию того же алгоритма. Просто посмотрев на это, я, хотя это было не, что я изучал Haskell, и я хотел сделать лучшую версию начального qsort, не жертвуя своей элегантностью. Я в основном сосредоточены на устранении необходимости запускать filter
дважды каждый вызов, и это то, что я придумал:
filter' :: (a -> Bool) -> [a] -> ([a], [a])
filter' _ [] = ([], [])
filter' f a = filterInternal a ([], [])
where
filterInternal [] p = p
filterInternal (x:xs) (l, t)
| f x = filterInternal xs (x:l, t)
| otherwise = filterInternal xs (l, x:t)
qsort' :: (Ord a) => [a] -> [a]
qsort' [] = []
qsort' (x:xs) = qsort' less ++ [x] ++ qsort' more
where
(more, less) = filter' (>x) xs
Но я не уверен, что это действительно лучше. Я имею в виду, он работает, но как он сравнивается с исходной версией?
Не все ли нужно делать FP, чтобы избежать побочных эффектов и, в дополнение, к локальным алгоритмам? –
«Проблема» кажется, что некоторые люди считают, что вы не можете назвать это «быстрой сортировкой», если это не алгоритм на месте. По какой-то причине. – MathematicalOrchid
[1] [Автор этого сообщения] (http://stackoverflow.com/users/649287/augustss) просто развлекался реализацией быстродействующих сетей на месте, что очень похоже на C. [2] A вторая неэффективность быстродействующей сортировки с одним слоем использует '(++)' для создания промежуточных списков. [3] Для эффективной реализации без изменчивости вы можете посмотреть, что ['qsort' закомментирован в' Data.List'] (https://hackage.haskell.org/package/base-4.8.0.0/docs/src /Data-OldList.html#sort), который изначально был написан Леннартом Августсоном. – duplode