Когда использовать сортировку слиянием и когда использовать быструю сортировку? - PullRequest
15 голосов
/ 24 октября 2011

Статья в Википедии для сортировки слиянием .

Статья в Википедии для быстрой сортировки .

Обе статьи имеют отличные визуализации.

Оба имеют n * log (n) сложность.

Таким образом, очевидно, что распределение данных будет влиять на скорость сортировки. Я предполагаю, что, поскольку сравнение может так же быстро сравнивать любые два значения, независимо от их разброса, диапазон значений данных не имеет значения.

Что более важно, следует учитывать боковое распределение (направление x) относительно порядка (величина убрана).

Хороший тестовый случай, который следует рассмотреть, был бы, если бы тестовые данные имели некоторый уровень сортировки ...

Ответы [ 6 ]

14 голосов
/ 24 октября 2011

Обычно это зависит от задействованных структур данных.Быстрая сортировка обычно самая быстрая, но она не гарантирует O (n * log (n));есть вырожденные случаи, когда он становится O (n ^ 2).Сортировка кучи - обычная альтернатива;он гарантирует O (n * log (n)) независимо от начального порядка, но имеет гораздо более высокий постоянный коэффициент.Обычно он используется, когда вам нужен жесткий верхний предел времени.Некоторые более современные алгоритмы используют быструю сортировку, но пытаются распознать, когда она начинает вырождаться, и переключиться на сортировку кучи.Сортировка слиянием используется, когда структура данных не поддерживает произвольный доступ, поскольку она работает с чисто последовательным доступом (прямые итераторы, а не итераторы с произвольным доступом).Например, он используется в std::list<>::sort.Он также широко используется для внешней сортировки, где произвольный доступ может быть очень и очень дорогим по сравнению с последовательным доступом.(При сортировке файла, который не помещается в память, вы можете разбить его на куски, которые помещаются в память, отсортировать их с помощью быстрой сортировки, записать каждый файл в файл, а затем объединить отсортировать сгенерированные файлы.)

9 голосов
/ 09 июня 2012

Слияние происходит быстрее при работе со связанными списками.Это потому, что указатели могут быть легко изменены при объединении списков.Для этого требуется только один проход (O (n)) по списку.

Алгоритм быстрой сортировки Quicksort требует перемещения (обмена) данных.Хотя это может быть очень эффективным для набора данных в памяти, оно может быть намного дороже, если ваш набор данных не помещается в памяти.Результатом будет много операций ввода-вывода.

В наши дни происходит много распараллеливания.Распараллеливание Mergesort проще, чем Quicksort (на месте).Если не использовать алгоритм на месте, то сложность пространства для быстрой сортировки равна O (n), что является одинаковым для сортировки слиянием.

Таким образом, в общем случае быстрая сортировка, вероятно, более эффективна для наборов данных, которые помещаются в памяти.Для вещей, которые больше, лучше использовать mergesort.

Другим общим временем использования сортировки слиянием над быстрой сортировкой является случай, когда данные очень похожи (то есть не близки к однородности).Quicksort полагается на использование центра.В случае, когда все значения одинаковы, быстрая сортировка достигает наихудшего значения O (n ^ 2).Если значения данных очень похожи, то более вероятно, что будет выбран плохой стержень, что приведет к очень несбалансированным разделам, что приведет к O (n ^ 2) времени выполнения.Самый простой пример, если все значения в списке одинаковы.

6 голосов
/ 24 октября 2011

Существует алгоритм сортировки реального мира, называемый Timsort , который использует идею о том, что данные, встречающиеся в дикой природе, часто частично сортируются.

Алгоритм получен изсортировка слиянием и сортировка вставками, используется в CPython, Java 7 и Android.

Подробнее см. в статье Википедии .

5 голосов
/ 24 октября 2011

Из двух, используйте сортировку слиянием, когда вам нужна стабильная сортировка.Вы можете использовать измененную быструю сортировку (например, интросорт), когда вы этого не сделаете, поскольку она имеет тенденцию быть быстрее и использует меньше памяти.

Обычная старая быстрая сортировка, описанная Хоаром, довольно чувствительна к специальным убийствам производительности.случаи, которые делают его Theta(n^2), поэтому вам обычно требуется измененная версия.Вот где начинается распределение данных, так как сортировка слиянием не имеет плохих случаев.После того, как вы начнете модифицировать быструю сортировку, вы можете приступать ко всем видам различных настроек, и интросорт является одним из наиболее эффективных.Он на лету обнаруживает, является ли это убийственным случаем, и, если это так, переключается на heapsort.

На самом деле, базовая быстрая сортировка Hoare дает сбой в худшем случае для уже отсортированных данных, и поэтому ваши "хорошие тестовые случаи" с некоторымиуровень сортировки убьет его до некоторого уровня.Этот факт только для любопытства, поскольку для того, чтобы этого избежать, требуется всего лишь небольшая подстройка, ничего более сложного, чем весь процесс интросортировки.Поэтому даже проще анализировать версию, убитую отсортированными данными.

На практике в C ++ вы обычно используете std::stable_sort и std::sort, а не слишком беспокоитесь о точном алгоритме.

3 голосов
/ 24 октября 2011

В то время как Java 6 и более ранние версии используют сортировку слиянием в качестве алгоритмов сортировки, C # использует QuickSort в качестве алгоритма сортировки.

QuickSort работает лучше, чем сортировка слиянием, даже если они оба O (nlogn).Быстрая сортировка имеет меньшую константу, чем сортировка слиянием.

1 голос
/ 24 октября 2011

Помните на практике, если у вас нет очень большого набора данных и / или вы выполняете сортировку много раз, это, вероятно, не будет иметь никакого значения. При этом быстрая сортировка обычно считается самой быстрой сортировкой n * log (n). См. Этот вопрос уже задавался: Быстрая сортировка против сортировки слиянием

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...