2.3 Сортування вибором при допомозі дерева – алгоритм Тree Sort

Алгоритм сортування деревом ТreeSort власне кажучи є поліпшенням алгоритму сортування вибором. Процедура вибору найменшого елемента удосконалена як процедура побудови так званого сортуючого дерева. Сортуюче дерево - це структура даних, у якій представлений процес пошуку найменшого елемента методом попарного порівняння елементів, що стоять поруч. Алгоритм сортує масив у два етапи.

I етап : побудова сортуючого дерева;

II етап : просівання елементів по сортуючому дереву.

Розглянемо приклад: Нехай масив A складається з 8 елементів. Другий рядок складається з мінімумів елементів першого рядка, які стоять поруч. Кожний наступний рядок складений з мінімумів елементів, що стоять поруч, попереднього рядка.

Ця структура даних називається сортуючим деревом. У корені сортуючого дерева розташований найменший елемент. Крім того, у дереві побудовані шляхи елементів масиву від листів до відповідного величині елемента вузла -розгалуження.

Коли дерево побудоване, починається етап просівання елементів масиву по дереву. Мінімальний елемент пересилається у вихідний масив B і усі входження цього елемента в дереві заміняються на спеціальний символ M. Потім здійснюється просівання елемента уздовж шляху, відзначеного символом M, починаючи з листка, сусіднього з M і до кореня. Крок просівання - це вибір найменшого з двох елементів, що зустрілися на шляху до кореня дерева і його пересилання у вузол, відзначений M.

 

a6 = min(M, a6)

a6 = min(a6, a8)

a3 = min(a3, a6)

b2 := a3

Просівання елементів відбувається доти, поки весь вихідний масив не буде заповнений символами M, тобто n раз:

 

For і := 1 to n do begin

Відзначити шлях від кореня до листка символом M;

Просіяти елемент уздовж відзначеного шляху;

 

B[I] := корінь дерева

end;


Обґрунтування правильності алгоритму очевидно, оскільки кожне чергове просівання викидає в масив У найменший з елементів масиву А, що залишилися.

Сортуюче дерево можна реалізувати, використовуючи або двовимірний масив, або одномірний масиві ST[1..N], де N = 2n-1.

Аналіз алгоритму Tree Sort.

Оцінимо складність алгоритму в термінах M(n), C(n). Насамперед відзначимо, що алгоритм Tree Sort працює однаково на усіх входах, так що його складність у гіршому випадку збігається зі складністю в середньому.

Припустимо, що n - ступінь 2 (n = 2l). Тоді сортуюче дерево має l + 1 рівень (глибину l). Побудова рівня I вимагає n / 2I порівнянь і пересилань. Таким чином, I-ий етап має складність:

 

C1(n) = n/2+n/4+ ... + 2+1 = n-1, M1(n) = C1(n) = n - 1

Для того, щоб оцінити складність II-го етапу С2(n) і M2(n) помітимо, що кожен шлях просівання має довжину l, тому кількість порівнянь і пересилань при просіванні одного елемента пропорційно l. Таким чином,

 

M2(n) = O(l n),

C2(n) = O(l n).

Оскільки l = log2n, M2(n)=O(n log2 n)), C2(n)=O(n log2 n), Але З(n) = C1(n) + C2(n), M(n) = M1(n) + M2(n). Тому що C1(n) < C2(n), M1(n) < M2(n),остаточно одержуємо оцінки складності алгоритму Tree Sort за часом:

 

M(n) = O(n log2 n), C(n) = O(n log2 n),

У загальному випадку, коли n не є ступенем 2, сортуюче дерево будується трохи інакше. "Зайвий" елемент (елемент, для якого немає пари) переноситься на наступний рівень. Легко бачити, що при цьому глибина сортуючого дерева дорівнює [log2 n] + 1. Удосконалення алгоритму II етапу очевидно. Оцінки при цьому змінюють лише мультиплікативні множники. Алгоритм Tree Sort має істотний недолік: для нього потрібно додаткова пам'ять розміру 2n - 1.

 

2.4Сортування вибором при допомозі дерева – алгоритм Heap Sort

Прямий вибір - повторюваний пошук найменшого елемента серед N елементів, N-1 елементів, N-2 і т.д. Кількість порівнянь при цьому (N2-N)/2. Для підвищення ефективності необхідно залишати після кожного етапу побільше інформації окрім ідентифікації найменшого ключа.

Після N/2 порівнянь можна знайти в кожній парі елементів найменший, після N/4 порівнянь - менший із пари вже вибраних на попередньому кроці і т.д. Виконавши загалом N/2+N/4+...+2+1=N-1 порівнянь, можна побудувати дерево вибору та ідентифікувати його корінь як шуканий найменший елемент. Наприклад

крок I \ / \ / \ / \ /

 44 12 06

крок II \ /  \ /

12 06

крок III  \ /

06

На наступному етапі сортування проводиться рух вздовж віток, які відмічені мінімальними елементом, і вилучення його з дерева шляхом заміни на пустий елемент.

44[]

\ /  \ / \ / \ /

44 12 18 []

\ / \ /

12 []

 \ /

 []

Далі здійснюється заповнення "дірок" у дереві. На першому рівні залишається "дірка" від вилученого елемента, а на наступних знову вибирається менший із двох сусідніх попереднього рівня. "Дірка" при порівнянні вважається як завгодно великим значенням.

44[]

\ /  \ / \ / \ /

44 12 18 67

\ / \ /

 12 18

\ /

12

Елемент, що опинився в корені, - знову найменший. Після N таких кроків дерево стане пустим, в ньому будуть лише одні "дірки" (сортування закінчене). На кожному з N етапів виконується log(N) порівнянь. Тому на весь процес впорядкування потрібно порядку N*log(N) операцій плюс N-1 операцій для побудови дерева. Це значно краще ніж N2 для прямих методів і навіть краще ніж N1,2 для алгоритму Шелла. Однак при цьому виникає проблема збереження додаткової інформації. Тому кожен окремий етап в алгоритмі ускладнюється.

Корисно було б, зокрема, позбутися від "дирок", якими вкінці буде заповнене все дерево, і які породжують багато непотрібних порівнянь. Крім того, виникає потреба такої організації даних за принципом дерева, яка б вимагала N одиниць пам’яті, а не 2N-1. Цього вдалося добитися в алгоритмі Heap Sort, який розробив Д. Уілльямс. Він використав спеціальну деревовидну структуру - піраміду.

Піраміда - це означене, тобто задане елементами кореневе бінарне дерево, яке визначається як послідовність ключів a L , a L+1 , ..., a R , для якої справедливі нерівності

 та  для .(1)

Таким чином бінарне дерево сортувань виду

a1

/ \

a2=42a3=06

/ \ / \

 a4=55a5=94a6=18a7=12

являє собою піраміду, а елемент a1 буде найменшим в розглядуваній множині : a1=min(a 1 , a 2 , ..., a N).

Припустимо, що є деяка піраміда із заданими елементами a L+1 , ..., a R для певних значень L та R, і потрібно ввести новий елемент x, утворюючи таким чином розширену піраміду a L , a L+1 , ..., a R . В якості вихідної візьмемо піраміду a 1 , a 2 , ..., a 7 із попереднього прикладу і добавимо до неї зліва елемент a 1=44. Нова піраміда отримується так : спочатку x ставиться зверху деревовидної структури, а потім він поступово опускається вниз кожен раз в напрямку меншого з двох прилеглих до нього елементів, а сам цей менший елемент переміщується вгору. Процес просіювання продовжується доти, поки в жодній з прилеглих вершин не буде елемента меншого за нововведеного. В розглядуваному прикладі ключ 44 спочатку поміняється місцями з ключем 06, а потім з 12, і в результаті отримується таке дерево

06

/ \

42

/ \ / \

 94 18

Характерно, що такий метод просіювання залишає незмінними умови (1), які визначають піраміду.

Р. Флойд запропонував певний "лаконічний" алгоритм побудови піраміди "на тому ж місці". Вважається, що деяка частина елементів масиву a m , a 2 , ..., a N (m=Ndiv2) вже утворює піраміду - нижній шар відповідного бінарного дерева, для них ніякої впорядкованості не вимагається. Тепер піраміда розширюється вліво; кожен раз добавляється і просіюваннями ставитться у відповідну позицію новий елемент. Ці дії реалізуються проседурою Sift :

 

Procedure Sift(L, R : integer);

Var

i, j : integer; x : basetype;

Begin

i:=L; j:=2*L; x:=a[L];

if (j<R) and (a[j+1]<a[j]) then j:=j+1;

while (j<=R) and (a[j]<x) do

begin

a[i]:=a[j]; a[j]:=x; i:=j; j:=2*j;

if (j<R) and (a[j+1]<a[j]) then j:=j+1

end

End;

 

Таким чином, процес формування піраміди із N елементів a 1 , ..., a N "на тому ж місці" є повторюваним виконанням процедури Sift при зміні параметра L=Ndiv2, ..., 1 :

 

L:=N div 2 +1;

while L>1 do

begin

L:=L-1;

Sift(L, N)

end;

Для ілюстації алгоритму розглянемо попередній варіант масиву :

44 |

44 |

44 |

44 | 42

06

Тут жирним шрифтом виділені добавлювані до піраміди елементи; підкреслені - елементи, з якими проводився обмін.

Для того, щоб отримати не тільки часткове, а і повне впорядкування серед елементів послідовності, потрібно виконати N зсувних етапів. Після кожного проходу на вершину дерева виштовхуватиметься черговий найменший ключ. Знову виникає питання : де зберігати "спливаючі" верхні елементи і чи можна проводити перестановки "на тому ж місці"? Це легко реалізувати, якщо кожен раз брати останню компоненту піраміди - це буде просіюваний ключ x, ховати верхній елемент з попереднього етапу в звільнене позицію, а x зсувати на відповідне місце. Зрозуміло, що після кожного етапу розглядувана піраміда буде скорочуватися на один елемент справа. Таким чином, впорядкування масиву буде здійснено за N-1 прохід :

06 42 12 55 94 18 44 67обмін 67 і 06

67 42 12 55 94 18 44 | 06просіювання 67

12 42 18 55 94 67 44 | 06обмін 44 і 12

44 42 18 55 94 67 | 12 06просіювання 44

18 42 44 55 94 67 | 12 06обмін 67 і 18

67 42 44 55 94 | 18 12 06просіювання 67

42 55 44 67 94 | 18 12 06обмін 94 і 42

94 55 44 67 | 42 18 12 06просіювання 94

44 55 94 67 | 42 18 12 06обмін 67 і 44

67 55 94 | 44 42 18 12 06просіювання 67

55 67 94 | 44 42 18 12 06обмін 94 і 55

94 67 | 55 44 42 18 12 06просіювання 94

67 94 | 55 44 42 18 12 06обмін 94 і 67

94 | 67 55 44 42 18 12 06просіювання 94

94 | 67 55 44 42 18 12 06

Тут жирним шрифтом виділені просіювані по піраміді елементи; підкреслені - елементи, між якими проводився обмін.

Процес сортування описується за допомогою процедури Sift таким чином:

 

R:=N;

while R>1 do

begin

x:=a[1]; a[1]:=a[R]; a[R]:=x;

R:=R-1;

Sift(1, R)

end;

 

Як видно з прикладу, отриманий порядок ключів фактично є зворотнім. Це легко виправити, помінявши напрямок відношення порівняння в процедурі Sift на протилежний. Остаточно процедура сортування масиву методом Heap Sort матиме вигляд :

 

Procedure Heap_Sort;

Var

L, R : integer; x : basetype;

Procedure Sift(L, R : integer);

Var

i, j : integer; x : basetype;

Begin

i:=L; j:=2*L; x:=a[L];

if (j<R) and (a[j]<a[j+1]) then j:=j+1;

while (j<=R) and (x<a[j]) do

begin

a[i]:=a[j]; a[j]:=x; i:=j; j:=2*j;

if (j<R) and (a[j]<a[j+1]) then j:=j+1

end

End;

Begin

L:=N div 2 +1; R:=N;

while L>1 do

begin L:=L-1; Sift(L, N) end;

while R>1 do

begin

x:=a[1]; a[1]:=a[R]; a[R]:=x;

R:=R-1;

Sift(1, R)

end

End;

 

Аналіз алгоритму Heap Sort. Як вже раніше відмічалося, складність алгоритму по операціях порівняння є величиною порядку O(N*log(N)+N). Кількість переміщень елементів суттєво залежить від стартового розміщення ключів в послідовності.

Однак при початково-впорядкованому масиві не слід чекати максимальної ефективності. Адже об’єм перестановок в цьому випадку є досить великим під час просіювання "важких" елементів після побудови піраміди. Фактично на кожному етапі такого просіювання виконується log(K) перестановок плюс ще N-1 обмін перед просіюванням, де K - кількість елементів в піраміді, в якій проводиться просіювання. Таким чином, в цьому випадку

.

Тому можна вважати, що розглядуваний метод як і по порівняннях так і по перестановках має ефективність порядку O(N*log(N)+N).


Информация о работе «Порівняльний аналіз ефективності та складності швидких алгоритмів сортування масивів»
Раздел: Информатика, программирование
Количество знаков с пробелами: 43832
Количество таблиц: 1
Количество изображений: 0

Похожие работы

Скачать
182729
21
21

... Висновки по розділу 3 У даному розділі диплома була розроблена автоматизована інформаційна система розрахунку прибутку на гірничо-збагачувальному підприємстві. Дана система була розроблена для підвищення ефективності роботи підприємства. В основу алгоритмів обробки даних покладені методи математичної статистики й оптимізаційні моделі. Для проектування і реалізації автоматизованої інформаційної ...

Скачать
173833
3
2

... стимулювати учнів до нових зусиль у роботі, до самостійного переборення труднощів – це істотна ознака майстерності вчителя. Розділ 2. Технологія організації самостійної роботи учнів на уроках у початковій школі 2.1 Дидактичні умови організації самостійної роботи молодших школярів Визначаючи дидактико-методичні підходи до організації самостійної роботи учнів, ми враховували творчі надбання ...

Скачать
213419
24
23

... ·  пошуковий механізм, який користувачі використовують як інтерфейс для взаємодії з базою даних. Засоби пошуку типу агентів, павуків, кроулерів і роботів використовуються для збору інформації про документи, які знаходяться в мережі Інтернет. Це спеціальні програми, які займаються пошуком сторінок в мережі, збирають гіпертекстові посилання з цих сторінок і автоматично індексують інформацію, яку ...

Скачать
304576
89
18

... Чарка, стакан 4 320 2 80 400 Столові прибори (комплект) 4 320 2 80 400 Далі наведемо характеристику посуду, який будуть використовувати в комплексному закладі ресторанного господарства (табл. 2.8–2.11). Таблиця 2.8. Характеристика та призначення класичного вітчизняного порцелянового та фаянсового посуду Найменування Розміри, мм Місткість, см3, порцій Призначення ...

0 комментариев


Наверх