Каковы случаи использования, когда какой-то конкретный алгоритм сортировки предпочтительнее других - сортировка слиянием, QuickSort, heapsort, intro sort и т. Д.?
Существует ли рекомендуемое руководство по их использованию в зависимости от размера, типа структуры данных, доступной памяти и кэша, а также производительности процессора?
Ответы:
Во-первых, определение, поскольку оно очень важно: стабильная сортировка - это та, которая гарантированно не переупорядочивает элементы с одинаковыми ключами.
Рекомендации:
Быстрая сортировка: когда вам не нужна стабильная сортировка, а средняя производительность важнее, чем худшая. Быстрая сортировка - это O (N log N) в среднем, O (N ^ 2) в худшем случае. Хорошая реализация использует O (log N) вспомогательное хранилище в форме стекового пространства для рекурсии.
Сортировка слиянием: если вам нужна стабильная сортировка O (N log N), это ваш единственный вариант. Единственным недостатком является то, что он использует O (N) вспомогательное пространство и имеет немного большую константу, чем быстрая сортировка. Есть несколько видов слияний на месте, но AFAIK все они либо нестабильны, либо хуже, чем O (N log N). Даже O (N log N) на месте сортировки имеют намного большую константу, чем обычная сортировка слиянием, что они скорее теоретические курьезы, чем полезные алгоритмы.
Сортировка кучи: когда вам не нужна стабильная сортировка, и вы больше заботитесь о производительности в худшем случае, чем в среднем. Он гарантированно равен O (N log N) и использует O (1) вспомогательное пространство, что означает, что вы не будете неожиданно исчерпывать пространство кучи или стека на очень больших входах.
Introsort: это быстрая сортировка, которая переключается на сортировку кучи после определенной глубины рекурсии, чтобы обойти O (N ^ 2) наихудшего случая быстрой сортировки. Это почти всегда лучше, чем обычная старая быстрая сортировка, поскольку вы получаете средний случай быстрой сортировки с гарантированной производительностью O (N log N). Вероятно, единственная причина использовать сортировку кучи вместо этого - в системах с жестким ограничением памяти, где пространство стека O (log N) практически значимо.
Вставка сортировки : когда N гарантированно будет небольшим, в том числе в качестве базового варианта быстрой сортировки или сортировки слиянием. Хотя это O (N ^ 2), оно имеет очень маленькую константу и является устойчивой сортировкой.
Сортировка по пузырям, сортировка по выбору : когда вы делаете что-то быстрое и грязное, и по какой-то причине вы не можете просто использовать алгоритм сортировки стандартной библиотеки. Единственное преимущество, которое они имеют перед сортировкой вставок, заключается в том, что их немного проще реализовать.
Несопоставимые сортировки: при некоторых довольно ограниченных условиях можно преодолеть барьер O (N log N) и отсортировать по O (N). Вот несколько случаев, когда стоит попробовать:
Подсчет сортировки: когда вы сортируете целые числа с ограниченным диапазоном.
Сортировка по корням: когда log (N) значительно больше, чем K, где K - количество радикальных цифр.
Сортировка по сегментам: когда вы можете гарантировать, что ваши входные данные распределены приблизительно равномерно.
источник
Быстрая сортировка, как правило, самая быстрая в среднем, но она имеет довольно неприятные наихудшие варианты поведения. Так что, если вы должны гарантировать, что плохие данные вам не предоставлены
O(N^2)
, вам следует их избегать.Сортировка слиянием использует дополнительную память, но особенно подходит для внешней сортировки (то есть огромных файлов, которые не помещаются в память).
Сортировка кучи может сортировать на месте и не имеет худшего квадратичного поведения, но в среднем медленнее, чем быстрая сортировка в большинстве случаев.
Там, где задействованы только целые числа в ограниченном диапазоне, вы можете использовать некоторую сортировку по осям, чтобы сделать это очень быстро.
В 99% случаев вы будете в порядке с сортировками библиотек, которые обычно основаны на быстрой сортировке.
источник
На странице Википедии об алгоритмах сортировки есть отличная сравнительная таблица.
http://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms
источник
То, что предоставленные ссылки на сравнения / анимации не учитывают, - это когда объем данных превышает доступную память - в этот момент количество проходов по данным, т. Е. Затраты на ввод-вывод, преобладают во время выполнения. Если вам нужно это сделать, ознакомьтесь с «внешней сортировкой», которая обычно охватывает варианты сортировки слиянием и кучей.
http://corte.si/posts/code/visualisingsorting/index.html и http://corte.si/posts/code/timsort/index.html также содержат несколько интересных изображений, сравнивающих различные алгоритмы сортировки.
источник
@dsimcha wrote: Подсчет сортировки: когда вы сортируете целые числа с ограниченным диапазоном
Я бы изменил это на:
Подсчет сортировки: когда вы сортируете положительные целые числа (0 - Integer.MAX_VALUE-2 из-за отверстия)
Вы всегда можете получить максимальные и минимальные значения в качестве эвристики эффективности и за линейное время.
Также вам нужно как минимум n дополнительного пространства для промежуточного массива, и он, очевидно, стабилен.
(хотя это на самом деле позволит MAX_VALUE-2) увидеть: максимальный размер массивов Java?
Также я бы объяснил, что сложность радикальной сортировки равна O (wn) для n ключей, которые являются целыми числами размера слова w. Иногда w представляется как константа, что делает радикальную сортировку лучше (для достаточно большого n), чем лучшие алгоритмы сортировки на основе сравнения, которые все выполняют O (n log n) сравнений для сортировки n ключей. Тем не менее, в общем случае w нельзя считать константой: если все n ключей различны, то для того, чтобы машина с произвольным доступом могла хранить их в памяти, w должен иметь как минимум log n, что в лучшем случае дает сложность O (п лог п). (из википедии)
источник