Сколько сравнений делает сортировка слиянием? - PullRequest
7 голосов
/ 16 декабря 2011

Я читал, что быстрая сортировка на практике намного быстрее, чем сортировка слиянием, и причина этого кроется в скрытой константе. Итак, решение для рандомизированной сложности быстрой сортировки равно 2nlnn = 1,39nlogn, что означает, что константа быстрой сортировки равна 1,39. Но как насчет слияния? Что такое константа в слиянии?

Ответы [ 4 ]

17 голосов
/ 16 декабря 2011

Давайте посмотрим, сможем ли мы решить это!

В сортировке слиянием на каждом уровне рекурсии мы делаем следующее:

  1. Разбить массив пополам.
  2. Рекурсивная сортировка каждой половины.
  3. Используйте алгоритм слияния для объединения двух половинок.

Так сколько сравнений делается на каждом шаге? Ну, шаг деления не делает никаких сравнений; он просто разбивает массив пополам. Шаг 2 (напрямую) не делает никаких сравнений; все сравнения выполняются рекурсивными вызовами. На шаге 3 у нас есть два массива размера n / 2, и нам нужно объединить их. Это требует не более n сравнений, поскольку каждый шаг алгоритма слияния выполняет сравнение, а затем использует некоторый элемент массива, поэтому мы не можем сделать больше, чем n сравнений.

Объединяя это вместе, мы получаем следующее повторение:

C(1) = 0
C(n) = 2C(n / 2) + n

(Как уже упоминалось в комментариях, линейный термин является более точным (n - 1), хотя это не меняет общего вывода. Мы будем использовать вышеупомянутое повторение в качестве верхней границы.)

Чтобы упростить это, давайте определим n = 2 k и перепишем это повторение в терминах k:

C'(0) = 0
C'(k) = 2C'(k - 1) + 2^k

Первые несколько терминов здесь - это 0, 2, 8, 24, .... Это выглядит примерно так: k 2 k , и мы можем доказать это по индукции. В нашем базовом случае, когда k = 0, первый член равен 0, а значение k 2 k также равно 0. Для индуктивного шага предположим, что утверждение верно для некоторого k, и рассмотрим k + 1 Тогда значение равно 2 (k 2 k ) + 2 k + 1 = k 2 k + 1 + 2 k + 1 = (k + 1) 2 k + 1 , поэтому утверждение верно для k + 1, завершающего индукцию. Таким образом, значение C '(k) равно k 2 k . Так как n = 2 k , это означает, что, предполагая, что n является совершенной степенью двойки, мы получаем, что число сделанных сравнений равно

C (n) = n lg n

Впечатляюще, это лучше , чем быстрая сортировка! Так почему же быстрая сортировка быстрее, чем сортировка слиянием? Это связано с другими факторами, которые не имеют ничего общего с количеством проведенных сравнений. Прежде всего, поскольку быстрая сортировка работает на месте, в то время как сортировка слиянием работает не на своем месте, местность ссылок не так хороша в сортировке слиянием, как в быстрой сортировке. Это такой огромный фактор, что быстрая сортировка в конечном итоге оказывается намного, намного лучше, чем сортировка слиянием на практике, поскольку стоимость промаха кэша довольно велика. Кроме того, время, необходимое для сортировки массива, учитывает не только количество сравнений. Другие факторы, такие как количество перемещений каждого элемента массива, также могут быть важны. Например, в сортировке слиянием нам нужно выделить пространство для буферизованных элементов, переместить элементы так, чтобы их можно было объединить, а затем слить обратно в массив. Эти шаги не учитываются в нашем анализе, но они определенно складываются. Сравните это с шагом разбиения быстрой сортировки, который перемещает каждый элемент массива ровно один раз и остается в исходном массиве. Эти дополнительные факторы, а не количество выполненных сравнений, доминируют во время выполнения алгоритма.

Этот анализ немного менее точен, чем оптимальный, но Википедия подтверждает, что анализ примерно n lg n и что это действительно меньше сравнений, чем в среднем случае быстрой сортировки.

Надеюсь, это поможет!

3 голосов
/ 10 сентября 2012

В худшем случае и при прямой реализации число сравнений для сортировки n элементов равно

n ⌈lg n ⌉ - 2 ⌈lg n + 1

, где lg n обозначает логарифм base-2 из n .

Этот результат можно найти в соответствующей статье Википедии или в последних изданиях Искусство компьютерного программирования Дональда Кнута, и я только что записал доказательство для этого ответа .

2 голосов
/ 16 декабря 2011

Объединение двух отсортированных массивов (или списков) размером k соотв.m берет k+m-1 сравнения не более, min{k,m} в лучшем случае.(После каждого сравнения мы можем записать одно значение в цель, когда одно из двух исчерпано, больше никаких сравнений не требуется.)

Пусть C(n) будет наихудшим числом сравнений для сортировки слияниеммассив (список) из n элементов.

Тогда у нас есть C(1) = 0, C(2) = 1, что вполне очевидно.Кроме того, у нас есть рецидив

C(n) = C(floor(n/2)) + C(ceiling(n/2)) + (n-1)

Легкая индукция показывает

C(n) <= n*log_2 n

С другой стороны, легко видеть, что мы можем произвольно приблизиться к границе (для каждого ε > 0, мы можем построить случаи, требующие более (1-ε)*n*log_2 n сравнений), поэтому константа для mergesort равна 1.

0 голосов
/ 17 декабря 2011

Сортировка слиянием составляет O (n log n) и на каждом шаге, в «наихудшем» случае (для количества сравнений), выполняет сравнение.

Быстрая сортировка, с другой стороны, равна O (n ^ 2) в худшем случае.

...