Uploaded by valet04

Lection 11 сортування

advertisement
Методи сортування
Лекция № 12
Алгоритм сортування
• Сортування - це процес упорядкування деякої
множини елементів, на якому визначені відносини
порядку >, <, ,  .
• Завданням сортування є перетворення вихідної
послідовності в послідовність, що містить ті ж
елементи, але в порядку зростання (або зменшення)
значень.
Цілочисельний масив (список, файл) з розташованими за
неспаданням або за незростанням значеннями елементів
називається впорядкованим.
Алгоритми сортування використовують там, де мова йде про обробку
та зберігання великих обсягів інформації.
Деякі завдання обробки даних вирішуються простіше, якщо дані
заздалегідь упорядкувати.
Якщо елемент списку має кілька полів, поле, що служить
критерієм порядку, називається ключем сортування.
На практиці в якості ключа часто виступає число, а в
інших полях зберігаються будь-які дані, які не впливають
на роботу алгоритму.
3
Формулювання задачі сортування
Заданий масив A з n елементів:
a1 , a2 , … , an ,
Будемо вважати, що з кожним елементом ai (крім іншої інформації, що
не впливає на сортування) пов’язаний ключ ki є K. На множині ключів K
задане відошення порядку - лінійного (або іншог) впорядкування, для
якого були би виконані такі умови:
закон трихотомії: для будь-яких x,y є K або x<y, або x>y, або x=y;
транзитивність: для будь-яких x,y,z є K якщо x<y і y<z, то x<z.
Завданням сортування за неспаданням є знаходження
перестановки елементів p (1), p (2), ..., p (n) з індексами 1,2, ..., n, при
якій ключі розташовуються в порядку неспадання:
kp(1)≤ kp(2) ≤ … ≤ kp(n) .
В результаті роботи алгоритма і застосування перестановки
отримаємо відсортований масив ap(1), ap(2), … ap(n) .
Аналогічно можна визначити сортвання за незрастанням.
4
1 Оцінка алгоритмів сортування
Алгоритми сортування оцінюються за швидкістю
виконання та ефективністю використання
пам’ятs.
Часова оцінка характеризує швидкодію алгоритму.
Важливі найгірша, середня і найкраща оцінка алгоритму в термінах
потужності вхідної множини A:
множина A поступає на вхід алгоритму ;
n = |A| - потужність множини (кількість елементів масиву ).
Хороша оцінка O(n log n), погана оцінка O(n2), ідеальна оцінка O(n).
Алгоритми сортування, що використовують тільки абстрактну операцію
порівняння ключів, завжди потребують щонайменше Ω(n log(n)) порівнянь.
Існує поняття сортуючих мереж. Вважаючи, що можна одночасно (наприклад,
при паралельних обчисленнях) проводити декілька порівнянь, можна
відсортувати n чисел за O(log2(n)) операцій. При цьому число n повинно бути
відомим.
5
Оцінка ефективності використання пам'яті
Ряд алгоритмів вимагає виділення додаткової пам'яті під
тимчасове зберігання даних.
Як правило, ці алгоритми вимагають O (log (n)) пам'яті.
При оцінці не враховується місце, яке займає вихідний
масив і незалежні від вхідної послідовності витрати,
наприклад, на зберігання коду програми (так як все це
споживає O (1)).
Алгоритми сортування, що не споживають додаткової
пам'яті, відносять до сортувань на місці.
6
Оптимальність алгоритму сортування O(n log(n))
Завдання сортування в загальному випадку передбачає,
що єдиною обов'язково існуючою операцією для
елементів є порівняння.
Нехай по ходу роботи алгоритмом проводиться k
порівнянь.
Відповіддю на порівняння двох елементів a і b може
бути один з двох варіантів
(a <b або a> b).
Значить, все можливо 2k варіантів комбінацій відповідей
на k питань.
Кількість перестановок з n елементів дорівнює n !.
7
2 Властивості і характеристики алгоритмів
сортування
Властивість сортування - Стійкість (stability)
Стійка сортування не змінює взаємного розташування
елементів з однаковими ключами.
Практично завжди стійкість може бути досягнута шляхом
подовження вихідних ключів за рахунок додаткової
інформації про їх первісний порядок.
Стійкість не обов'язкова для правильності сортування і
найчастіше не дотримується, оскільки для її забезпечення
практично завжди необхідні додаткова пам'ять і час.
8
2 Властивості і характеристики алгоритмів
сортування
Властивість сортування - Природність поведінки
Природність поведінки - ефективність методу при обробці вже
упорядкованих або частково впорядкованих даних.
Алгоритм поводиться природно, якщо враховує впорядкованість
або часткову упорядкованість даних вхідної послідовності і
працює краще.
Властивість сортування – Використання операції
порівняння
Алгоритми, що використовують для сортування порівняння елементів
між собою, називаються заснованими на порівняннях.
Мінімальна трудомісткість гіршого випадку для цих алгоритмів
становить O (n log (n)), але вони відрізняються гнучкістю застосування.
9
Класифікація за типом пам’яті, що
використовується
• Внутрішнє сортування оперує з масивами, що цілком
поміщаються в оперативній пам'яті з довільним доступом
до будь-якої комірки. Дані зазвичай упорядковуються на
тому ж місці, без додаткових витрат.
• Зовнішнє сортування оперує з запам’ятовуючими
пристроями великого обсягу, але з доступом не довільним,
а послідовним (впорядкування файлів). Це накладає деякі
додаткові обмеження на алгоритм і призводить до
спеціальних методів впорядкування, що, зазвичай,
використовують додатковий дисковий простір. Крім того,
доступ до даних на носії здійснюється набагато
повільніше, ніж операції з оперативною пам'яттю.
Класифікація алгоритмів сортування
Алгоритми сортування можна класифікувати за різними
ознаками:
- стійкість;
- поведінка;
- використання операцій порівняння;
- потреба в додатковій пам'яті;
- потреба в знаннях про структуру даних, що
виходять за рамки операції порівняння, та інші.
n – кількість записів, які потрібно впорядкувати;
k - кількість унікальних ключів.
11
Алгоритми стійкого сортування
• Сортування обміном (бульбашкою) (англ. Bubble sort) - складність
алгоритму: O (n2); для кожної пари індексів проводиться обмін, якщо
елементи розташовані не по порядку.
• Сортування перемішуванням (шейкерна, Cocktail sort, bidirectional
bubble sort) – масив переглядається почергово справа наліво та
зліва направо. Складність алгоритму: O (n2)
• Гномове сортування - має спільне з сортуванням бульбашкою і
сортуванням вставками. Перед вставкою на потрібне місце
виконується серія обмінів. Складність алгоритму - O (n2).
• Сортування вставками (Insertion sort) - Складність алгоритму: O
(n2); визначаємо, де поточний елемент повинен знаходитися в
упорядкованому списку і вставляємо його туди
• Сортування злиттям (Merge sort) - Складність алгоритму: O (n log
n); потрібно O (n) додаткової пам'яті; вибудовуємо першу і другу
половину списку окремо, а потім - зливаємо впорядковані списки
Алгоритми стійкого сортування
• Сортування за допомогою двійкового дерева (англ. Tree sort) Складність алгоритму: O (n log n); потрібно O (n) додаткової пам'яті.
Є оптимальною при безпосередньому читанні з потоку (файла,
сокета, консолі)
• Сортування Timsort – комбінація алгоритмів сортування вставками
та злиттям. Складність алгоритму: O (n log n); потрібно O (n)
додаткової пам'яті.
• Блокова сортування (корзину, Bucket sort) - Складність алгоритму:
O (n); потрібно O (k) додаткової пам'яті і знання про природу даних,
які сортуються, це виходить за рамки функцій "переставити" і
"порівняти".
• Сортування підрахунком (Counting sort) - Складність алгоритму: O
(n + k); потрібно O (n + k) додаткової пам'яті. Використовується
діапазон чисел масиву, що сортується, для підрахунку елементів,
що співпадають. Використовується тоді, коли діапазон можливих
значень послідовності, що сортується, достатньо малий в порівнянні
з кількістю елементів послідовності (наприклад, міліон чисел в
діапазоні від 0 до 1000)
Алгоритми нестійкого сортування
• Сортування вибором (Selection sort) - Складність алгоритму: O (n2);
пошук найменшого або найбільшого елемента і поміщення його в
початок або кінець впорядкованого списку
• Сортування Шелла (Shell sort) - Складність алгоритму: O (n log2 n);
спроба поліпшити сортування вставками. Порівняння елементів, які
стоять на певній відстані один від одного (сортування вставками з
попередніми грубими проходами)
• Сортування гребінцем (Comb sort) - Складність алгоритму:
O(n*log(n)). Покращене сортування бульбашкою. Головна ідея –
усуеути черепах (маленькі елементи, що знаходяться в кінці списку).
Кролики (великі елементи на початку списку не створюють проблем)
• Пірамідальне сортування (Сортування купи, Heapsort) Складність алгоритму: O (n log n); перетворюємо список в купу,
беремо найбільший елемент і додаємо його в кінець списку.
• Плавне сортування (Smoothsort) - Складність алгоритму: O (n log
n). Різновид пірамідального сортування. Складність наближується
до O(n), якщо дані частково впорядковані
Алгоритми нестійкого сортування
• Швидке сортування (Quicksort) - Складність алгоритму: O (n log n) середній час, O (n2) - найгірший випадок. Найшвидший алгоритм з
відомих для впорядкування великих списків. З розбиттям вхідного
набору даних на жві частини так, що будь-який елемент першої
половини впорядкований відносно будь-якого елемента другої
половини, потім алгоритм застосовується рекурсивно до кожної
половини. При використанні O(n) додаткової пам’яті можна зробити
сортування стійким
• Інтроспективне сортування (Intro Sort) – поєднання швидкого та
пірамідального сортування. Пірамідальне сортування
застосовується, якщо глибина рекурсії перевищує log n. Складність
O (n log n)
• Терпляче сортування (Patience Sort). В найгіршому випадку
потребує O(n) додаткової пам’яті. Знаходить найдовшу зростаючу
послідовність.
• Сортування по частинах, блукаюче сортування (Stooge sort) –
рекурсивний алгоритм
• Сортування за розрядами (Цифрова сортування) - Складність
алгоритму: O (n · k); потрібно O (k) додаткової пам'яті.
Інші алгоритми сортування
• Сортування перестановкою - O (n · n!) - найгірший час. Для
кожної пари здійснюється перевірка вірного порядку і
генеруються всілякі перестановки вихідного масиву.
• Дурне сортування (Stupid sort) - O (n3); рекурсивна версія
вимагає додатково O (n2) пам'яті
• Млинцеве сортування (Pancake sorting) - O (n), потрібне
спеціалізоване апаратне забезпечення
• Топологічне сортування – впорядкування вершин
орієнтованого графа у відповідності з поставленим завданням
(алгоритм Кана)
• Зовнішнє сортування – сортування даних, що розташовані на
зовнішніх пристроях і не поміщаються в оперативній пам’яті
Сортування вставками
17
Сортування простими вставками
• Масив ділиться на дві частини
– «готову» a1, a2, …, ai-1
– вхідну ai, ai+1, …, aN
• Для кожного i від 2 до N
– з вхідної частини витягується i-й елемент
– вставляється в готову частину на потрібне місце
Пошук відповідного місця для чергового елемента
вхідної
послідовності
здійснюється
шляхом
послідовних порівнянь з елементом, що стоять перед
ним. Залежно від результату порівняння елемент або
залишається на поточному місці (вставка завершена),
або вони міняються місцями і процес повторюється.
Сортування простими вставками
int i, j;
for (i = 1; i < n; i++) {
int c = data[i];
for (j = i-1; j >= 0 && data[j] > c; j--) {
data[j+1] = data[j];
}
data[j+1] = c;
}
4 27 51 14 31 42 1
8 24 3 59 33 44 53 16 10 38 50 21 36
4 14 27 51 31 42 1
8 24 3 59 33 44 53 16 10 38 50 21 36
4 14 27 31 51 42 1
8 24 3 59 33 44 53 16 10 38 50 21 36
4 14 27 31 42 51 1
8 24 3 59 33 44 53 16 10 38 50 21 36
Сортировка вставками
Сортування простими вставками
• Аналіз алгоритма
– Найкращий випадок: масив впорядкований
– Найгірший випадок: массив впорядкований в
оберненому порядку
– Сmin = N – 1
Mmin = 3(N-1)
– Cavg = (N2 + N – 2)/4
Mavg = (N2 + 9N – 10)/4
– Cmax = (N2 + N – 4)/2
Mmax = (N2 + 3N – 4)/2
• Отже:
T(N) = C(N) + M(N) = O(N2)
Сортування бінарними вставками
Сортування простими вставками може бути поліпшене
• Можна прискорити пошук відповідного місця в «готовій»
частині, тому що вона впорядкована
• У впорядкованій послідовності можна застосувати
бінарний пошук!
• Складність бінарного пошуку в гіршому випадку є O(log N)
 Кількість порівнянь є O(N log N)
 Але все одно, M(N) = O(N2)
• Итог:
21
T(N) = O(N log N) +O(N2) = O(N2)
Сортировка вставками
Сортування обміном
(бульбашкове сортування)
Ідея методу:
бульбашка повітря в склянці води піднімається з дна
вгору - найменший («легкий») елемент масиву
переміщується вгору («спливає»)
крок сортування полягає в проході знизу вгору по
масиву. По дорозі проглядаються пари сусідніх
елементів. Якщо елементи деякої пари знаходяться в
неправильному порядку, то міняємо їх місцями.
Сортування обміном
(бульбашкове сортування)
• Для кожного i від 2 до N
• Для кожного j від N до i
– Якщо в парі елементів aj –1 і aj порушений порядок,
– то помяніти місцями aj –1 и aj
1-й прохід
23
2-й прохід
3-й прохід
5
5
5
1
1
1
1
1
1
2
2
1
5
5
5
2
2
2
1
1
2
2
2
2
5
5
3
3
3
3
3
3
3
3
3
5
Сортировка обменами
Сортування обміном
(бульбашкове сортування)
void main() {
const int N = 10;
int A[N], i, j, c;
// заповнити масив
елементи вище
// вивести вхідний масив
A[i] вже
for (i = 0; i < N-1; i ++){
поставлений
for (j = N-2; j >= i ; j --)
if ( A[j] > A[j+1] ) {
с = A[j];
A[j] = A[j+1];
A[j+1] = с;
міняємо
}
A[j] и A[j+1]
}
// вивести отриманий масив
Сортировка обменами
}24
Сортування «бульбашкою»
for (int i = 1; i < n; i++) {
for (int j = 0; j < n-i; j++) {
if (data[j] > data [j+1]) {
int tmp = data[j];
data[j] = data[j+1];
data[j+1] = tmp;
}
}
}
4 27 51 14 31 42 1
4 27 14 31 42 1
4 14 27 31 1
4 14 27 1
4 14 1
4
1
8 24 3 59 33 44 53 16 10 38 50 21 36
8 24 3 51 33 44 53 16 10 38 50 21 36 59
8 24 3 42 33 44 51 16 10 38 50 21 36 53 59
8 24 3 31 33 42 44 16 10 38 50 21 36 51 53 59
8 24 3 27 31 33 42 16 10 38 44 21 36 50 51 53 59
8 14 3 24 27 31 33 16 10 38 42 21 36 44 50 51 53 59
Покращений метод «бульбашки»
• Якщо при виконанні чергового проходу не було
обмінів, то масив уже відсортований і інші проходи не
потрібні
• Реалізується через змінну-прапорець, що показує, чи
були обміни
– Якщо прапорець піднято, то обміни були і потрібен
ще один прохід
– Якщо прапорець опущений, то - вихід
26
2
1
1
2
4
3
3
4
Покращений метод «бульбашки»
i = 0;
do {
flag = 0; // скинути прапорець
for ( j = N-2; j >= i ; j -- )
if ( A[j] > A[j+1] ) {
с = A[j];
A[j] = A[j+1];
A[j+1] = с;
flag = 1; // підняти прапорець
}
ii++;
++;
}
while ( flag ); // вихід при flag = 0
27
Сортировка обменами
Шейкерне сортування
• Метод бульбашки несиметричний
– При порушенні майже повного порядку «легкими»
елементами, потрібно мало проходів
– При порушенні майже повного порядку «важкими»
елементами, потрібно багато проходів
1 прохід
3 проходи
2
1
4
1
3
2
1
2
4
3
2
3
1
4
3
4
• Вихід: чергувати напрямок проходів
28
Шейкерне сортування
29
Сортировка обменами
Сортування простими обмінами
• Аналіз алгоритму
– Кращий випадок: масив впорядкований
– Найгірший випадок: масив упорядкований у
зворотному порядку
– Сmin = (N2 – N)/2
– Cavg = (N2 – N)/2
– Cmax = (N2 – N)/2
• Підсумок:
30
Mmin = 0
Mavg = (N2 – N)/4
Mmax = (N2 – N)/2
T(N) = C(N) + M(N) = O(N2)
Сортировка обменами
«Шейкерне» сортування
• Аналіз алгоритму
– Кращий випадок: масив впорядкований
– Найгірший випадок: масив упорядкований у
зворотному порядку
– Сmin = N – 1
– Cavg = (N2 – N(k+ln N))/2
– Cmax = (N2 – N)/2
• Підсумок:
31
Mmin = 0
Mavg = (N2 – N)/4
Mmax = (N2 – N)/2
T(N) = C(N) + M(N) = O(N2)
Сортировка обменами
Сортування вибором
Ідея методу полягає в тому, щоб створювати
відсортовану послідовність шляхом
приєднання до неї одного елемента за одним в
правильному порядку.
Суть алгоритму: Побудувати готову
впорядковану послідовність, починаючи з
лівого кінця масиву.
Алгоритм складається з n послідовних кроків,
починаючи від нульового і закінчуючи (n-1) -м.
На i-му кроці вибираємо найменший з елементів
a [i] ... a [n] і міняємо його місцями з a [i].
Приклад
Прямі методи сортування
• Сортування обмінами дещо менш ефективна, ніж
сортування вставками і вибором
• Шейкерні сортування вигідні, коли масив майже
впорядкований
• Загальна властивість: переміщення елементів рівно на
одну позицію за один прийом
• Можна показати, що середня відстань, на яке повинен
зсуватися елемент дорівнює N / 3
• Треба прагнути до далеких пересиланням елементів
34
Сортировка обменами
Сортування Шелла
• Сортування Шелла (англ. Shell sort) - алгоритм
сортування, ідея якого полягає в порівнянні
елементів, що стоять не тільки поруч, але і на
відстані один від одного. Іншими словами сортування вставками з попередніми «грубими»
проходами.
• При сортуванні Шелла спочатку порівнюються і
сортуються між собою ключі, віддалені один від
одного на деяку відстань d. Після цього процедура
повторюється для деяких менших значень d, а
завершується сортування Шелла упорядкуванням
елементів при d = 1 (тобто, звичайним сортуванням
вставками).
Сортування Шелла
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
4 27 51 14 31 42 1
8 24 3 59 33 44 53 16 10 38 50 21 36
4 10 3 14 21 36 1
8 24 38 50 31 42 53 16 27 51 59 33 44
step=7
step=3
1
8
3
4 10 36 14 21 24 27 44 31 33 50 16 38 51 59 42 53
1
4
3
8 10 21 14 27 16 31 24 36 33 38 42 50 44 53 51 59
1
3
4
8 10 14 16 21 24 27 31 33 36 38 42 44 50 51 53 59
step=2
step=1
Сортування Шелла
int n ;
// Довжина масива
int step = n;
// Крок пошуків і вставки
int i, j;
do {
// обчислюємо новий крок
step = step / 3 + 1;
// Виконуємо сортування простими вставками з заданим кроком
for (i = step; i < n; i++) {
int c = data[i];
for (j = i-step; j >= 0 && data[j] > c; j -= step) {
data[j+step] = data[j];
}
data[j+step] = c;
}
} while (step != 1);
Кількість перестановок елементів
(за результатами експериментів з випадковим масивом)
n = 25
n = 1000
n = 100000
Сортування Шелла
50
7700
2 100 000
Сорьування простими вставками
150
240 000
2.5 млрд.
Швидке сортування
Швидке сортування (англ. Quicksort) - широко
відомий
алгоритм
сортування,
розроблений
англійським інформатики Чарльзом Хоаром. Один з
найшвидших відомих універсальних алгоритмів
сортування масивів (в середньому O (n log n) обмінів
при упорядкуванні n елементів), хоча і має ряд
недоліків.
Короткий опис алгоритму
вибрати елемент, званий опорним. Порівняти всі інші
елементи з опорним, на підставі порівняння розбити
безліч на три - «менші опорного», «рівні» і «великі»,
розташувати їх в порядку менші-рівні-великі.
Повторити рекурсивно для «менших» і «великих».
Швидке сортування
0
1
2
3
4
5
6
4 27 51 14 31 42 1
7
8
9
10
11
12
13
14
15
16
17
18
19
8 24 3 59 33 44 53 16 10 38 50 21 36
h
l
1
3
4 10 8 14 51 42 24 27 59 33 44 53 16 31 38 50 21 36
1
3
4
8 10 14 36 42 24 27 21 33 44 50 16 31 38 51 53 59
1
3
4
8 10 14 31 16 24 27 21 33 36 50 44 42 38 51 53 59
1
3
4
8 10 14 21 16 24 27 31 33 36 38 44 42 50 51 53 59
1
3
4
8 10 14 16 21 24 27 31 33 36 38 44 42 50 51 53 59
1
3
4
8 10 14 16 21 24 27 31 33 36 38 42 44 50 51 53 59
Швидке сортування
Швидке сортування
• Псевдокод
41
Быстрая сортировка
int a[100];
void quickSort(int l, int r)
{
int x = a[l + (r - l) / 2];
//запис еквівалентний (l+r)/2,
//але не викликає переповнення на
великих даних
int i = l;
int j = r;
//код в while зазвичай виносять в
процедуру particle
while(i <= j)
{
while(a[i] < x) i++;
while(a[j] > x) j--;
if(i <= j)
{
swap(a[i], a[j]);
i++;
j--;
}
}
if (i<r)
quickSort(i, r);
if (l<j)
quickSort(l, j);
}
int main()
{
int n;//кількість елементів у масиві
scanf(“%d”,n]);
for(int i = 0; i < n; i++)
{
scanf(“%d”,a[i]);
}
quickSort(0, n-1);
for(int i = 0; i < n; i++)
{
printf(“%d ”,a[i]);
}
return 0;
}
Покращення алгоритма
• Перший елемент в сортованій частині
вибирається випадково і
запам'ятовується
• Ділянки, менші певного розміру,
упорядковуються простими способами
• Іноді виключення рекурсивних викликів
призводить до підвищення ефективності
43
Быстрая сортировка
Швидке сортування
• Аналіз алгоритму
– Ефективність в основному залежить від
збалансованості розбиття на підмасиви
• Найгірше розбиття: 1 до (N–1) => O(N2)
• Найкраще розбиття: N/2 до N/2 => O(N log N)
• Середній випадок:
O(N log N)
44
Быстрая сортировка
Алгоритм злиття впорядкованих масивів
4
14
27
51
1
3
8
24
31
42
59
int na, // довжина масиву a[]
nb, // довжина масиву b[]
nc;
int[] c = new int[nc = na + nb];
int ia = 0,
ib = 0,
ic = 0;
while (ia < na && ib < nb) {
if (a[ia] < b[ib])
c[ic++] = a[ia++];
else
c[ic++] = b[ib++];
}
while (ia < na) c[ic++] = a[ia++];
while (ib < nb) c[ic++] = b[ib++];
Сортування злиттям (фон
Неймана)
0
1
2
3
4
5
6
4 27 51 14 31 42 1
7
8
9
10
11
13
14
15
16
17
18
19
8 24 3 59 33 44 53 16 10 38 50 21 36
І так далі…
46
12
Сортировка слиянием
Алгоритм сортування злиттям
(фон Неймана)
• Псевдокод
// Merge() зливає два впорядкованих підмасива
// в єдиний підмасив
MergeSort(A, left, right) {
if (left < right) {
mid = floor((left + right) / 2); // середина
MergeSort(A, left, mid);
MergeSort(A, mid+1, right);
Merge(A, left, mid, right);
}
}
47
Сортировка слиянием
Алгоритм сортування злиттям
(фон Неймана)
#include <stdio.h>
#include <stdlib.h>
void merge (int *a, int n, int m) {
int i, j, k;
int *x = malloc(n * sizeof (int));
for (i = 0, j = m, k = 0; k < n; k++)
{
x[k] = j == n ? a[i++]: i == m ? a[j++]: a[j] < a[i] ?a[j++]: a[i++];
}
for (i = 0; i < n; i++) {
a[i] = x[i];
}
free(x);
}
void merge_sort (int *a, int n) {
if (n < 2)
return;
int m = n / 2;
merge_sort(a, m);
merge_sort(a + m, n - m);
merge(a, n, m);
}
int main () {
int a[] = {4, 65, 2, -31, 0, 99, 2, 83, 782, 1};
int n = sizeof a / sizeof a[0];
int i;
for (i = 0; i < n; i++)
printf("%d%s", a[i], i == n - 1 ? "\n" : " ");
merge_sort(a, n);
for (i = 0; i < n; i++)
printf("%d%s", a[i], i == n - 1 ? "\n" : " ");
return 0;
}
Output:
4 65 2 -31 0 99 2 83 782 1
-31 0 1 2 2 4 65 83 99 782
48
Сортировка слиянием
Сортування злиттям
• Аналіз алгоритма
– Аналіз призводить до складних
математичних задач
– Асимптотична складність – O(N log N)
49
Сортировка слиянием
Сортування підрахунком
Цей алгоритм підходить для сортування цілих чисел з
не дуже великого діапазону (порівнянного з розміром
масиву).Ідея алгоритму: для кожного елемента знайти,
скільки елементів, менших певного числа, і помістити це
число на відповідні місце.
За лінійний прохід по масиву для кожного з можливих
значень підраховуємо, скільки елементів мають таке
значення. Потім додаємо до кожного зі знайдених чисел
суму всіх попередніх. Отримуючи, таким чином, скільки
є елементів, значення яких не більше даного значення.
Далі, знову-таки за лінійний прохід, формуємо з
вихідного масиву новий відсортоване.
Сортування підрахунком
0
1
2
3
4
5
6
7
8
9
2
1
0
6
5
4
3
2
1
7
6
10
3
9
8
7
14
13
12
10
11
4
14
0
16
15
14
2
17
16
1
19
18
17
2
20
19
1
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
4
7
1
4
1
2
1
8
4
3
9
3
4
3
6
0
8
0
1
6
Цифрове (поразрядне)
сортування
Цифрове сортування - один з алгоритмів
сортування, що використовують внутрішню
структуру
сортируемих
об'єктів.
Алгоритм
полягає в послідовному сортуванні об'єктів будьяким стійким сортуванням по кожному розряду, в
порядку від молодшого розряду до старшого,
після чого послідовності будуть розташовані в
необхідному порядку.
Алгоритм поразрядного сортування MSD
Алгоритми поразрядного сортування аналізують значення цифр в
ключах в напрямку зліва направо. Першими обробляються найбільш
значущі цифри.
Такі методи в загальному випадку називаються поразрядним
сортуванням MSD (most significant digit radix sort - сортування за
розрядами спочатку по старшій цифрі).
У поразрядному сортуванні MSD аналізується мінімальний обсяг
інформації, необхідний для виконання сортування.
Сортування за розрядами MSD узагальнює поняття швидкого
сортування, оскільки воно виконується за рахунок поділу сортованого
масиву відповідно зі старшими цифрами ключів, після чого той же
метод застосовується до підмасивів в режимі рекурсії.
В умовах, коли в якості основи системи числення u1074 обрана 2,
сортування за розрядами MSD реалізується тим же способом, що і
швидке сортування.
53
Алгоритм поразрядного сортування MSD
Поразрядне сортування за молодшими розрядами
Поразрядне сортування за старшими розрядами
54
Алгоритм поразрядного сортування MSD
4 27 51 14 31 42 1
8 24 3 59 33 44 53 16 10 39 50 21 36
Після сортування за останньою цифрою:
10 50 51 31 1 21 42 3 33 53 4 14 24 44 16 36 27 8 59 39
Після стійкого сортування за першою цифрою:
1
3
4
8 10 14 16 21 24 27 31 33 36 39 42 44 50 51 53 59
Бібліотека STL
Функціональні
об’єкти
Адаптери
Алгоритми STL
• STL - алгоритми представляють набір
готових функцій, які можуть бути
застосовані до STL колекціям і можуть
бути поділені на три основні групи
Пошуку
Робота
з послідовностями
Математичні
Сортування
Алгоритми
• Алгоритми (algorithms) виконують операції над вмістом
контейнера (тобто над об’єктами контейнера).
• Існують найрізноманітніші алгоритми - від ініціалізації до заміни
вмісту контейнера. Окрім цього, вони дозволяють одночасно
працювати з двома контенерами різних типів. Багато алгоритмів
призначені для роботи з послідовністю, яка є лінійним списком
елементів всередині контейнера.
• Хоча кожен контейнер і підтримує власний набір операцій, проте
існує набір стандартних алгоритмів, які забезпечують більш
широкі і комплексні дії. Використання стандартних алгоритмів
пов’язане з необхідністю підикання ФЗ <algorithm.h>.
• Усі алгоритми з <algorithm. h> є функціями-шаблонами. Це дає
можливість використовувати їх з контейнерами будь-яких типів.
Наведемо приклад використання алгоритму, наприклад count.
Його реалізація в середовищі Borland C++ відрізняєтьтся від
реалізації у специфікації Standart C++. А тому приведемо
прклади для обох версій мови.
Алгоритми
• Наведемо приклад використання алгоритму, наприклад count.
Його реалізація в середовищі Borland C++ відрізняєтьтся від
реалізації у специфікації Standart C++. А тому приведемо
прклади для обох версій мови.
• Прототип алгоритму count у версії Standart C++ має вигляд
 template <class InIter, class T> size_t
count(InIter початок, InIter кінець, const T&
значення);
• Третій параметер значення є параметром на рівність якому
порівнються усі елементи контейнера, а їх кількість
повертається алгоритмом.
#include <iostream>
#include <vector>
using namespace std;
vector<int> mas;
main(){
cout<<"Введіть розмір масиву ";
int sz;
cin>>sz;
int val;
for(int i=0;i<sz;i++){
cout<<"Введіть "<<i<<" елемент";
cin>>val;
mas.push_back(val); // додавання елементів в масив
}
int n = count(mas.begin(),mas.end(),1);
cout<<"Кількість елементів рівних 1 є "<<n;
}
Функції алгоритмів
Алгоритми, які не змінюють
вміст контейнерів
for_each
find
find_end
find_if
find_first_of
adjacent_find
count
count_if
mismatch
equal
search
search_n
Чисельні алгоритми
accumulate
inner_product
partial_sum
adjacent_difference
Алгоритми сортування та пошуку
sort
stable_sort
partial_sort
partial_sort_copy
nth_element
lower_bound
upper_bound
equal_range
binary_search
merge
inplace_merge
includes
set_union
set_intersection
set_difference
set_symmetric_difference
make_heap
push_heap
pop_heap
sort_heap
min
max
min_element
max_element
lexicographical_compare
next_permutation
prev_permutation
Модифікуючі алгоритми
сору
copy_backward
swap_ranges
swap
iter_swap
transform
replace
replace_if
replace_copy
replace_copy_if
fill
fill_n
generate
generate_n
remove
remove_if
remove_copy
remove_copy_if
unique
unique_copy
reverse
reverse_copy
rotate
rotate_copy
random_shuffle
partition
Приклад застосування
• Найвидатніший алгоритм пошуку в STL - це двійковий
пошук. Алгоритм двійкового пошуку працює на
відсортованому масиві та здійснює пошук елемента,
розділивши масив навпіл.
Його загальний синтаксис:
binary_search(startaddr, endaddr, key)
Де,
startaddr: адреса першого елемента масиву.
endaddr: адреса останнього елемента масиву.
ключ: елемент для пошуку.
Приклад застосування
• STL надає нам алгоритм 'Сортування', який
використовується для розташування елементів у
контейнері в певному порядку.
Загальний синтаксис алгоритму сортування:
sort(startAddr, endAddr);
Де,
startAddr: початкова адреса сортуваного масиву.
endAddr: кінцева адреса сортуваного масиву.
• Внутрішньо STL використовує алгоритм Quicksort для
сортування масиву.
Приклад застосування
• Приклад для демонстрації алгоритму двійкового пошуку :
#include <iostream>
#include <vector> //використовуємо вектор
#include <algorithm> //використовуємо алгоритм бінарного пошуку
(binary_search)
using namespace std;
int main(void)
{
int A[]={1,3,3,4,5,6,7,8,9,10}; //перед пошуком масив потрібно відсортувати
vector<int> v(A,A+10); //копіюємо масив в вектор
copy(v.begin(),v.end(),ostream_iterator<int>(cout," "));//виводимо масив на екран
cout<<endl;
if (binary_search(v.begin(),v.end(),3)) cout<<“Елемент знайдений\n"; //якщо
пошук успішний
else cout<<“Елемента немає\n"; //якщо немає
return 0;
}
Приклад застосування
• Приклад для демонстрації алгоритму сортування:
#include <algorithm>
#include <vector>
using std::vector;
using std::sort;
bool decrease(int m, int n) { return m > n; }
int main()
{ vector<int> v = { 1, 11, 7, 4, 8 };
sort(v.begin(), v.end(), decrease);
return 0; }
Download