Несколько лет назад я потратил некоторое время, пытаясь максимально оптимизировать функциональную быструю сортировку. Вот что я придумал для ванили List[A]
:
def qsort[A : Ordering](ls: List[A]) = {
import Ordered._
def sort(ls: List[A])(parent: List[A]): List[A] = {
if (ls.size <= 1) ls ::: parent else {
val pivot = ls.head
val (less, equal, greater) = ls.foldLeft((List[A](), List[A](), List[A]())) {
case ((less, equal, greater), e) => {
if (e < pivot)
(e :: less, equal, greater)
else if (e == pivot)
(less, e :: equal, greater)
else
(less, equal, e :: greater)
}
}
sort(less)(equal ::: sort(greater)(parent))
}
}
sort(ls)(Nil)
}
Мне удалось сделать еще лучше с пользовательской структурой List
. Эта пользовательская структура в основном отслеживала идеальную (или почти идеальная) опорную точку для списка. Таким образом, я мог бы получить гораздо лучшую точку поворота в постоянное время, просто используя этот специальный список свойств. На практике это немного лучше, чем стандартный функциональный подход к выбору головы.
На самом деле, всё ещё довольно быстро. Это "половинный" хвост, рекурсивный (вы не можете сделать хвостовую рекурсивную быструю сортировку, не становясь действительно уродливой). Что еще более важно, он сначала перестраивается из хвостовой части, что приводит к существенно меньшему количеству промежуточных списков, чем при традиционном подходе.
Важно отметить, что это , а не , самый элегантный или самый идиоматичный способ выполнения быстрой сортировки в Scala, просто он работает очень хорошо. Вероятно, у вас будет больший успех при написании сортировки слиянием, что обычно является гораздо более быстрым алгоритмом при реализации на функциональных языках (не говоря уже о том, что он намного чище).