Вы находитесь на странице: 1из 8

ВВЕДЕНИЕ В

АЛГОРИТМЫ
СОРТИРОВКА СЛИЯНИЕМ
LTROSEGREM
ПСЕВДОКОД

ПСЕВДОКОД
ПСЕВДОКОД СЛЕГКА НЕАКУРАТЕН. РАБОЧАЯ ПРОГРАММА, ЕСТЕСТВЕННО, ДОЛЖНА ОТСЛЕЖИВАТЬ КОГДА ПРОХОЖДЕНИЕ D ИЛИ C ВЫХОДИТ ЗА

ПРЕДЕЛЫ (В ПРОЦЕССЕ ПРИРАЩЕНИЯ ИНДЕКСОВ J ИЛИ I), И ТОГДА В ЭТОЙ ТОЧКЕ ОСТАЮЩИЕСЯ ЭЛЕМЕНТЫ ДРУГОГО МАССИВА КОПИРУЮТСЯ В

ОКОНЧАТЕЛЬНЫЕ ЭЛЕМЕНТЫ B ПО ПОРЯДКУ.

MERGESORT MERGE
ВХОД: массив А из n разных чисел ВХОД: отсортированные массивы С и D (длинной n/2 каждый)
ВЫХОД: тот же отсортированный массив ВЫХОД: отсортированный массив B (длинной n)
УПРОЩАЮЩЕЕ ДОПУЩЕНИЕ: n - четное

// базовый случай (если длинна входного массив


равна 0 или 1) i := 1
С := рекурсивно отсортировать первую половину A j := 1
D := рекурсивно отсортировать вторую половину A for k := 1 to n do
Вернуть Merge( C, D ) if C[i] < D[j] then
B[k] := C[i]
i := i + 1
else
B[k] := D[j]

АЛГОРИТМЫ
j := j + 1

PAGE 01
АНАЛИЗ АЛГОРИТМА
MERGESORT

PAGE 02
ВРЕМЯ ИСПОЛНЕНИЯ
ПОДПРОГРАММЫ MERGE
Первые 1 и 2 строки выполняют инициализацию, и мы зачтем их как две
операции. Затем у нас есть цикл for, который исполняется в общей
сложности l раз. Каждая итерация цикла выполняет сравнение в строке 4,
приcваение в строке 5 либо 8 и приращение в строке 6 или в строке 9.
Индекс k цикла тоже должен увеличиваться при каждой итерации.
АНАЛИЗ Резюмируя, мы приходим к заключению, что для того, чтобы объединить два
массива длинной l/2 подпрограмма MERGE выполняет не более 4l+2
MERGE SORT операций.
Для l/2 >= 1, 4l + 2 <= 6l

Для каждой пары отсортированных входных


массивов C, D длинной l/2 подпрограмма MERGE
выполняет не более 6l операций, где l - длинна
входного массива

PAGE 03
ВРЕМЯ ИСПОЛНЕНИЯ АЛГОРИТМА MERGESORT
ТЕОРЕМА

PAGE 04
ДОКАЗАТЕЛЬСТВО ТЕОРЕМЫ
ПЛАН ДОКАЗАТЕЛЬСТВА СОСТОИТ В ТОМ, ЧТОБЫ ИСПОЛЬЗОВАТЬ
ДЕРЕВО РЕКУРСИИ, ИЛИ ДЕРЕВО РЕКУРСИВНЫХ ВЫЗОВОВ

Мы проходим от уровня к уровню, поэтому зафиксируем j-й уровень дерева рекурсии, подсчитаем количество операций на j-м
уровне, не считая операций, выполняемых последующими рекурсивными итерациями, вызываемыми с этого уровня. Таким
образов, если, как условились, игнорировать операции, выполняемые более поздними рекурсивными вызовами, делаем вывод
о том, что работа, выполняемая подзадачей на уровне j - это просто работа, выполняемая подпрограммой MERGE.

Сводя все воедино, мы можем выразить общий объем операций, выполняемых рекурсивными вызовами на уровне j (не
учитывая более поздние рекурсивные вызовы), как

Таким образом, во всех рекурсивных вызовах на j-м уровне выполняется не более 6n операций. Удивительно, но каждый
уровень дерева выполняет одинаковое количество число операций. Это обусловлено идеальным равновесием между двумя
конкурирующими силами - количество подзадач удваивается с каждым уровнем, в то время как объем вычислений,
выполняемый в расчете на подзадачу, с каждым уровнем сокращается вдвое.

Поскольку дерево имеет log2n + 1 уровней, получаем, что общее количество операций на весь алгоритм составляет

PAGE 5
РЕАЛИЗАЦИЯ НА С #

static int[] MergeSort(int[] array, int lowIndex, int highIndex) 01


{
Если начальный индекс массива меньше за последний, то есть
if (lowIndex < highIndex)
длинна входного массива больше, чем 1, вызываем рекурсивно
{
функцию, разбивая подмассив на 2 подмассива (ноходим средний
int middleIndex = (lowIndex + highIndex) / 2;
индекс массива, и разделяем массив на две части).
MergeSort(array, lowIndex, middleIndex);
MergeSort(array, middleIndex + 1, highIndex);
Merge(array, lowIndex, middleIndex, highIndex);
} 02
Когда длинна одного из подмассивов равна 1, вызываем
return array;
подпрограмму MERGE
}

PAGE 06
РЕАЛИЗАЦИЯ ПОДПРОГРАММЫ НА C#
static void Merge(int[] array, int lowIndex, int middleIndex, int highIndex)

СРАВНИВАЕМ ДВЕ ЧАСТИ {


int left = lowIndex;

МАССИВА . int right = middleIndex + 1;


int tempArray = new int[highIndex - lowIndex + 1];
LEFT - НАЧАЛЬНЫЙ ИНДЕКС int index = 0;
ПЕРВОЙ ЧАСТИ
RIGHT - НАЧАЛЬНЫЙ ИНДЕКС while ((left <= middleIndex) && (right <= highIndex))

ВТОРОЙ ЧАСТИ {

TEMPARRAY - МАССИВ - БУФЕР if (array[left] < array[right])


{
INDEX - ПРОХОД ПО TEMPARRAY tempArray[index] = array[left];
left++;
}
else

ЕСЛИ ЛЕВАЯ ЧАСТЬ


{
tempArray[index] = array[right];

ОКАЗАЛАСЬ ДЛИННЕЕ }
right++;

КОПИРУЕМ ЭЛЕМЕНТЫ ЛЕВОЙ ЧАСТИ В index++;


МАССИВ - БУФФЕР }

for (int i = right; i <= highIndex; i++)


{
tempArray[index] = array[i];
index++;
}
ЕСЛИ ПРАВАЯ ЧАСТЬ
ОКАЗАЛАСЬ ДЛИННЕЕ
for (int i = left; i <= middleIndex; i++)
{
tempArray[index] = array[i];

КОПИРУЕМ ЭЛЕМЕНТЫ ЛЕВОЙ ЧАСТИ В index++;

МАССИВ - БУФФЕР }

for (int i = 0; i < tempArray.Lenght; i++)


{
array[lowIndex + i] = tempArray[i];
}
}

PAGE 07