Сортировка слиянием с
рекурсией.
Слиянием двух упорядоченных множеств называется процесс упорядочения объединения
данных множеств.
Теорема. Пусть даны два упорядоченных множества {A1,…,AN } и {B1,…,BN }. В рамках алгоритмов,
основанных на простых сравнениях, данные множества нельзя слить быстрее, чем
за 2N-1 сравнение в худшем
случае. Т.е. 2N-1 является нижней оценкой
времени работы алгоритма, если учитывать только время, расходуемой на сравнения
элементов множеств, и если положить время одного сравнения равным 1.
Доказательство. Пусть для конкретных заданных множеств выполняются соотношения Ai< Bi и Ai+1> Bi. Тогда отсортированное
объединение множеств выглядит следующим образом: {A1, B1, A2, B2 ,…, AN,BN }. Если хотя бы одно
из приведенных 2N-1 соотношений не будет проверено, то найдется еще хотя бы одна перестановка
элементов множества, удовлетворяющая всем приведенным соотношениям. Например,
если не будет проверено соотношение A2> B1, то следующая
последовательность будет удовлетворять всем остальным соотношениям:
{A1, A2, B1, B2 ,…, AN,BN }.
Более того, отношения между всеми остальными элементами останутся
неизменными. Т.о. мы доказали необходимость всех
приведенных сравнений для правильного упорядочивания указанных данных, из чего
непосредственно вытекает требуемое.
¢
Дословно так же доказывается следующая теорема
Теорема. Пусть даны два упорядоченных множества {A1,…,AN +1} и {B1,…,BN }. В рамках алгоритмов,
основанных на простых сравнениях, данные множества нельзя слить быстрее, чем
за 2N сравнений элементов множества в худшем
случае.
Алгоритм слияния. Пусть даны два упорядоченных множества {A1,…,AM} и {B1,…,BN }. Введем индексы i, j и k . Изначально i=1, j=1 и k=1 .
Пока i£M и j£N:
Если Ai < Bj то
Сk++ = Ai++
иначе
Сk++ = Bi++
Конец Если
Конец Цикла
Пока I £ M:
Сk++ = Ai++
Конец Цикла
Пока j £ N:
Сk++ = Bi++
Конец Цикла
Легко увидеть, что в данном алгоритме элементы множества
сравниваются не более M+N-1 раз. Т.о.
данный алгоритм оказывается строго оптимальным по числу сравнений элементов
сортируемого множества (по крайней мере в алгоритмах,
основанных на простых сравнениях).
Вопрос на понимание: можно ли два упорядоченных
множества {A1,…,AN } и {B1,…,BN} слить быстрее чем
за 2N-1 операций сравнения
в каком либо алгоритме, основанном операциях сравнения? … на операциях простого
сравнения?
Алгоритм сортировки слиянием. Обозначим данный алгоритм Z(A1,…,AM ), где {A1,…,AN } – сортируемое множество
элементов. Алгоритм имеет следующий вид
Если число обрабатываемых элементов £ 1 то
ВЫЙТИ
M1 = [ M/2 ]; M2 = M-M1; // размеры половин массива
Z(A1,…,AM1 )
Z(AM1+1,…,AM )
Слить упорядоченные множества {A1,…,A M1 } и { AM1+1,…,AM } в массив B.
Скопировать массив B в массив {A1,…,AN }.
Легко видеть, что данный алгоритм решает задачу за время O(N log2 N), где N – количество элементов в
сортируемом массиве.
Недостатком алгоритма является необходимость использования дополнительного
массива с размером, равным размеру исходного массива.
Сортировка слиянием без
рекурсии.
Предыдущий алгоритм можно модифицировать так, что он уже не будет
использовать рекурсию. Действительно. Рассмотрим последовательно все пары
элементов в сортируемом массиве. Каждый из элементов в паре представляет собой
уже отсортированный массив длины 1, поэтому эти массивы
(пока длины 1) можно слить в упорядоченные куски длины 2.
Далее мы рассматриваем уже пары упорядоченных массивов длины 2 и
сливаем их в массивы длины 4. И т.д.
Отметим, что при этих операциях на k-том проходе по упорядочиваемому массиву на правом конце массива мы будем
получать либо ситуацию, когда у правого оставшегося куска (длины £ 2k ) вообще нет парного куска для
слияния, либо кусок есть и его длина £ 2k. В первом случае делать
вообще ничего не нужно, а во втором следует стандартным способом сливать куски,
возможно, существенно различной длины.
Легко видеть, что данный алгоритм решает задачу за время O(N log2 N), где N – количество элементов в сортируемом
массиве.