Алгоритмы сортировки Прямого выбора Обменная (“пузырёк”) Сортировка вставками Постановка задачи Дан входной массив – неупорядоченный, длины N. На выходе необходимо получить массив, упорядоченный по возрастанию значений элементов, также длины N. Все значения из входного массива должны присутствовать в выходном массиве. Сортировка прямым выбором ( SelectionSort ) Идея алгоритма В выходном массиве: • на 1-м месте стоит наименьший элемент • на 2-м месте – наименьший среди «всех, кроме наименьшего элемента» • на 3-м – наименьший среди «всех, кроме двух наименьших элементов» • и т.д. Идея алгоритма Уже упорядоченная часть Ещё неупорядоченная часть 1) В неупорядоченной части находим минимальный элемент 2) Переставляем его на границу с упорядоченной частью 3) В результате: упорядоченная часть увеличивается на 1 элемент, а неупорядоченная - уменьшается на 1 элемент. Пример программы Var A: array[1..N] of string; k, m: integer; // здесь вставить // функцию FindMin // и процедуру Swap BEGIN // ввод данных // … for k:=1 to N-1 do begin m := FindMin(k, N); Swap(m, k); end; // … // вывод на печать END. Function FindMin(m, n: integer): integer; Var i: integer; Begin Result:=m; for i:=m+1 to n do begin if A[i] < A[Result] then Result:=i; End; Procedure Swap(i, j: integer); Var temp: string; Begin temp:=A[i]; A[i]:=A[j]; A[j]:=temp; End; Сложность алгоритма Для сортировки прямым выбором можно точно подсчитать количество действий сравнений и перестановок элементов: • Всего N-1 проход (поиск мин.элемента) • На K-м проходе выполняется N-K сравнений и ровно 1 перестановка . Всего сравнений: Lcmp = N*(N-1)/2 Всего перестановок: Lswap = N-1 Lcomp = O ( N2 ) Lswap = O ( N ) Обменная сортировка (в просторечии «пузырёк») ( BubbleSort ) Идея алгоритма ≤ ≤ ≤ ≤ ≤ ≥ ≤ ≥ ≤ ≤ В выходном массиве каждая пара соседних элементов упорядочена: Ai ≤ Ai+1 В исходном массиве пары соседних элементов могут быть неупорядоченными. Значит, надо упорядочивать пары элементов, пока не будут устранены все нарушения порядка. Идея алгоритма 1) Последовательно просматриваем массив. 2) Если находим неупорядоченную пару – переставляем элементы 3) Все элементы перемещаются в сторону своих «правильных» мест, но «большие» элементы перемещаются быстро, а «маленькие» – медленно, на 1 позицию за каждый проход. 4) По окончании 1-го прохода получится так, что самый большой элемент массива займёт своё «правильное» место. На следующем проходе можно уменьшить проверяемую часть массива. Движение элементов по массиву почему-то напомнило автору всплытие пузырьков в стакане газировки... романтичненько так... Пример программы А вот фигушки! Сложность алгоритма Для сортировки «пузырьком» количество действий можно подсчитать только приблизительно: • Всего N-1 проход (не более чем N-1) • На K-м проходе выполняется N-K сравнений и не более N-K перестановок. Всего сравнений: Lcmp = N*(N-1)/2 Всего перестановок: Lswap ≤ N*(N-1)/2 Lcomp = O ( N2 ) Lswap = O ( N2 ) Возможности улучшения Пузырявая сортировка допускает различные усповершенствования: 1. Если чередовать проходы «вверх» и «вниз», то большие и маленькие элементы будут быстрее перемещаться по массиву. 2. Если на каждом проходе подсчитывать количество нарушений порядка, то можно досрочно остановить алгоритм, (если массив уже стал упорядоченным). 3. Можно запоминать позиции 1-го и последнего нарушения; на следующем проходе просматривать только ту часть массива, где есть нарушения. Сортировка вставками (карточная) ( InsertionSort ) Идея алгоритма Пусть часть массива уже упорядочена. Тогда для очередного элемента из неупорядоченной части можно найти место в упорядоченной части (например, с помощью Binary Search), и вставить очередной элемент. Упорядоченная часть увеличится на 1 эл-т, неупорядоченная – сократится на 1 эл-т. Идея алгоритма 1)На 1-шаге упорядоченная часть содержит 1 элемент (1-й эл-т массива). 2)Берём 1-й элемент из неупорядоченной части, ищем его место в упорядоченной части. 3)Чтобы вставить элемент в середину массива, необходимо подвинуть все элементы, которые будут стоять после нового. Пример программы А вот фигушки! Сложность алгоритма Для сортировки вставками количество действий можно подсчитать только приблизительно: • Всего N-1 проход (не более чем N-1) • На K-м проходе выполняется log2(K) сравнений и не более K перестановок. Всего сравнений: Lcmp ≤ N*log2(N) Всего перестановок: Lswap ≤ N*(N-1)/2 Lcomp = O(N*log(N)) Lswap = O ( N2 )