
- •1. Cтруктуры данных и алгоритмы
- •1.1. Понятие структур данных и алгоритмов
- •1.2. Информация и ее представление в памяти
- •1.3. Классификация структур данных
- •1.4. Операции над структурами данных
- •1.5. Структурность данных и технология программирования
- •2. Простые структуры данных
- •2.1. Числовые типы
- •2.1.1. Целые типы
- •2.1.2. Вещественные типы
- •1). Десятичное число 15.375;
- •2). Десятичное число -0.5;
- •3). Десятичное число -25.75;
- •4). Число 0.0;
- •5). Числа верхней и нижней границ положительного диапазона
- •2.1.3. Операции над числовыми типами
- •2.2. Битовые типы
- •2.3. Логический тип
- •2.4. Символьный тип
- •2.5. Перечислимый тип
- •2.6. Интервальный тип
- •2.7. Указатели
- •2.7.1. Физическая структура указателя
- •2.7.2. Представление указателей в языках программирования
- •2.7.3. Операции над указателями.
- •3. Статические структуры данных
- •3.1. Векторы
- •3.2. Массивы
- •3.2.1. Логическая структура
- •3.2.2. Физическая структура
- •3.2.3. Операции
- •3.3 Множества
- •3.3.1 Множества и математика
- •3.3.1.1 Способы задания множеств
- •3.3.1.2 Операции над множествами
- •3.3.1.3 Множественный тип и его свойства
- •3.3.1.4 Переменные и константы множественных типов
- •3.3.1.5. Выражения множественного типа
- •3.3.2. Представление множеств в памяти эвм
- •3.3.2.1. Числовые множества
- •3.3.2.2. Символьные множества
- •3.3.2.3. Множество из элементов перечислимого типа
- •3.3.2.4. Множество от интервального типа
- •3.3.2.5. Операции над множествами
- •3.4. Записи
- •3.4.1. Логическое и машинное представление записей
- •3.4.2. Операции над записями
- •3.5. Таблицы
- •3.6.2. О сложности алгоритмов
- •3.6.3. Сортировка подсчетом
- •3.6.4. Сортировка включением
- •3.6.4.1. Простое включение
- •3.6.4.2.Метод Шелла (модифицированный)
- •3.6.5. Сортировка извлечением
- •3.6.5.1.Простое извлечение
- •3.6.5.2.Древесная сортировка(модифицированный)
- •3.6.6. Сортировка обменами
- •3.6.6.1. Пузырьковая сортировка
- •3.6.6.2. Быстрая сортировка (Хоара) (модифицированный)
- •3.6.7. Сортировка слиянием
- •3.6.8. Сортировка распределением
- •3.6.8.1. Вырожденное распределение
- •3.6.8.2. Сортировка распределением
- •3.6.9. Сравнительный анализ
- •3.7. Операции логического уровня над статическими структурами. Поиск
- •3.7.1. Линейный (последовательный) поиск
- •3.7.2. Быстрый последовательный список
- •3.7.3. Дихотомический (бинарный) поиск
- •3.7.4. Интерполяционный поиск
3.6.7. Сортировка слиянием
Этот метод сортирует массив последовательным слиянием пар уже отсортированных подмассивов, поэтому его и назвали сортировкой слиянием.
Пусть k - положительное целое число. Разобьем массив A[1]..A[n] на отрезки длины k. (Первый - A[1]..A[k], затем A[k+1]..A[2k] и т.д.) Последний отрезок будет неполным, если n не делится нацело на k. Назовем массив k-упорядоченным, если каждый из этих отрезков длины k упорядочен.
Ясно, что любой массив 1-упорядочен, так как его подмассивы длиной 1 можно считать упорядоченными. Если массив k-упорядочен и n<=k, то он упорядочен.
Теперь запишем общую схему алгоритма:
k:=1;
while k < n do
begin
... преобразовать k-упорядоченный массив
в 2k-упорядоченный;
k := 2 * k;
end;
Рассмотрим процедуру преобразования k-упорядоченного массива в 2k-упорядоченный. Сгруппируем все подмассивы длины k в пары подмассивов. Теперь пару упорядоченных подмассивов сольем в один упорядоченный подмассив. Проделав это со всеми парами, мы получим 2k-упорядоченный массив:
t:=0;
while t + k < n do
begin
p := t;
q := t+k;
...r := min(t+2*k, n); {в паскале нет функции min }
...сливаем два подмассива A[p..q-1] и A[q..r]
t := r;
end;
Слияние требует вспомогательного массива для записи результатов слияния - обозначим его B. Через p0 и q0 обозначим номера последних элементов участков, подвергшихся слиянию, s0 - последний записанный в массив B элемент. На каждом шаге слияния производится одно из двух действий:
B[s0+1]:=A[p0+1];
Inc(p0);
Inc(s0);
или
B[s0+1]:=A[q0+1];
Inc(q0);
Inc(s0);
Первое действие (взятие элемента из первого отрезка) может производиться при двух условиях:
(1) первый отрезок не кончился (p0 < q);
(2) второй отрезок кончился (q0 = r) или не кончился, но элемент в нем не меньше [(q0 < r) и (A[p0+1] <= A[q0+1])].
Аналогично для второго действия. Итак, получаем
p0 := p; q0 := q; s0 := p;
while (p0<>q)or(q0<>r) do
begin
if (p0<q)and((q0=r)or((q0 < r) and
(A[p0+1]<=A[q0+1]))) then
begin
B[s0+1] := A[p0+1]; Inc(p0); Inc(s0);
end else
begin
B[s0+1] := A[q0+1]; Inc(q0); Inc(s0);
end;
end;
(Если оба отрезка не кончены и первые невыбранные элементы в них равны, то допустимы оба действия; в программе выбрано первое.)
Осталось собрать программу в одно целое:
k := 1;
while k < N do
begin
t := 0;
while t+k < N do
begin
p := t; q := t+k;
if t+2*k>N then r := N else r := t+2*k;
p0 := p; q0 := q; s0 := p;
while (p0<>q) or (q0<>r) do
begin
if (p0<q) and ((q0=r)or((q0<r)and
(A[p0+1]<=A[q0+1]))) then
begin
B[s0+1] := A[p0+1];
Inc(p0);
end else
begin
B[s0+1] := A[q0+1];
Inc(q0);
end;
Inc(s0);
end;
t := r;
end;
k := k shl 1;
A := B;
end;
Сразу же бросается в глаза недостаток метода – он требует дополнительную память размером порядка N (для хранения вспомогательного массива). Но как и для древесной сортировки, его временная сложность всегда пропорциональна N*log(N) (так как преобразование k-упорядоченного массива в 2k-упорядоченный требует порядка N действий и внешний цикл по k совершает порядка log(N) итераций).