Метод_материалы / Учебники / Программирование_С
.pdfi_father = left; i_son = 2 * i_father; buf = a[i_father];
while ((i_son <= right) and flg)
{
if (i_son < right)
if (a[i_son] > a[i_son + 1]) i_son = i_son + 1;
if (buf <= a[i_son]) flg = FALSE;
else
{
a[i_father] = a[i_son]; i_father = i_son; i_son = 2 * i_father;
};
};
a[i_father] = buf;
};
II. Сортировка на построенной пирамиде:
Описание алгоритма:
1)берем последний элемент массива в качестве текущего;
2)меняем первый элемент массива (верхний — пирамиды, он наименьший) и текущий местами;
3)текущий (он теперь первый) просеиваем сквозь n – 1 элементную пирамиду;
4)берем предпоследний элемент и так далее.
Пример (символом * обозначен просеиваемый элемент, символом # — занявший окончательное место):
1) |
a) |
24* |
|
b) |
15 |
|
|
20 |
15 |
20 |
|
24 |
|
|
31 |
52 |
6# |
31 |
52 |
6# |
2) |
a) |
52* |
|
b) |
20 |
|
191
20 |
24 |
|
31 |
24 |
|
31 |
15# |
6# |
52 |
15# |
6# |
3) a) |
52* |
|
b) |
24 |
|
31 |
24 |
|
31 |
52 |
|
20# |
15# |
6# |
20# |
15# |
6# |
и так далее.
В итоге массив будет отсортирован — для этого алгоритма, по убыванию. Псевдокод для полного алгоритма пирамидальной сортировки выглядит так:
{
left = (n / 2) + 1;
//просеять_все_элементы_левее_left;
//выполнить_сортировку_на_построенной_пирамиде;
};
Более детально,
{
left = (n / 2) + 1; while (left > 1 )
{
left = left–1; Sift(left, n, a);
};
right = n;
while (right > 1)
{
buf = a[1]; a[1] = a[right]; a[right] = buf; right = right–1; Sift(1, right, a);
};
};
192
3.1.2.2.3. Задачи на сортировки выбором.
3.1.2.2.3.1. Простой выбор
Напишите программу, реализующую метод простого выбора.
3.1.2.2.3.2. Пирамидальная сортировка
Напишите программу, реализующую пирамидальную сортировку.
3.1.2.2.3.3. Сортировка методом квадратичного выбора.
Разделим n элементов в файле на
n групп по
n элементов в каждой группе. Найдем наибольший элемент в каждой группе и поместим его в некоторый вспомогательный массив. Найдем наибольший элемент в этом вспомогательном массиве. Этот элемент является наибольшим элементом в данном файле. Затем заменим этот элемент в массиве на следующий по величине элемент в той группе, из которой он поступил. Снова найдем наибольший элемент во вспомогательном массиве. Этот элемент — второй по величине в данном файле. Повторим этот процесс до тех пор, пока файл не будет отсортирован. Напишите программу, которая реализует сортировку методом квадратичного выбора.
3.1.2.3. Обменные сортировки
Если два элемента расположены не по порядку, они меняются местами; процесс повторяется до упорядочения всех элементов
3.1.2.3.1. Простой обмен (пузырьковая сортировка)
Попарно сравниваются (и при необходимости меняются местами) соседние элементы;
процесс повторяется для оставшихся n – 1 элемента с конца массива; каждый раз наименьший элемент оставшейся части "прогоняется" через эту часть.
Пример (символом # обозначен элемент, занявший окончательное место). Исходный массив: 24 31 15 20 52 6
исх. |
24 31 15 20 52 6 |
i = 1 |
┌───────────┘ |
i = 2 |
6# 24 31 15 20 52 |
|
┌────┘ |
i = 3 |
6# 15# 24 31 20 52 |
|
┌────┘ |
i = 4 |
6# 15# 20# 24 31 52 |
i = 5 |
6# 15# 20# 24# 31 52 |
i = 6 6# 15# 20# 24# 31# 52
Заметим, что на последних двух итерациях перемещений элементов не было. Псевдокод для алгоритма пузырьковой сортировки:
{
for (i = 2 to n)
{
193
//сравнить и, если нужно, поменять местами
//текущий и предыдущий элементы, начиная с
//a[n] и до a[i]
};
};
Более детально:
{
for (i = 2 to n)
{
for (j = n to I)
if (a[j – 1] > a[j])
{
buf = a[j – 1]; a[j – 1] = a[j]; a[j] = buf;
};
};
};
Количество сравнений: n*(n–1)/2 (всегда одинаково).
Пересылок: от 0, когда массив уже отсортирован, до 3*n*(n–1)/2, когда каждый шаг — с пересылкой.
Возможные улучшения этого алгоритма. I. Не делать лишнего:
1)закончить сортировку, если при последнем проходе не было ни одного обмена;
2)заканчивать очередной проход не на индексе i, а на индексе последнего обмена (так как все более близкие к началу элементы уже отсортированы).
II. Менять направление проходов:
10 25 30 48 5 — отсортируется за 1 проход, 48 5 10 25 30 — отсортируется за 4 прохода,
хотя и в том и в другом случае не на месте только один элемент. Поэтому лучше чередовать проходы слева — направо и справа — налево, меня знаки неравенств
валгоритме (шейкер — сортировка).
3.1.2.3.2. Быстрая сортировка Обмениваются элементы не соседние, а более удаленные друг от друга. I. Разделение массива
Процесс разделения массива: некоторый элемент выбирается граничным (по положению) и массив просматривается в обе стороны. Первый элемент слева больший граничного и первый элемент справа меньший граничного меняются местами.
В примере граничным выбран средний по положению элемент массива (индекс вычислен по формуле (n + 1) / 2), что дает 3. Просмотр массива происходит одновременно с самого левого элемента направо и с самого правого элемента налево.
194
Пример: исходный массив: 24 31 15 20 52 6 Первыми для обмена выбраны элементы 24 слева и 6 справа, вторыми — 31
слева и 15 справа: |
|
||
i_low = 1 |
i_high = 6 |
|
|
|
│ |
│ |
|
исх. |
24 31 15 20 52 6 |
|
|
|
|
── bord |
|
i_low = 2 i_high = 3 |
|
||
|
│ |
│ |
|
i = 2 |
6 31 15 20 52 24 |
|
|
|
|
── bord |
|
i_high = 2 i_low = 3 |
|
||
|
│ |
│ |
|
i = 3 |
6 15 31 20 52 24 |
i_high < i_low |
|
|
── bord |
|
|
Процесс прекращается, когда индексы текущих верхнего и нижнего элементов «встречаются» где-то около граничного элемента (в нашем примере это i_high = 2, i_low = 3, то есть i_high < i_low). В итоге массив принимает показанный выше вид. Подчеркнем, что это еще не отсортированный массив, проведено лишь разделение его на два подмассива, в одном из которых собраны все меньшие, а в другом — все большие граничного элементы.
Псевдокод для алгоритма разделения массива:
{
// выбрать bord i_low = 1; i_high = n;
do
// искать обмен и обменивать элементы i_low = i_low + 1;
i_high = i_high–1; while (i_low <= i_high);
};
или более детально
{
// выбрать bord; i_low = 1; i_high = n;
do
{
while (a[i_low] < bord)
195
i_low = i_low + 1;
while (bord < a[i_high]) i_high = i_high – 1;
if (i_low <= i_high)
{
buf = a[i_low]; a[i_low] = a[i_high]; a[i_high] = buf; i_low = i_low + 1; i_high = i_high – 1;
}
}
while (i_low <= i_high);
};
Оба цикла while выполняют поиск очередных элементов для обмена; условие if отсекает возможность лишнего обмена, когда индексы уже «перекрещены».
II. Собственно сортировка
Ранее была выполнена функция Sort(1,n), левый и правый индексы: left = 1, right = n.
Процесс закончился при i_high = 2, i_low = 3. Теперь применим алгоритм рекурсивно. Наш массив
6 15 31 20 52 24
Sort(1,2) |
Sort(3,n) |
left = 3, right = n |
615 31 20 52 24
── ──
при |
|
|
закончится |
|
|
|
|
|
|
|
|
i_high |
= |
0, |
20 │ 31 52 |
24 |
|
i_low |
= |
2 |
|
|
|
|
|
закончится при |
|
||
конец |
|
i_high = 3, |
|
|
|
|
|
|
рекурсии |
i_low = 4 |
|
|
|
|
Sort(4,n) |
left = |
4, right = n |
196
31 52 24
──
…
и так далее (вертикальная черта разделяет рекурсивно образованные подмассивы).
Остается написать псевдокод для функции Sort, которая в силу описания алгоритма должна быть рекурсивной.
void Sort(int left,right )
{
i_low = left; i_high = right;
bord = a[(left + right) / 2];
do
{
while (a[i_low] < bord ) i_low = i_low + 1;
while (bord < a[i_high]) i_high = i_high – 1;
if (i_low <= i_high)
{
buf = a[i_low]; a[i_low] = a[i_high]; a[i_high] = buf; i_low = i_low + 1; i_high = i_high – 1;
};
}
while (i_low <= i_high);
if (left < i_high) Sort(left,i_high);
if (i_low < right) Sort(i_low,right);
};
Вызов функции из главной функции программы должен выглядеть так: Sort(1,n).
197
3.1.2.3.3. Задачи на обменные сортировки.
3.1.2.3.3.1. Пузырьковая сортировка
Напишите программу, реализующую пузырьковую сортировку.
3.1.2.3.3.2. Улучшенная пузырьковая сортировка
Напишите программу, реализующую улучшенную пузырьковую сортировку
(см. примечание к п. 3.1.2.3.1-1).
3.1.2.3.3.3. Шейкер — сортировка
Напишите программу, реализующую шейкер — сортировку.
3.1.2.3.3.4. Быстрая сортировка
Напишите программу, реализующую быструю сортировку.
3.1.2.3.3.5. Сортировка методом подсчета
Эта сортировка выполняется следующим образом. Заводится некоторый массив count и элементу count[i] присваивается значение числа элементов, которые меньше или равны a[i]. Затем элемент a[i] помещается в позицию count[i] в выходном массиве. Напишите программу для сортировки массива a размером n, используя этот метод.
3.1.2.3.3.6. Сортировка методом распределяющего подсчета
Предположим, что некоторый массив mas содержит целые числа в диапазоне от а до b, причем многие числа повторяются несколько раз. Сортировка методом распределяющего подсчета выполняется следующим образом. Заводится вспомогательный массив number размером b–а + 1 и элементу number[i – a + 1] присваивается значение, равное тому, сколько раз число i появляется в исходном массиве. Затем значения в массиве соответственно переустанавливаются. Напишите программу для сортировки некоторого массива mas размером n, содержащего целые числа в диапазоне от а до b, используя этот метод.
3.1.2.3.3.7. Сортировка методом четных и нечетных транспозиций
Выполняются несколько раз просмотры исходного массива mas. На первом просмотре сравнивайте mas[i] с mas [i + 1] для всех нечетных i. На втором просмотре сравнивайте mas[i] с mas[i + 1] для всех четных i. Каждый раз, когда mas[i] > mas [i + 1] выполняйте транспозицию этих двух элементов. Продолжайте эти просмотры до тех пор, пока массив не будет отсортирован.
Что является условием окончания этой сортировки? Напишите программу, реализующую эту сортировку.
3.1.2.4. Другие сортировки.
3.1.2.4.1. Сортировка слиянием Слияние является процессом объединения двух или более отсортированных
массивов в некоторый третий отсортированный массив.
Мы можем использовать этот метод для сортировки массива следующим образом.
Разделим массив на n подмассивов размером 1 и будем объединять соседние (необъединенные) пары массивов. Мы тогда будем иметь примерно n/2 массивов размером 2. Будем повторять этот процесс до тех пор, пока не останется только
198
один массив размером n. Ниже показано, как выполняется этот процесс. Каждый отдельный массив на рисунке заключен в скобки.
Пример:
Исходный массив: [25] [57] [48] [37] [12] [92] [86] [33]
Шаг 1: |
[25 |
57] |
[37 |
48] |
[12 |
92] |
[33 |
87] |
Шаг 2: |
[25 |
37 |
48 |
57] |
[12 |
33 |
86 |
92] |
Шаг 3: |
[12 |
25 |
33 |
37 |
48 |
57 |
86 |
92] |
Для реализации этой процедуры на самом деле достаточно иметь только два массива, которые будут поочередно использоваться для результатов текущего шага.
Напишите программу, реализующую этот метод. 3.1.2.4.2. Поразрядная сортировка
Этот метод основан на свойстве значений целых чисел в обычном позиционном представлении. Например, число 235 в десятичной системе записывается так, что имеет 2 в позиции сотен, 3 в позиции десятков и 5 в позиции единиц. Большее из двух таких чисел, имеющих одинаковую длину, может быть определено следующим образом. Надо начать со старшей цифры и продвигаться к младшим цифрам, пока соответствующие цифры двух чисел совпадают. Как только достигнута ситуация несовпадения, то число с большей цифрой в текущей позиции является большим из этих двух чисел. Если все цифры обоих чисел совпадают, то эти числа равны.
При использовании десятичного основания числа могут быть отсортированы на 10 групп по их самой старшей цифре. Если числа имеют неодинаковое количество цифр, это можно обойти добавлением незначащих лидирующих нулей. Далее выполняется сортировка внутри отдельных групп по следующей значащей цифре. Этот процесс повторяется до тех пор, пока каждая подгруппа не будет разделена по самой младшей значащей цифре. В этот момент первоначальный массив будет отсортирован, и достаточно просмотреть все очереди по порядку, сливая данные в один массив.
Ясно, что этот метод требует создания значительного количества подмассивов
(очередей). |
|
|
|
|
|
|
|
Пример. |
|
|
|
|
|
|
|
Исходный массив |
|
|
|
|
|||
25 |
57 |
48 |
37 |
12 |
92 |
86 |
33 |
Очереди, организованные по СЗЦ |
|||||||
|
Начало |
|
Конец |
|
|
||
queue (0) |
|
|
|
|
|
|
|
queue (1) |
|
12 |
|
|
|
|
|
queue (2) |
|
25 |
|
|
|
|
|
queue (3) |
|
33 |
|
|
|
37 |
|
queue (4) |
|
48 |
|
|
|
|
|
199
queue (5) |
57 |
|
|
|
|
|
|
queue (6) |
|
|
|
|
|
|
|
queue (7) |
|
|
|
|
|
|
|
queue (8) |
86 |
|
|
|
|
|
|
queue (9) |
92 |
|
|
|
|
|
|
Omcоpmupoванный файл |
|
|
|
|
|||
12 |
25 |
33 |
37 |
48 |
57 |
86 |
92 |
Напишите программу, реализующую этот метод.
3.1.2.4.3. Сортировка методом турнира с выбыванием (выбором из дерева)
Рис. 3.5. Сортировка методом турнира с выбыванием
200
