- •Лекция 8. Сортировка массива
- •1. Задача сортировки
- •Сортировка массивов
- •2. Простые алгоритмы сортировки
- •Сортировка обменами
- •Анализ алгоритма сортировки обменами
- •Завершаемость
- •Корректность
- •Эффективность по времени
- •Устойчивость
- •Улучшенный алгоритм сортировки обменами
- •3. Сортировка выбором
- •Анализ алгоритма сортировки выбором
- •4. Сортировка вставками
Анализ алгоритма сортировки обменами
Анализ алгоритма заключается в обосновании его свойств. Важнейшими свойствами алгоритма являются: корректность (правильность), оценка сложности по времени и памяти, а также и некоторые другие свойства.
Для обоснования алгоритма сортировки необходимо доказать, что алгоритм всегда (независимо от входа) завершает свою работу и его результат - упорядоченный по возрастанию массив. Оценка сложности (эффективности) алгоритма по времени заключается в нахождении C(n), M(n) в худшем случае, в среднем. Поскольку алгоритм сортирует массив “на месте”, его сложность по памяти - константа.
К другим свойствам алгоритма можно отнести свойство устойчивости. (Алгоритм сортировки называется устойчивым, если он не переставляет местами равные элементы.) Осуществим анализ алгоритма сортировки обменами.
Завершаемость
Алгоритм BublSort всегда завершает свою работу, поскольку он использует только циклы с параметром, и в теле циклов параметры принудительно не изменяются.
Корректность
Внутренний цикл алгоритма (с параметром j) осуществляет последовательный просмотр первых i элементов массива. На каждом шаге просмотра сравниваются и, если это необходимо, переставляются два соседних элемента. Таким образом, наибольший среди первых i +1 элементов “всплывает” на i +1-ое место. Поэтому после выполнения оператора If имеет место соотношение:
a[j+1] = Max(a[1], ..., a[i], a[j+1])
а после завершения цикла (i = j) имеет место соотношение
a[i+1] = Max(a[1], ..., a[i], a[i+1])
Внешний цикл (с параметром i) управляет длиной просматриваемой части массива: она уменьшается на 1. Поэтому после завершения внутреннего цикла имеет место соотношение: a[i+1] a[i+2] ... a[n] После завершения внешнего цикла получим: а[1] a[2], a[2] a[3] ... a[n] т.е. массив отсортирован.
Эффективность по времени
Внешний цикл выполнился n-1 раз. Внутренний цикл выполняется i раз (i = n-1, n-2, ..., 1). Каждое выполнение тела внутреннего цикла заключается в одном сравнении и, возможно, в одной перестановке.
Поэтому
C(n) = 1+2+ ... +n-1 = n*(n-1)/2, M(n)n*(n-1)/2
В худшем случае, когда элементы исходного массива расположены в порядке убывания
C(n) = n*(n-1)/2 = O(n2), M(n)=n*(n-1)/2= О(n2)
Устойчивость
Для доказательства устойчивости достаточно заметить, что переставляются только соседние неравные элементы.
Улучшенный алгоритм сортировки обменами
В программе BublSort цикл For используется в качестве внешнего. Это приводит к тому, что он выполняется ровно n - 1 раз, даже если массив уже упорядочен после нескольких первых проходов. От лишних проходов можно избавиться, применив цикл Repeat и проверяя во внутреннем цикле массив на упорядоченность:
Program BublSort1;
Const n = 100;
Var a : array[1..n] of Real;
i, j : Integer;
b : Real;Flag : Boolean;
Begin
{Блок ввода массива}
i := n - 1;
Repeat
Flag:= True; { признак упорядоченности }
For j := 1 to i do
If a[j] > a[j+1]
then
begin
b := a[j+1]; a[j+1] := a[j]; a[j] := b;
Flag:= False обнаружена “засортировка” (элементы стоят не на своем месте}
end;
i := Pred(i)
until Flag;
{Блок вывода массива}
End.
Этот алгоритм можно еще улучшить, если каждый следующий проход начинать не с начала (j = 1), а с того места, где на предыдущем проходе произошел первый обмен:
{Index : Integer;}
Repeat
Flag:= True; { признак упорядоченности }
Index := 1; { отрезок A[1..Index] упорядочен }
For j := LowIndex to i do
If a[j] > a[j+1]
then
begin
b := a[j+1]; a[j+1] := a[j]; a[j] := b;
If Flag then
begin Index := j; Flag:= False
end
end;
i := Pred(i)
until Flag;
Заметим однако, что наш алгоритм работает несимметрично: если наибольший элемент “всплывет” на свое место за один проход, то наименьший элемент “утонет” на 1-ое место, находясь изначально на n-том месте, за n-1 проход. При этом осуществится максимально возможное число сравнений. Устранить асимметрию можно, чередуя проходы вперед и назад.
Все улучшения рассматриваемого метода относятся к эффективности в среднем. Ни одно из них не уменьшает оценки сложности С(n) в худшем случае.
