Алгоритмы сортировки
Основная задача сортировки: Пусть имеется массив численных значений
A[n+1]. Необходимо упорядочить элементы массива в порядке
возрастания.
Все алгоритмы сортировки делятся на четыре группы:
- сортировка вставками — элементы просматриваются
по одному, и каждый новый элемент вставляется в подходящее место среди
ранее упорядоченных элементов;
- обменная сортировка — если два элемента расположены
не по порядку, то они меняются местами; процесс повторяется по полного
упорядочения;
- сортировка подсчетом — каждый элемент сравнивается
со всеми остальными и подсчитывается количество сравнений одного типа
(изменяется значение соответствующего ключа); окончательное положение
элемента определяется величиной соответствующего ключа;
- сортировка посредством выбора — выделяется
наименьший (или наибольший) элемент и отделяется от остальных,
затем выбирается наименьший (наибольший) из оставшихся и т.д.
Иногда один и тот же метод сортировки может быть отнесен
к разным группам, т.е. разделение на группы условно.
Ниже приводятся алгоритмы этих методов сортировки и результат их
исполнения. Тексты соответствующих программ приведены в приложении.
Алгоритм простых вставок
Идея метода: Пусть элементы A0 … Aj-1 уже отсортированы, т.е. A0 < A1 < … < Aj-1. Тогда сравниваем элемент Aj с элементами Aj-1, Aj-2, … до тех пор, пока не обнаружим, что Aj надо вставить между Ai и Ai+1. Тогда элементы Ai+1, …, Aj-1 сдвигаются вправо на 1 и новый элемент вставляется на место Ai+1.
Алгоритм:
- 1. Организуется цикл по j = 1, 2, …, n, в котором выполняются
пункты 2-5.
- 2. Присвоить i = j - 1, B = Aj.
- 3. Пока B ≤ Ai или i ≥ 0 выполнять пункт 4, иначе перейти к пункту 5.
- 4. Присвоить A_{i + 1} = Ai, i = i - 1.
- 5. A_{i + 1} = B.
Среднее время работы алгоритма t = n2.
Метод Шелла (сортировка с убывающим шагом)
Идея метода. Сократить длину перемещения элементов при сортировке. В методе простых вставок средняя длина пути элемента равна N / 3 позиций. В методе Шелла процесс сортировки управляется вспомогательной последовательностью шагов hm, hm-1, …, h1, h0 = 1. Соответственно, массив A[n+1] последовательно делится на hm групп, затем на hm-1 групп и т.д. с шахматным чередованием элементов. В пределах каждой группы на каждом шаге выполняется сортировка простыми вставками. На последнем этапе сортируется весь массив, но длина пути перемещения элементов в среднем будет значительно меньше, чем в методе простых вставок.
Алгоритм:
- 1. Присваиваем g = 2m+1 и организуем цикл по k = (m, 0) для пунктов 2-6.
- 2. g = g / 2. Цикл по j = (g, n) для пунктов 3-6.
- 3. Присвоить B = Aj, i = j - g.
- 4. Пока B ≤ Ai и i ≥ 0 выполнять пункт 5.
- 5. Присвоить Ai+g = Ai, i = i - g.
- 6. Присвоить Ai+g = B.
Оптимальная последовательность шагов hj+1 = 3 hj + 1, j = 0, 1, …, m. Число m выбирается из условия hm+1 ≥ n.
Среднее время работы t = n1.25.
Обменная сортировка: метод пузырька
Идея метода: Сравнить A0 и A1 и поменять их местами, если A0 ≥ A1. Затем проделать то же самое с парами A1 и A2 и т.д. В результате этой процедуры элементы с наибольшими значениями сдвигаются вправо (всплывают как пузырек).
Простейший алгоритм:
- Цикл по i = (0, n-1).
- Цикл по j = (0, n-1).
- Сравнить Aj и Aj+1. Если Aj > Aj+1, то меняем элементы местами B = Aj, Aj = Aj+1, Aj+1 = B.
Оптимизированный алгоритм:
- 1. Присвоить k = n (k — индекс самого верхнего элемента, о
котором еще не известно, занял ли он свое место).
- 2. Присвоить i = -1.
- 3. Цикл по j = (0, k-1).
- 4. Если Aj > Aj+1, то B = Aj, Aj = Aj+1, Aj+1 = B, i = j.
- Если i = -1, то завершить работу цикла. Иначе присвоить k = i и вернуться к пункту 2.
Среднее время работы t ∼ n2.
Обменная сортировка: быстрая сортировка
Идея метода: Пусть имеются два указателя i и j, причем вначале i = 0 и j = n, т.е. i и j вначале указывают на граничные элементы массива A. Сравним Ai и Aj. Если обмен не требуется, то уменьшим j на 1 и повторим процесс. После нового обмена увеличим i на 1 и продолжим увеличение i до следующего обмена. Тогда снова будем уменьшать j. Когда i = j, исходный элемент A1 займет свою окончательную позицию. В результате массив окажется разделенным на два подмассива, причем в левом все элементы будут меньше A1, а в правом - больше. К каждому из этих подмассивов применяется тот же метод, пока размеры подмассивов не станут достаточно малыми (меньше некоторого значения M), после чего к ним можно применить метод простых вставок.
- 1. Присвоить l = 0, r = n (границы).
- 2. Если r - l < M, то перейти к пункту 8. Иначе присвоить i = l, j = r, B = A_l.
- 3. Если B < Aj, то j = j - 1 и повторить этот шаг.
- 4. Если j ≤ i, то Ai = B и перейти к пункту 7. В противном случае Ai = Aj и i = i + 1.
- 5. Если Ai < B, то i = i + 1 и повторить этот шаг.
- 6. Если j ≤ i, то Aj = B и i = j. В противном случае Aj = Ai, j = j - 1 и перейти пункту 3.
- 7. Если r - i ≥ i - l, то запомнить пару чисел (i + 1, r) и установить r = i - 1. В противном случае запомнить (l,i - 1) и установить l = i + 1. Вернуться к пункту 2.
- 8. Сортировка простыми вставками подмассива от l + 1 до r.
- 9. Взять последнюю запомненную пару (l′,r′), присвоить l = l′, r = r′ и вернуться к шагу 2. Если больше пар не осталось, то сортировка завершена.
Сортировка посредством выбора: метод простого выбора
Идея метода: выбирается наибольший элемент и перемещается на последнюю позицию и т.д.
Алгоритм:
- Цикл по j = (n,1).
- Найти наибольший из элементов Aj, Aj-1, …, A0. Пусть это элемент Ai.
- Поменять местами Ai и Aj: B = Ai, Ai = Aj, Aj = B.
Среднее время t ∼ n2.
Сортировка подсчетом
Идея метода: сравнить попарно элементы и в случае когда 1-й больше 2-го увеличить значение счетчика (ключа) у первого на n-1. Окончательно размещение осуществляется по значению ключей.
Алгоритм:
- Занулить массив ключей ki = 0, i = (0, n).
- Цикл по i = (n, 1).
- Цикл по j = (i-1, 0).
- Если Ai < Aj, то kj = kj + 1 иначе ki = ki + 1.
- Завершить циклы i и j.
- Переместить элемент Aj на позицию kj. Для этого лучше использовать новый массив: B[kj] = A[j].