|
І |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
<• |
/ |
2 |
3 |
4 |
.5 |
6 |
7 |
8 |
|
а, |
06 |
55 |
18 |
44 |
42 |
12 |
67 |
94 |
а, |
55 |
44 |
18 |
06 |
42 |
12 |
67 |
94 |
Мал. 64
171
@©@
@©@
|
І |
/ |
2 |
3 |
4 |
5 |
6 |
7 |
в |
|
i |
І |
2 |
3 |
4 |
5 |
в |
7 |
8 |
|
«, |
.12 |
44 |
18 |
06 |
42 |
55 |
67 |
94 |
а, |
44 |
42 |
18 |
06 |
12 |
55 |
67 |
94 |
Мал. 65
(06


|
І |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
1 |
і |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
at |
12 |
42 |
18 |
06 |
44 |
55 |
67 |
94 |
а, |
42 |
12 |
18 |
06 |
44 |
55 |
67 |
94 |
|
|
К |
1ал. 6 |
6 |
||||||||||||||||
|
®Ґ®% |
Ог^ое) |
|||||||||||||||||
|
@©@©@ |
|
@©@@@ |
||||||||||||||||
|
: |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
і |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
а, |
06 |
12 |
18 |
42 |
44 |
55 |
67 |
94 |
°, |
18 |
12 |
06 |
42 |
44 |
55 |
67 |
94 |
|
Мал. 67
06
12
![]()
![]()
12)
@©@@@@
|
І |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
і |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
|
а, |
06 |
12 |
18 |
42 |
44 |
55 |
67 |
94 |
аі |
06 |
12 |
18 |
42 |
44 |
55 |
67 |
91 |
Мал. 68
172
@©@@@@@
@©@@@@@©
|
І |
1 |
2 |
3 |
4 |
5 |
6' |
7 |
8 |
|
а, |
06 |
12 |
18 |
42 |
44 |
55 |
67 |
94 |
Мал. 69
А тепер перейдемо до узагальнення всього вищесказаного.
Метод, що базується на описаному вище алгоритмі, нази-ваеться HeapSort.
Подивимося на загальний вигляд бінарного дерева як на піраміду (мал. 70).

Мал. 70
Аналізуючи малюнок 70, неважно помітити таку закономір-ність:
hi>h2lTahl>h2l + vRei = 1, 2, ..., [л/2].
3 малюнка 70 видно, що термінальними вершинами є ті, порядков! номери яких у масиві більші за [л/2]. Усім іншим еле-ментам масиву в бінарному дереві відповідають вершини, які мають нащадків. Тому згідно з нашим алгоритмом будувати піраміду треба для елементів масиву з індексами і - [л/2], [л/2] - 1,..., 2, 1. Саме в такій послідовності треба переглядати елементи масиву на кожному етапі, включати їх у бінарне дерево і будувати одночасно піраміду.
Визначаючи дерево як піраміду, слід констатувати, що Aj = max (л,, h2,..., hn). Але аналогічно елемент h2 є найбільшим для свого піддерева, а л3 - для свого. А це означав, що при ви-лученні (згідно з нашим алгоритмом) для наступного перегляду найбільшого елемента масиву, який знаходиться в корені побудованої піраміди, для подальшого збереження властивос-тей піраміди в бінарному дереві кількість переставлень якщо не зменшуеться, то явно не збільшується.
Отже, підіб'ємо підсумок наших міркувань у вигляді словесного алгоритму. Фактично цей алгоритм складається з двох кроків:
173
побудувати піраміду для тієї частини масиву, яка розгля-дається на даному кроці;
поміняти місцями найбільший елемент, який знаходиться в корені дерева, з останнім елементом тієї частини масиву, що розглядається, та зменшити з кінця кількість елементів масиву, частина якого розглядається.
Реалізуємо цей алгоритм мовою програмування Pascal.
Спершу розглянемо процедуру, яка реалізує переміщення поточного L-го елемента масиву на свое місце в піраміді. Це здійснюється шляхом порівняння його значения зі значениями безпосередніх нащадків. Якщо серед нащадків є більший за по-точний елемент, то піднімаємо його на місце поточного і визна-чаємо цього нащадка поточним елементом. Процес завер-шується в одному з таких двох випадків: або ми дійшли до тер-мінальної вершини, або обидва нащадки менші за поточний елемент. Отже, процедура pyramida будує піраміду з елементів масиву aL, ..., aR.
procedure pyramida (L, R: word); var i, j: word; x: word;
begin {Запам'ятовуємо значения вершини,)
X := а[Ц; {яке необхідно поставити на свое місце в піраміді.)
i := L; {Визначаємо цю вершину поточною.)
j := 2 * L; {Визначаємо лівого нащадка для поточної вершини.)
{Якщо існує правий нащадок для поточноі вершини)
if (j<R) and (a[j + 1] > a[j]) {i він більшийзалівого,)
then j := j + 1; {то переходимо до нього.)
{Переглядаємо всіх нащадків, які більші за поточний елемент.)
while (j <= R) and (a[j] > x) do
begin
{Якщо нащадок більший за поточний елемент,)
a[i] := a[j]; {то переміщаємо його на місце поточного.)
І := j; {Переходимо до нащадка як до поточного елемента.)
j := 2 * j; {Визначаємо для поточного елемента його нащадка.)
{Якщо існує правий нащадок для поточно! вершини)
if (j<R) and (a[j + 1] >a[j]) {i він більший за лівого,)
then j := j + 1 {то переходимо до нього.)
end;
а[І] := X {Ha місце поточно! вершини записуємо значення елемента а[Ц.)
end;
Тепер основна частина алгоритму виглядатиме так:
L := (n div 2) + 1; R := п; {Визначимо термінальні вершини.)
{Формування стартової піраміди із заданих п елементів масиву.) while L > 1 do begin
L := L - 1; {Переміщення L від (n div 2) + 1 до 1.)
{Включения кожного L-го елемента масиву в піраміду.) pyramida (L, R) end;
174
while R > 1 do {Перегляд фрагментів масивуа[1] a[R].)
begin
x:=a[1]; a[1] :=a[R]; a[R] :=x; {Обмінмісцямиелементіва[і]іа[Я].} R := R - 1; {Зменшення довжини масиву з кінця.} pyramida (1, R) {Побудова піраміди для фрагментів масиву а[1] а[Я].}
end;
Аналіз алгоритму пірамідального сортування полягає у визна-ченні середньої кількості дій, що їх треба виконати для здійснен-ня сортування будь-якого масиву за допомогою цього методу.
Раніше зазначалося, що даний алгоритм складається з двох частин: побудова піраміди для фрагмента масиву та вилучення найбільшого елемента, який з'явився у корені бінарного дерева.
Із цих міркувань можна визначити оцінку ефективності ви-користання методу пірамідального сортування. Рух по бінарно-му дереву будь-якого елемента для побудови піраміди стано-вить 0(log2n). Але оскільки цю процедуру треба виконати для всіх п елементів масиву, то остаточна оцінка даного методу ста-новить 0(п log2n).
Оскільки метод пірамідального сортування належить до удосконалених методів, то результати його тестування повин-ні відповідно це продемонструвати. Рекомендується підібрати такі вхідні дані:
вхідний масив уже впорядкований необхідним чином;
вхідний масив є частково впорядкованим;
вхідний масив упорядкований у зворотному порядку;
елементи вхідного масиву розміщені випадковим чином. При тестуванні передбачити п = 10, п = 100, п = 1000,
п = 10 000, п = 30 000.
/ Запитання для самоконтролю
На якому методі прямого сортування базується метод піра-мідапьного сортування?
Зобразіть одновимірний масив у вигляді бінарного дерева, ви-користавши для цього власний приклад.
Як виглядатиме бінарне дерево, побудоване з того самого масиву, що й у запитанні 2, але після його упорядкування за спаданиям?
Які характерні ознаки можна відмітити, порівнюючи бінарні дерева у запитаннях 2-3?
Яке бінарне дерево можна називати пірамідою, або бінарною купою?
Що можна сказати про значения елемента, який знаходиться в корені піраміди?
Продемонструйте на власному прикладі перетворення будь-якого бінарного дерева на піраміду, зобразивши цю інформацію як у вигляді дерева, так і у вигляді масиву.