1632
правки
Изменения
м
='''Сортировка слиянием=[[Файл:Merge sort animation2.gif|right|380px|thumb|Действие алгоритма на примере сортировки случайных точек.]]'''Сортировка слиянием(англ. ''Merge sort'' — Сортировка слиянием — вероятно) {{---}} алгоритм сортировки, один из самых простых алгоритмов сортировки использующий <tex>O(n)</tex> дополнительной памяти и работающий за <tex>O(среди «быстрых» алгоритмовn\log(n)). Особенностью этого алгоритма является то, что он работает с элементами массива преимущественно последовательно, благодаря чему именно этот алгоритм используется при сортировке в системах с различными аппаратными ограничениями</tex> времени.
Кроме того, сортировка слиянием — чуть ли не единственный алгоритм, который может быть эффективно использован для сортировки таких структур данных, как связанные списки==Принцип работы==[[Файл:Merging_two_arrays. Последовательная работа с элементами массива значительно увеличивает скорость сортировки в системах с кэшированиемpng|270px|right|thumb|Пример работы процедуры слияния.]]
Сортировка слиянием — стабильный алгоритм сортировки[[Файл:Merge sort1. Это означает, что порядок «равных» элементов не изменяется в результате работы алгоритма. В некоторых задачах это свойство достаточно важно.Этот алгоритм был предложен Джоном фон Нейманом в 1945 годуpng|300px|right|thumb|Пример работы рекурсивного алгоритма сортировки слиянием]]
=Принцип [[Файл:Merge sort itearative.png|300px|right|thumb|Пример работы=Эта сортировка — хороший пример использования принципа «разделяй и властвуй». Сначала задача разбивается на несколько подзадач меньшего размера. Затем эти задачи решаются с помощью рекурсивного вызова или непосредственно, если их размер достаточно мал. Наконец, их решения комбинируются, и получается решение исходной задачи.итеративного алгоритма сортировки слиянием]]
Для решения задачи сортировки эти три этапа выглядят такАлгоритм использует принцип «разделяй и властвуй»:*Сортируемый массив задача разбивается на две части примерно одинакового подзадачи меньшего размера;*Каждая из получившихся частей сортируется отдельно, обычно - рекурсивнокоторые решаются по отдельности, тем же самым алгоритмом;*Два упорядоченных массива половинного размера соединяются в одинпосле чего их решения комбинируются для получения решения исходной задачи.Конкретно процедуру сортировки слиянием можно описать следующим образом:
Рекурсивное разбиение задачи # Если в рассматриваемом массиве один элемент, то он уже отсортирован {{---}} алгоритм завершает работу.# Иначе массив разбивается на меньшие происходит до тех пордве части, пока размер которые сортируются рекурсивно.# После сортировки двух частей массива не достигнет единицы <br>(любой к ним применяется процедура слияния, которая по двум отсортированным частям получает исходный отсортированный массив длины 1 можно считать упорядоченным).
a = 0; b = 0; While (a < <tex>n_a</tex>) and (b < <tex>n_b</tex>) If A[a] Множество отсортированных списков с операцией <tex>\leqslantmathrm{merge}</tex> B[b] C[a + b] = Aявляется [a]; a = a + 1; Else C[a + bМоноид|моноидом] = B[b]; b = b + 1; End; End; If a < <tex>n_a</tex> Copy remain part of A Else Copy remain part of B End;, где нейтральным элементом будет пустой список.
Пример работы алгоритма показан ===Итеративный алгоритм===При итеративном алгоритме используется на <tex>O(\log n)</tex> меньше памяти, которая раньше тратилась на рисункерекурсивные вызовы.<code style="display:inline-block"> '''function''' mergeSortIterative(a : '''int[[Файлn]'''):Merge sort1.png|500px|center|thumb|Пример работы рекурсивного алгоритма сортировки слиянием]] '''for''' i = 1 '''to''' n, i *= 2 '''for''' j = 0 '''to''' n - i, j += 2 * i merge(a, j, j + i, min(j + 2 * i, n))</code>
<tex>T(n) = 2T(n/2) + O(n) = 4T(n/4) + 2*O2O(n) = ... \dots= 2^kTT(1) + kO\log(n)O(n)=O(n\log(n))</tex>.
Осталось оценить ==Сравнение с другими алгоритмами==Достоинства:* устойчивая,* можно написать эффективную [[Многопоточная сортировка слиянием|многопоточную сортировку слиянием]],* сортировка данных, расположенных на периферийных устройствах и не вмещающихся в оперативную память<texref>k<[http://tex>en.wikipedia. Мы знаем, что <tex>2^k=n<org/wiki/tex>, а значит <tex>k=\log(n)External_sorting Wikipedia {{---}} External sorting]</texref>. Уравнение примет вид Недостатки:* требуется дополнительно <tex>T(n)=nT(1)+ \log(n)O(n)</tex>. Так как памяти, но можно модифицировать до <tex>TO(1)</tex> - константа, то <tex>T(n). ==См. также==* [[Сортировка кучей]]* [[Быстрая сортировка]]* [[Timsort]]* [[Cортировка слиянием с использованием O(n)+\log(n)O(n1)дополнительной памяти]] ==Примечания==O(n\log(n))<references/tex> ==Источники информации==*[http://ru.wikipedia.org/wiki/Mergesort Википедия {{---}} сортировка слиянием]*[http://www.sorting-algorithms.com/merge-sort Визуализатор]*[https://ru.wikibooks.org/wiki/Примеры_реализации_сортировки_слиянием Викиучебник {{---}} Примеры реализации на различных языках программирования]
=Ссылки=
*[http://ru.wikipedia.org/wiki/Mergesort| Википедия - сортировка слиянием]
*[http://iproc.ru/parallel-programming/lection-6/| Сортировка слиянием]
rollbackEdits.php mass rollback
===Слияние 2-х двух массивов===Допустим, у У нас есть два отсортированных массива А и B размерами <tex>N_a a</tex> и <tex>N_b b</tex> соответственно(фактически это будут две части одного массива, но для удобства будем писать, и мы хотим объединить их элементы в один большой отсортированный что у нас просто два массива). Нам надо получить массив C <tex>c</tex> размером <tex>N_a |a| + N_b |b|</tex> . Для этого можно применить процедуру слияния, суть которой слияния. Эта процедура заключается в повторяющемся «отделении» элементатом, наименьшего что мы сравниваем элементы массивов (начиная с начала) и меньший из двух имеющихся них записываем в финальный. И затем, в началах исходных массивовмассиве у которого оказался меньший элемент, переходим к следующему элементу и присоединении этого элемента к концу результирующего массивасравниваем теперь его. Элементы мы переносим до тех порВ конце, пока если один из исходных массивов не закончитсязакончился, мы просто дописываем в финальный другой массив. После этого оставшийся «хвост» одного из входных массивов дописывается в конец результирующего массива. Пример работы процедуры показан на рисунке:[[Файл:Mergearrмы наш финальный массив записываем заместо двух исходных и получаем отсортированный участок.png|center|500px|thumb|Пример работы процедуры слияния.]]<br>Алгоритм слияния формально можно записать следующим образом:
Ниже приведён псевдокод процедуры слияния, который сливает две части массива <tex>a</tex> {{---}} <tex>[left; mid)</tex> и <tex>[mid; right)</tex>
<code style="display: inline-block">
'''function''' merge(a : '''int[n]'''; left, mid, right : '''int'''):
it1 = 0
it2 = 0
result : '''int[right - left]'''
'''while''' left + it1 < mid '''and''' mid + it2 < right
'''if''' a[left + it1] < a[mid + it2]
result[it1 + it2] = a[left + it1]
it1 += 1
'''else'''
result[it1 + it2] = a[mid + it2]
it2 += 1
'''while''' left + it1 < mid
result[it1 + it2] = a[left + it1]
it1 += 1
'''while''' mid + it2 < right
result[it1 + it2] = a[mid + it2]
it2 += 1
'''for''' i = 0 '''to''' it1 + it2
a[left + i] = result[i]
</code>
===Рекурсивный алгоритм===Проще всего формализовать этот алгоритм рекурсивным способом. Функция Функция сортирует участок подотрезок массива от элемента с номером a до элемента с номером bиндексами в полуинтервале <tex>[left; right)</tex>.<code style="display:inline-block"> Function MergeSort'''function''' mergeSortRecursive(a: '''int[n]'''; left,bright : '''int'''): If b '''if''' left + 1 >= a then Exit;right '''return''' c mid = (a left + bright)/2; Mergesort mergeSortRecursive(a,cleft, mid); MergeSort mergeSortRecursive(c + 1a, mid,bright); Merge fragments merge(a,c) and (c + 1left, mid,bright); End</code>
==Время работы==Чтобы оценить время работы этого алгоритма, составим рекуррентное соотношение. Пускай <tex>T(n)</tex> {{--- }} время сортировки массива длины <tex>n</tex>, тогда для сортировки слиянием справедливо <tex>T(n)=2T(n/2)+O(n)</tex> <br>(<tex>O(n)</tex> {{-- это -}} время, необходимое на то, чтобы слить два массива)длины <tex>n</tex>. Распишем это соотношение:
[[Категория: Дискретная математика и алгоритмы]]
[[Категория: Сортировки]]
[[Категория: Сортировки на сравнениях]]