
- •Лекция 8. Сортировка массива
- •1. Задача сортировки
- •Сортировка массивов
- •2. Простые алгоритмы сортировки
- •Сортировка обменами
- •Анализ алгоритма сортировки обменами
- •Завершаемость
- •Корректность
- •Эффективность по времени
- •Устойчивость
- •Улучшенный алгоритм сортировки обменами
- •3. Сортировка выбором
- •Анализ алгоритма сортировки выбором
- •4. Сортировка вставками
3. Сортировка выбором
Основное действие сортировки выбором - поиск наименьшего элемента в просматриваемой части массива и перестановка с первым элементом этой части:
For i := 1 to n - 1 do begin
k := Индекс( Min(a[i], ..., a[n]));
Переставить a[i], a[k]
end;
Program SelectSort;
Const n = 10;
Var a : array[1..n] of Real;
i, j, MinInd : Integer; b : Real;
Begin
{Блок ввода массива}
For i := 1 to n - 1 do begin
MinInd := i;
for j := i + 1 to n do
If a[j] < a[MinInd] then
Begin
MinInd := j;
b := a[MinInd]; a[MinInd] := a[i]; a[i] := b
end
end;
{Блок вывода массива}
End.
Рис 2. Алгоритм сортировки обменами
Алгоритм SelectSort осуществляет n-1 линейный просмотр массива а. В результате каждого просмотра наименьший элемент просмотренной части массива меняется местами с первым элементом этой части. Первый просмотр осуществляется во всем массиве, а каждый следующий – в диапазоне, на единицу меньшем. Таким образом, левая часть массива становится упорядоченной. На рисунке эти элементы – от a[1] до a[i] - заштрихованы серым. На рисунке выделены переставляемые элементы a[i+1] и a[MinInd].
Анализ алгоритма сортировки выбором
Внутренний цикл осуществляет поиск минимального элемента. После выполнения оператора If имеет место соотношение Min = Min(a[i], a[i+1], ... , a[j]), а после завершения цикла Min = Min(a[i], a[i+1], ... , a[n]). После перестановки имеем: a[i] = Min(a[i], a[i+1], ... , a[n]). Внешний цикл управляет длиной просматриваемой части массива. После выполнения тела внешнего цикла начало массива отсортировано: a[1] a[2] .. a[i]
После завершения внешнего цикла получим:
a[1] a[2] ... a[n-1], a[n-1] = Min(a[n-1], a[n]), т.е массив отсортирован.
Внешний цикл выполнился n-1 раз. Внутренний цикл выполняется i-1 раз (i = n-1, n-2, ...,1). Каждое выполнение тела внутреннего цикла заключается в одном сравнении.
Поэтому C(n) = 1 + 2 + ... + n - 1 = n(n - 1)/2,
Перестановка элементов осуществляется во внешнем цикле. Поэтому M(n) = 3(n - 1)
Также, как и алгоритм сортировки обменами, анализируемый алгоритм устойчив. Можно сделать вывод, что простая сортировка выбором эффективней сортировки простыми обменами по критерию M(n). Если сортируемая последовательность состоит из данных большого размера, этот критерий может иметь решающее значение.
4. Сортировка вставками
Еще один простой алгоритм сортировки - сортировка вставками основан на следующей идее: предположим, что первые k элементов массива A[1..n] уже упорядочены: A[1] A[2] ... A[k], A[k+1], ..., A[n]. Найдем место элемента A[k+1] в начальном отрезке A[1],...,A[k] и вставим этот элемент на свое место, получив упорядоченную последовательность длины k+1. Поскольку начальный отрезок массива упорядочен, поиск нужно реализовать как бинарный. Вставке элемента на свое место должна предшествовать процедура сдвига “хвоста” начального отрезка для освобождения места.
Program InsSort;
Const n = 100;
Var A : array[1..n] of Integer;
k : Integer; l, r, i, j : Integer; b : Integer;
Begin
{Блок чтения массива A}
For k := 1 to n-1 do begin
b := A[k+1];
If b < A[k]
then begin
l := 1; r := k; {Бинарный поиск}
Repeat
j := (l + r) div 2;
If b < A[j] then r := j else l := j + 1;
until (l = j); { Сдвиг “хвоста” массива на 1 позицию вправо}
For i := k downto j do A[i+1] := A[i];
A[j] := b ; { Пересылка элемента на свое место}
end
end;
{Блок вывода массива A}
End.
Рис 3. Алгоритм сортировки вставками
Алгоритм InsSort осуществляет n-1 линейный просмотр массива а. В каждом просмотре ищется место элемента a[]k+1], следующего непосредственно за уже упорядоченным диапазоном массива 1..k. На рисунке этот диапазон – от a[1] до a[k] – заштрихован серым Затем элемент a[]k+1] вставляется на свое место. Вставке элемента предшествует сдвиг диапазона j..k вправо на одну позицию. Таким образом, левая, уже упорядоченная часть массива становится большей на 1 элемент. На рисунке выделены обрабатываемый элемент a[k+1] и элементы, между которыми он вставляется.
Оценим эффективность алгоритма. Поиск места элемента A[k+1] требует, как показано выше, O(log2 k ) сравнений. Поэтому в худшем случае количество сравнений С(n) есть C(n) = O(log2 2 ) + ... + O(log2(n-1)) + O(log2 n) = O(n log2 n)
Сдвиг хвоста на каждом шаге внешнего цикла в худшем случае требует k перестановок. Поэтому в худшем случае M(n) = 1+..+ (n-2) + (n-1) = n*(n-1)/2 = O(n2).
Таким образом, алгоритм сортировки вставками существенно эффективнее, чем все рассмотренные ранее алгоритмы по числу сравнений. Однако число перестановок в худшем случае так же велико, как и в самом неэффективном алгоритме - сортировке простыми обменами.