
- •Сортировки
- •Введение
- •Формулировка задачи сортировки
- •Простейшие методы сортировки
- •Алгоритм линейной сортировки (метод прямого выбора)
- •1 Способ 2 способ
- •Алгоритм сортировки обменом (метод "Пузырька")
- •Усовершенствованная "пузырьковая" сортировка
- •"Шейкер" - сортировка
- •Сортировка подсчетом
- •Алгоритм сортировки вставками (метод прямого включения)
- •Размещение путем сравнения и обмена (просеивание)
- •Размещение путем поиска места и вставки
- •Более сложные и более эффективные методы сортировки
- •Алгоритм сортировки Шелла (метод h-сортировки)
- •Обменная сортировка с разделением (сортировка Хоара)
- •Сортировка методом слияний
- •Простое слияние
- •Естественное двухпутевое слияние
- •Рекурсивный алгоритм слияния
- •Слияние списков
- •Алгоритм сортировки бинарными вставками
- •Сортировка с помощью двоичного включения
- •Лексикографическая сортировка
- •Топологическая сортировка
- •Поразрядная сортировка
- •Пирамидальная сортировка
- •Рекурсивная сортировка
- •Сравнительная характеристика методов сортировки
- •Классификация задач с применением сортировок
- •1. Задачи заполнения
- •2. Задачи анализа
- •3. Задачи поиска
- •4. Задачи перестановки
- •Литература
Более сложные и более эффективные методы сортировки
При решении более сложных задач приходится обрабатывать большие наборы данных. Применение простых для понимания, но медленно работающих методов сортировки, изложенных выше, становится нецелесообразно. Рассмотрим более эффективные методы сортировки.
Алгоритм сортировки Шелла (метод h-сортировки)
Некоторое усовершенствование сортировки простыми вставками предложено Д.Шеллом (Donald Lewis Shеll) в 1959 г.
Основная идея алгоритма заключается в сортировке элементов массива, отстоящих друг от друга на расстоянии h. Этот процесс называется h-сортировкой или сортировкой с уменьшающимися расстояниями.
Каждая h-сортировка программируется как сортировка простыми вставками. Затем h уменьшается и повторяется сортировка заново. Процесс заканчивается, когда h уменьшается до 1.
Рассмотрим последовательность 44, 55, 12, 42, 94, 18, 06, 67.
Сначала отдельно группируются и сортируются элементы, отстоящие друг от друга на расстоянии 4(четвертная сортировка):
44 55 12 42 94 18 06 67
Методом простой вставки сортируются массивы: 44-94, 55-18, 12-06, 42-67. После сортировки получаем массив:
44 18 06 42 94 55 12 67
2-сортировка дает следующие массивы для сортировки: 44-06-94-12, 18-42-55-67. После сортировки получаем массив:
06 18 12 42 44 55 94 67.
Уменьшаем h до 1 и сортируем весь массив, после чего получаем:
06 12 18 42 44 55 67 94.
Таким образом, программа разрабатывается как сортировка элементов массива для приращений h1, h2,…ht с условиями ht=1, hi+1<hi.
На первый взгляд можно сомневаться: если необходимо несколько проходов сортировки, причем в каждый включаются все элементы, то не добавят ли они больше работы, чем сэкономят?
Однако, на каждом таком проходе либо сортируется относительно мало элементов, либо элементы уже довольно хорошо упорядочены и требуется сравнительно немного перестановок.
Ясно, что такой метод дает упорядоченный массив, и каждый проход от предыдущих только выигрывает, так как каждая i-ая сортировка объединяет две группы уже отсортированные 2i-сортировкой (предыдущей).
Расстояния в группах можно уменьшать по-разному лишь бы последнее было единичным, ведь в самом плохом случае последний проход и сделает всю работу. Однако, совсем не очевидно, что прием "уменьшающихся расстояний" может дать лучшие результаты, если расстояния не будут степенями двойки.
При анализе алгоритма Шелла выяснилось, что неизвестно, какая последовательность приращений дает лучшие результаты.
Кнут рекомендовал последовательность 1, 4, 13, 40, 121,… (записанную в обратном порядке), где hk-1=3hk+1, ht=1, t=[log3 n]-1.
Он же рекомендовал последовательность 1, 3, 7, 15, 31,…, где hk-1=2hk+1, ht=1, t=[log2 n]-1.
Procedure Shellsort (var x: vector);
Var h, j, i, r: integer;
Begin
t:=round(ln(n)/ln(2))-1;
for m:=t downto 1 do
begin
h:=0;
For i:=1 to m do h:=2*h+1;
For i:=h+1 to N do
begin
r:=x[i]; j:=i-h;
while (j>=1) and (r<x[j]) do
begin
x[j+h]:=x[j];
dec(j,h);
end;
x[j+h]:=r
end;
end;
end (Shellsort);