<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=217.66.152.0&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=217.66.152.0&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/217.66.152.0"/>
		<updated>2026-05-19T14:02:21Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%BB%D0%B8%D1%8F%D0%BD%D0%B8%D0%B5%D0%BC&amp;diff=46939</id>
		<title>Сортировка слиянием</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_%D1%81%D0%BB%D0%B8%D1%8F%D0%BD%D0%B8%D0%B5%D0%BC&amp;diff=46939"/>
				<updated>2015-05-25T19:46:03Z</updated>
		
		<summary type="html">&lt;p&gt;217.66.152.0: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Сортировка слиянием''' (англ. ''Merge sort'') {{---}} алгоритм сортировки, пред­ло­женный Джо­ном фон Ней­ма­ном в 1945 го­ду.&lt;br /&gt;
&lt;br /&gt;
Это устойчивый алгоритм, использующий &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; дополнительной памяти и работающий за &amp;lt;tex&amp;gt;O(n&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\log n)&amp;lt;/tex&amp;gt; времени.&lt;br /&gt;
&lt;br /&gt;
==Принцип работы==&lt;br /&gt;
[[Файл:Merging_two_arrays.png|270px|right|thumb|Пример работы процедуры слияния.]]&lt;br /&gt;
Алгоритм использует принцип «разделяй и властвуй»: задача разбивается на подзадачи меньшего размера, которые решаются по отдельности, после чего их решения комбинируются для получения решения исходной задачи. Конкретно процедуру сортировки слиянием можно описать следующим образом:&lt;br /&gt;
&lt;br /&gt;
# Если в рассматриваемом массиве один элемент, то он уже отсортирован {{---}} алгоритм завершает работу.&lt;br /&gt;
# Иначе массив разбивается на две части, которые сортируются рекурсивно.&lt;br /&gt;
# После сортировки двух частей массива к ним применяется процедура слияния, которая по двум отсортированным частям получает исходный отсортированный массив.&lt;br /&gt;
&lt;br /&gt;
===Слияние двух массивов===&lt;br /&gt;
У нас есть два массива &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; (фактически это будут две части одного массива, но для удобства будем писать, что у нас просто два массива). Нам надо получить массив &amp;lt;tex&amp;gt;c&amp;lt;/tex&amp;gt; размером &amp;lt;tex&amp;gt;|a| + |b|&amp;lt;/tex&amp;gt;. Для этого можно применить процедуру слияния. Эта процедура заключается в том, что мы сравниваем элементы массивов (начиная с начала) и меньший из них записываем в финальный. И затем, в массиве у которого оказался меньший элемент, переходим к следующему элементу и сравниваем теперь его. В конце, если один из массивов закончился, мы просто дописываем в финальный другой массив. После мы наш финальный массив записываем заместо двух исходных и получаем отсортированный участок.&lt;br /&gt;
&lt;br /&gt;
Множество отсортированных списков с операцией &amp;lt;tex&amp;gt;\mathrm{merge}&amp;lt;/tex&amp;gt; является [[Моноид|моноидом]], где нейтральным элементом будет пустой список.&lt;br /&gt;
&lt;br /&gt;
Ниже приведён псевдокод процедуры слияния, который сливает две части массива &amp;lt;tex&amp;gt;a&amp;lt;/tex&amp;gt; {{---}} &amp;lt;tex&amp;gt;[left; mid)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;[mid; right)&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 '''function''' merge(a : '''int[n]'''; left, mid, right : '''int'''):&lt;br /&gt;
     it1 = 0&lt;br /&gt;
     it2 = 0&lt;br /&gt;
     result : '''int[right - left]'''&lt;br /&gt;
   &lt;br /&gt;
     '''while''' left + it1 &amp;lt; mid '''and''' mid + it2 &amp;lt; right&lt;br /&gt;
         '''if''' a[left + it1] &amp;lt; a[mid + it2]&lt;br /&gt;
             result[it1 + it2] = a[left + it1]&lt;br /&gt;
             it1 += 1&lt;br /&gt;
         '''else'''&lt;br /&gt;
             result[it1 + it2] = a[mid + it2]&lt;br /&gt;
             it2 += 1&lt;br /&gt;
   &lt;br /&gt;
     '''while''' left + it1 &amp;lt; mid&lt;br /&gt;
         result[it1 + it2] = a[left + it1]&lt;br /&gt;
         it1 += 1&lt;br /&gt;
   &lt;br /&gt;
     '''while''' mid + it2 &amp;lt; right&lt;br /&gt;
         result[it1 + it2] = a[mid + it2]&lt;br /&gt;
         it2 += 1&lt;br /&gt;
   &lt;br /&gt;
     '''for''' i = 0 '''to''' it1 + it2&lt;br /&gt;
         a[left + i] = result[i]&lt;br /&gt;
&lt;br /&gt;
===Рекурсивный алгоритм===&lt;br /&gt;
[[Файл:Merge sort1.png|300px|right|thumb|Пример работы рекурсивного алгоритма сортировки слиянием]]&lt;br /&gt;
Функция сортирует подотрезок массива с индексами в полуинтервале &amp;lt;tex&amp;gt;[left; right)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code style=&amp;quot;display: inline-block&amp;quot;&amp;gt;&lt;br /&gt;
 '''function''' mergeSortRecursive(a : '''int[n]'''; left, right : '''int'''):&lt;br /&gt;
     '''if''' left + 1 &amp;gt;= right&lt;br /&gt;
         '''return'''&lt;br /&gt;
     mid = (left + right) / 2&lt;br /&gt;
     mergeSortRecursive(a, left, mid)&lt;br /&gt;
     mergeSortRecursive(a, mid, right)&lt;br /&gt;
     merge(a, left, mid, right)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
===Итеративный алгоритм===&lt;br /&gt;
[[Файл:Merge sort itearative.png|300px|right|thumb|Пример работы итеративного алгоритма сортировки слиянием]]&lt;br /&gt;
При итеративном алгоритме используется на &amp;lt;tex&amp;gt;O(\log n)&amp;lt;/tex&amp;gt; меньше памяти, которая раньше тратилась на рекурсивные вызовы.&lt;br /&gt;
&amp;lt;code style=&amp;quot;display: inline-block&amp;quot;&amp;gt;&lt;br /&gt;
 '''function''' mergeSortIterative(a : '''int[n]'''):&lt;br /&gt;
     '''for''' i = 1 '''to''' n, i *= 2&lt;br /&gt;
         '''for''' j = 0 '''to''' n - i, j += 2 * i&lt;br /&gt;
             merge(a, j, j + i, min(j + 2 * i, n))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Время работы==&lt;br /&gt;
Чтобы оценить время работы этого алгоритма, составим рекуррентное соотношение. Пускай &amp;lt;tex&amp;gt;T(n)&amp;lt;/tex&amp;gt; {{---}} время сортировки массива длины &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;, тогда для сортировки слиянием справедливо &amp;lt;tex&amp;gt;T(n)=2T(n/2)+O(n)&amp;lt;/tex&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; {{---}} время, необходимое на то, чтобы слить два массива. Распишем это соотношение:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;T(n)=2T(n/2)+O(n)=4T(n/4)+2O(n)=\dots=2^kT(1)+kO(n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Осталось оценить &amp;lt;tex&amp;gt;k&amp;lt;/tex&amp;gt;. Мы знаем, что &amp;lt;tex&amp;gt;2^k=n&amp;lt;/tex&amp;gt;, а значит &amp;lt;tex&amp;gt;k=\log n&amp;lt;/tex&amp;gt;. Уравнение примет вид &amp;lt;tex&amp;gt;T(n)=nT(1)+ \log n&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Так как &amp;lt;tex&amp;gt;T(1)&amp;lt;/tex&amp;gt; {{---}} константа, то &amp;lt;tex&amp;gt;T(n)=O(n)+\log n &amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;O(n)=O(n\log n)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Сравнение с другими алгоритмами==&lt;br /&gt;
===Достоинства===&lt;br /&gt;
* Устойчивая,&lt;br /&gt;
* Сортировка связанных списков,&lt;br /&gt;
* Быстрая сортировка больших файлов из-за того, что память &amp;quot;любит&amp;quot; работать с последовательными данными.&lt;br /&gt;
===Недостатки===&lt;br /&gt;
* При любых входных данных время работы {{---}} &amp;lt;tex&amp;gt;O(n\log{n})&amp;lt;/tex&amp;gt;,&lt;br /&gt;
* требуется дополнительно &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; памяти, но можно модифицировать до &amp;lt;tex&amp;gt;O(1)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Сортировка кучей]]&lt;br /&gt;
* [[Быстрая сортировка]]&lt;br /&gt;
* [[Timsort]]&lt;br /&gt;
*[[Cортировка слиянием с использованием O(1) дополнительной памяти]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/Mergesort Википедия {{---}} сортировка слиянием]&lt;br /&gt;
*[http://www.sorting-algorithms.com/merge-sort Визуализатор]&lt;br /&gt;
*[http://ru.wikibooks.org/wiki/%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B_%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D1%81%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B8_%D1%81%D0%BB%D0%B8%D1%8F%D0%BD%D0%B8%D0%B5%D0%BC Викиучебник {{---}} Примеры реализации на различных языках программирования]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Сортировки]]&lt;br /&gt;
[[Категория: Сортировки на сравнениях]]&lt;/div&gt;</summary>
		<author><name>217.66.152.0</name></author>	</entry>

	</feed>