Посмотрим, сможем ли мы это решить!
В сортировке слиянием на каждом уровне рекурсии мы делаем следующее:
- Разделите массив пополам.
- Рекурсивно сортировать каждую половину.
- Используйте алгоритм слияния, чтобы объединить две половины вместе.
Итак, сколько сравнений выполняется на каждом шаге? Ну, шаг деления не делает никаких сравнений; он просто делит массив пополам. Шаг 2 (напрямую) не делает никаких сравнений; все сравнения выполняются рекурсивными вызовами. На шаге 3 у нас есть два массива размером n/2, и нам нужно их объединить. Для этого требуется не более n сравнений, поскольку каждый шаг алгоритма слияния выполняет сравнение, а затем потребляет некоторый элемент массива, поэтому мы не можем выполнить больше n сравнений.
Объединив это вместе, мы получим следующее повторение:
C(1) = 0
C(n) = 2C(n / 2) + n
(Как упоминалось в комментариях, линейный член точнее (n - 1), хотя это не меняет общего вывода. Мы будем использовать приведенное выше повторение в качестве верхней границы.)
Чтобы упростить это, давайте определим n = 2k и перепишем это повторение через k:
C'(0) = 0
C'(k) = 2C'(k - 1) + 2^k
Первые несколько членов здесь 0, 2, 8, 24, ... . Это выглядит примерно как k 2k, и мы можем доказать это по индукции. В качестве нашего базового случая, когда k = 0, первый член равен 0, и значение k 2k также равно 0. Для индуктивного шага предположим, что утверждение верно для некоторого k, и рассмотрим k + 1. Тогда значение равно 2(k 2k) + 2k + 1 = k 2k + 1 + 2k + 1 = (k + 1)2k + 1, поэтому утверждение верно для k + 1, что завершает индукцию. Таким образом, значение C'(k) равно k 2k. Поскольку n = 2k, это означает, что, предполагая, что n является полной степенью двойки, мы имеем, что количество сделанных сравнений равно
C(n) = n lg n
Впечатляет, но это лучше, чем быстрая сортировка! Так почему же быстрая сортировка работает быстрее, чем сортировка слиянием? Это связано с другими факторами, которые не имеют ничего общего с количеством сделанных сравнений. Прежде всего, поскольку быстрая сортировка работает на месте, а сортировка слиянием работает не на своем месте, локальность ссылок при сортировке слиянием не так хороша, как при быстрой сортировке. Это настолько важный фактор, что на практике быстрая сортировка оказывается намного лучше, чем сортировка слиянием, поскольку стоимость промаха кэша довольно высока. Кроме того, время, необходимое для сортировки массива, учитывает не только количество сравнений. Другие факторы, такие как количество перемещений каждого элемента массива, также могут иметь значение. Например, при сортировке слиянием нам нужно выделить место для буферизованных элементов, переместить элементы так, чтобы их можно было объединить, а затем снова объединить в массив. Эти ходы не учитываются в нашем анализе, но они определенно складываются. Сравните это с этапом секционирования быстрой сортировки, при котором каждый элемент массива перемещается ровно один раз и остается в пределах исходного массива. Эти дополнительные факторы, а не количество выполненных сравнений, определяют время выполнения алгоритма.
Этот анализ немного менее точен, чем оптимальный, но Википедия подтверждает, что анализ примерно n lg n и что это действительно меньше сравнений, чем в среднем случае быстрой сортировки.
Надеюсь это поможет!
person
templatetypedef
schedule
16.12.2011