Методи: включення | вибору | бульбашки
СОРТУВАННЯ МАСИВІВ
Будемо розглядати алгоритми сортування "на місці", тобто такі, які практично не потребують додаткової пам'яті, роблячи майже усі обміни всередині масиву.
При цьому усі методи сортування є сенс поділити на дві групи:
Вважатимемо надалі, що у програмі визначено масив
type Items = array [1..n] of Item;
...
var a : Items;
сортування відбувається за значеннями ключів a.key.
Вправи.
Контрольні питання.
На початок | Методи: включення | вибору | бульбашки
Прості методи сортування.
Метод прямого включення.
Один елемент завжди можна вважати відсортованим масивом довжини 1. Розглядаючи послідовно решту елементів масиву будемо включати їх у відсортовану частину масиву, ставлячи на потрібне місце, тобто не порушуючи відсортованості цієї частини. Повторивши операцію включення n-1 раз, одержимо відсортований масив.
Приклад. Візьмемо кілька випадкових чисел:
Остаточно програма має вигляд
procedure StraightInsertion (var a : Items);
var
i,j,k: integer;
x: Item;
begin
for i :=2 to n do begin
x := a[i]; j := 1;
while x.key > a[j].key do inc(j);
if j < i then
{є дірка!} begin
for k := i downto j+1 do
a[k] := a[k-1];
a[k-1] := x;
end;
end;
end
Аналіз. Кількість перевірок на i-му кроці дорівнює щонайбільше i-1, щонайменше 1, тому в середньому - i/2. Тому у середньому загальна кількість перевірок
Кількість обмінів не змінюється, тому модифікація є незначною: обмін займає звичайно більше часу, особливо, якщо частина a[i].rest є значною.
Вправи.
3. Модифікуйте обидві програми, щоб вони рахували і виводили загальну кількість порівнянь та обмінів, тобто C та M.
Контрольні питання.
На початок | Методи: включення | вибору | бульбашки
Сортування за допомогою простого вибору.
Основна ідея методу полягає в тому, що на кожному кроці шукається елемент, найменший з тих, що залишилися невпорядкованими, а після цього він додається до впорядкованої частини масиву останнім ( бо він там - найбільший).
Потім операція повторюється для підмасиву a[2..n]:
Програма може мати вигляд:
procedure StraightSelection;
var
i,j,k : Integer;
r : Item;
begin
for i := 1 to n-1 do
{номер мінімуму} begin
k := i; { шукати min серед a[i]..a[n] }
for j := i+1 to n do
if a[k] > a[j].key then begin
k := j;
end;
{Тут a[k] - найменше з a[i]..a[n]}
{Тепер обмін}
if k <> i then begin
r := a[k];
a[k] := a[i];
a[i] := r;
end;
end;
end;
Оцінимо якісні характеристики програми. На i-му кроці робиться (n-i) перевірок з елементами i+1, i+2, ..., n.
Тому
Принагідно зауважимо, що у [2,3], звідки взято ідею всіх методів, пропонується менш довершений варіант цього алгоритму з
На початок | Методи: включення | вибору | бульбашки
Сортування за допомогою простого обміну.
Це - найпростіший з методів сортування. Програма цього методу є найкоротшою з усіх можливих.
Ідея полягає у тому, щоб на кожному кроці, порівнюючи сусідні елементи між собою, міняти їх місцями, якщо вони стоять "не в тому порядку".
Таких проходів по масиву може знадобитися не менше, як (n-1), бо, якщо найменший елемент стоїть на останньому місці, то він досягне свого (першого) місця лише за n-1 крок сусідніх обмінів.
Procedure BubbleSort;
var
i,j : Integer;
x : Item;
begin
for i := 1 to n-1 do
for j := 2 to n do
if a[j-1].key > a[j].key then begin
{обмін}
x := a[j];
a[j] := a[j-1];
a[j-1] := x;
end;
end;
Програма називається "булькове сортування", а метод - методом "бульбашки", бо, якщо вважати кінець масива таким, що знаходиться угорі, то складається враження під час роботи програми, що елементи піднімаються по масиву, як бульбашки у воді до поверхні.
Ідея методу та його реалізація такі прості, що, скоріш за все, швидкісні характеристики його є найгіршими з усіх, що ми розглянули. Так воно і є.
Є багато способів поліпшити роботу алгоритму. Ми зробимо це, а потім проаналізуємо якість.
По-перше, після першого ж проходу ( при i = 1) найбільший елемент одразу підніметься на своє місце - останнє. Тому внутрішній цикл можна робити лише до (n - i + 1).
По-друге, якщо хоча б один елемент стоїть ще не на місці, то за черговий прохід буде зроблено принаймі один обмін. Тому, якщо за деякий прохід не зроблено жодного обміну, це означає, що масив уже відсортовано.
Тому слід перед кожним проходом встановлювати деяку логічну змінну y, рівну, скажімо, true, а в середині, якщо робиться обмін, то y := false. Після проходу її слід аналізувати.
Третю модіфікацію пов'язано з асиметриєю методу: якщо найбільший елемент потрапляє на місце лише за один прохід, то найменший - лише за n, якщо він стоїть на крайньому місці.
Тому пропонується проходи здійснювати по-черзі в двох напрямках. Такий спосіб називається шейкер-сортування (shaker (англ.)).
Кількість порівнянь для "булькового методу":
Для шейкер-методу аналіз зробити складно. Але цей метод має сильну перевагу якщо масив "майже відсортовано", тобто, коли кількість елементів m, що не стоять на місці, є незначною у порівнянні з n, n бб m. Тоді їх буде розставлено рівно за m проходів.
Вправи.
Контрольні питання.
На початок | Методи: включення | вибору | бульбашки