Я думаю, что ответ @comingstorm в значительной степени на носу, но вот еще немного информации об истории функции сортировки GHC.
В исходном коде Data.OldList
вы можете найти реализацию из sort
и убедиться, что это сортировка слиянием. Чуть ниже определения в этом файле следующий комментарий:
Quicksort replaced by mergesort, 14/5/2002.
From: Ian Lynagh <igloo@earth.li>
I am curious as to why the List.sort implementation in GHC is a
quicksort algorithm rather than an algorithm that guarantees n log n
time in the worst case? I have attached a mergesort implementation along
with a few scripts to time it's performance...
Итак, первоначально была использована функциональная быстрая сортировка (и функция qsort
все еще там, но закомментирована). Тесты Яна показали, что его сортировка слиянием была конкурентоспособной с быстрой сортировкой в случае «случайного списка» и значительно превзошла его в случае уже отсортированных данных. Позже, согласно дополнительным комментариям в этом файле, версия Яна была заменена другой реализацией, которая была примерно в два раза быстрее.
Основная проблема с оригинальным qsort
заключалась в том, что он не использовал случайный пивот. Вместо этого он поворачивается на первое значение в списке. Это, очевидно, довольно плохо, поскольку подразумевает, что производительность будет наихудшим (или близким) для отсортированного (или почти отсортированного) ввода. К сожалению, есть пара сложностей при переходе от «поворот на первом» к альтернативе (или случайным образом, или - как в вашей реализации - где-то в «середине»). На функциональном языке без побочных эффектов управление псевдослучайным вводом представляет собой небольшую проблему, но, допустим, вы решили это (возможно, встроив генератор случайных чисел в функцию сортировки). У вас все еще есть проблема, заключающаяся в том, что при сортировке неизменяемого связанного списка, нахождении произвольного центра и последующем разбиении на его основе потребуется несколько обходов списка и копий подсписков.
Я думаю, что единственный способ реализовать предполагаемые преимущества быстрой сортировки - это записать список в вектор, отсортировать его по месту (и пожертвовать стабильностью сортировки) и записать его обратно в список. Я не понимаю, что это может быть общей победой. С другой стороны, если у вас уже есть данные в векторе, то быстрая сортировка на месте определенно была бы разумным вариантом.