Дати поняття про впорядкування табличних величин та методи впорядкування. Навчити розв'язувати задачі, що потребують сортування.
Лекційний.
Дуже часто при розв'язуванні задач, пов'язаних з обробкою масивів, необхідно
виконувати сортування його елементів за зростанням або спаданням. Такі задачі
мають велике практичне значення. Розглянемо деякі з методів, що дозволяють впорядкувати
елементи таблиць.
Всі існуючі методи сортування можна поділити на три групи:
обмінні сортування - виконується обмін між собою двох деяких (найчастіше сусідніх)
елементів масивів, якщо відповідні елементи розташовані у вихідному масиві невірно;
процес повторюється або певну кількість разів, або доки при черговому проході
елементи в масиві не будуть переставлятися;
· методи прямого вибору - в масиві вибирається елемент з певними властивостями
(наприклад, мінімум або максимум), а потім вибраний елемент становиться на своє
місце;
методи прямої вставки - послідовно вибирається елемент з масиву і після визначення
його місця у впорядкованому наборі даних вставляється безпосередньо на своє
місце.
Найбільш відомим обмінним сортуванням являється метод "бульбашки".
В ньому при послідовному проході по масиву порівнюються два сусідніх елементи.
Якщо їх розміщення являється неправильним (наприклад, при впорядкуванні за зростанням
лівий елемент більший за правий), виконується взаємообмін елементів. Процес повторюється
щонайменше N-1 разів, де N - кількість елементів в масиві.
Простіший алгоритм "бульбашки" має наступний вигляд :
Program Bubble; {Сортування за зростанням} Const N=20; Var Mas:array[1..N] of integer; i,j:integer; {i,j - змінні циклу} Rez:integer; {Rez - додаткова змінна для обміну елементів масиву між собою} Begin For i:=1 to N do For j:=1 to N-1 do If Mas[j]>Mas[j+1] then Begin {Обмін елементів масиву через третю змінну} Rez:=Mas[j]; Mas[j]:=Mas[j+1]; Mas[j+1]:=Rez; End; End.Метод можна модифікувати, зменшуючи діапазон сортування після кожного проходу, адже ясно, що після кожного проходу максимальний елемент масиву буде "спливати наверх", тобто займати спочатку останню позицію таблиці, потім передостанню і таке інше (дивись таблицю).
Початковий масив
|
Прохід 1
|
Прохід 2
|
Прохід 3
|
Прохід 4
|
Прохід 5
|
Прохід 6
|
Прохід 7
|
Прохід 8
|
703
765 677 612 509 154 426 653 275 897 170 908 061 512 087 503 |
908
703 765 677 612 509 154 426 653 275 897 170 512 061 503 087 |
908
897 703 765 677 612 509 154 426 653 275 512 170 503 061 087 |
908
897 765 703 677 653 612 509 154 426 512 275 503 170 087 061 |
908
897 765 703 677 653 612 512 509 154 426 503 275 170 087 061 |
908
897 765 703 677 653 612 512 509 503 154 426 275 170 087 061 |
908
897 765 703 677 653 612 512 509 503 426 154 275 170 087 061 |
908
897 765 703 677 653 612 512 509 503 426 275 154 170 087 061 |
908
897 765 703 677 653 612 512 509 503 426 275 170 154 087 061 |
Програма, що реалізує описаний алгоритм має наступний вигляд:
Program Bubble; {Сортування за зростанням}
Const N=20;
Var Mas:array[1..N] of integer;
i,j:integer; {i,j - змінні циклу}
Rez:integer; {Rez - додаткова змінна для
обміну елементів масиву між собою}
Begin
For i:=1 to N do
For j:=1 to N-i do
If Mas[j]>Mas[j+1]
then
Begin
{Обмін елементів масиву через третю змінну}
Rez:=Mas[j];
Mas[j]:=Mas[j+1];
Mas[j+1]:=Rez;
End;
End.
Зверніть увагу, що в цьому алгоритмі у вкладеному циклі, що безпосередньо здійснює
порівняння елементів, змінна циклу змінюється за іншим законом, ніж в попередньому
випадку: від 1 до N-i, де i - змінна циклу зовнішньої команди повторення.
Другий метод модифікації алгоритму "бульбашки" полягає в тому, що ми
вводимо додаткову змінну булівського типу (так званий прапорець), яка буде фіксувати,
при черговому проході була здійснена хоча б одна перестановка елементів чи ні.
Очевидно, що якщо при черговому проході ні однієї перестановки не було зроблено,
то масив вже відсортований і процес перегляду можна припинити.
Домовимось вважати прапорець "опущеним" (тобто рівним значенню false),
якщо перестановки не відбулося, і "піднятим" (рівним true) -
в протилежному випадку. Крім того, на забуваємо, що як і в попередньому випадку,
після кожного проходу по масиву найбільший елемент "спливає" наверх,
тобто займає своє позицію. Тому вводимо додаткову змінну k, що фіксує праву
границю впорядкованості, тобто при першому проході k=1 і ми впорядковуємо
всі елементи від 1 до N-1, на другому проході k=2 і будуть впорядковуватись
всі елементи від 1 до N-2 (останній елемент вже впорядкований) і так далі.
Програма, що виконує описаний вище алгоритм, має наступний вигляд:
Program Bubble; {Сортування за зростанням} Const N=20; Var Mas:array[1..N] of integer; i,j,k:integer; {i,j - змінні циклу, k - змінна, що фіксує праву границю впорядкування} Rez:integer; {Rez - додаткова змінна для обміну елементів масиву між собою} Flag:Boolean; {Flag - змінна, що фіксує, відбулася перестановка чи ні} Begin k:=1; Repeat Flag:=false; {Робимо припущення, що масив відсортований, а потім перевіряємо, чи правильним було це припущення, тобто чи немає серед елементів таких, що неправильно розташовані, якщо такі елементи будуть, то ми їх переставляємо і Flag присвоюємо значення true} For i:=1 to N-k do Begin If Mas[i]>Mas[i+1] then Begin {Обмін елементів масиву через третю змінну} Rez:=Mas[i]; Mas[i]:=Mas[i+1]; Mas[i+1]:=Rez; Flag:=true; End; k:=k-1; Until Flag = false; End.Мовою блок-схем алгоритм сортування "бульбашкою" має наступний вигляд (третій із запропонованих):
Другим методом сортування є метод прямого вибору. Один з його
різновидів полягає в тому, що вибирається мінімальний елемент масиву, а потім
виконується його обмін з першим елементом таблиці. Після цього перший елемент
вважається впорядкованим і процес повторюється для підмасиву, що містить на
один елемент менше за початковий, тобто елементи з 2-го до останнього. Процес
повторюється кожен раз для масиву, зменшеного на один елемент. Закінчується
він тоді, коли невпорядкований підмасив стає довжиною один елемент. Таким чином,
загальна кількість повторень дорівнює, як і в попередньому випадку, N-1
(N - кількість елементів масиву).
Програмна реалізація запропонованого методу наведена нижче:
Program Selection; Const N=20; Var Mas:array[1..N] of integer; i,j,Min,N_Min:integer; Begin For i:=1 to N-1 do Begin Min:=Mas[i]; {Зберігання еталону мінімуму} N_Min:=i; {Зберігання номера мінімуму} For j:=i+1 to N do If Mas[j]Зверніть увагу на те, що пошук мінімуму в програмі організований стандартно, тобто перший елемент береться за еталон, а потім порівнюється з усіма останніми і, якщо новий елемент являється меншим за еталон, то еталон переприсвоюється. Крім цього в алгоритмі запам'ятовується місце знаходження цього мінімального елемента для того, щоб після виходу з циклу можна було обміняти місцями знайдений мінімум і перший елемент підмасиву. Але так як підмасив весь час змінює свій розмір, за еталон береться перший елемент саме того підмасиву, який розглядається на наступному кроці, тобто і-ий елемент початкового масиву (і - змінна зовнішнього циклу, що вказує на початок нового підмасиву на кожному кроці).then Begin Min:=Mas[j]; {Перевизначення еталону} N_Min:=j; {Зберігання номеру еталону} End; {Обмін місцями мінімуму та першого елементу підмасиву} Mas[N_Min]:=Mas[i]; Mas[i]:=Min; End; End.
Program Insert; Const N=20; Var Mas:array[1..N] of integer; i,j,Rez:integer; Begin For i:=2 to N do Begin j:=i; {Цикл працює доки, лівий елемент більший за правий та не досягнуто початок масиву} while (j>1) and (Mas[j]<Mas[j-1]) do Begin Rez:=Mas[j]; Mas[j]:=Mas[j-1]; Mas[j-1]:=Rez; j:=j-1; End; End; End.