AlgStr / Практические занятия / Нелинейные структуры / Практична робота №7
.docПрактична робота № 7
Обхід бінарних дерев
Необхідно обійти вузли бінарного дерева з метою виконання деякої роботи.
Можна реалізувати у вигляді :
1. Генератора
2. Процедуры:
Procedure ITERATION(t:Ptree; P:ProcType);
де Р - процедура виду P(t:PTree);
яка виконує деяку обробку інформації, що зберігається у вузлі t бінарного дерева. Може мати деякі додаткові параметри або взаємодіяти з визначенням через глобальні змінні.
Обходи будуватимемо за допомогою другого способу Procedure ITERATION .
У відмінності від лінійних структур в БД дерева можна реалізувати значно більше видів обходів. Деякі обробки вимагають певного порядку обходів.
Якщо цього не вимагається, то порядок обходу повинен бути прихований усередині процедури ITERATION.
Дамо класифікацію обходів бінарного дерева
Багато обходів (але не все зручно визначити рекурсивно (т.е процедура застосовується точно також як до будь-якого поддереву дерева t)).
Розбиратимемо на прикладі:
У кружечках ключі вузлів
Завширшки - послідовність вузлів при суцільному представленні повного дерева в пам'яті ( номер елементу в масиві вузлів)
1. Лівобічний обхід (інфіксний або зворотний) симетричний
- спочатку обходиться ліве поддерево
- потім корінь
- потім обходимо праве поддерево
Цей алгоритм застосовується рекурсивно до будь-якого піддерева. Можна зобразити формулою :
Л – К – П
Отримаємо наступний порядок обходу:
Л-К-П:
2. Правобічний обхід ( зворотний, симетричний )
П-К-Л:
3. Правобічний обхід ( зворотний, симетричний )
К -Л - П:
4. Правобічний обхід ( зворотний, симетричний )
К-П-Л:
5. Кінцевий порядок обходу ( обхід знизу )
Л-П-К:
6. Кінцевий порядок обходу ( обхід знизу )
П-Л-К:
Реалізація рекурсивних обходів
Procedure ITERATION;
{ обхід в глибину }
Begin
If t <> nil then begin
P(t)
ITERATION(t^.left,P);
ITERATION(t^.right,P);
end
end
Переставляючи ці виклики отримаємо 6 різних дисциплін обходу
1) p, l, r
2) l, p, r
3) l, r, p 3*2*1=6
4) p, r, l
5) r, p, l
6) r, l, p
7) Горизонтальний обхід (обхід завширшки)
Краще його описувати нерекурсивно: Вузли дерева обходяться по рівнях
-корінь
-його два сини
-сини синів
і так далі.
Для суцільного уявлення дерева- це перегляд поряд елементів, що стоять.
Для зв'язаного дерева на базі покажчиків реалізація цього обходу найбільш важча.
Для пошуку алгоритму вирішення цього обходу . спочатку для алгоритму обходу в глибину процес опускання на вузол нижче виписати явно:
При рекурсії: Ми запам'ятовуємо в якомусь вузлі, ми знаходимося, виконуємо дії, і повертаємося в той же вузол ! Все це схоже на стек. Давайте спробуємо промоделіровать стік (у стеку запам'ятовуватимемо місце повернення) .здесь видно, що рекурсивна процедура робить значно більше, чим потрібно.Це міркування приводять нас небагато до іншої реалізації: Обробляємо корінь і переходячи в ліве поддерево, я в стеку запам'ятовую корінь правого поддерева(то, обхід чого я відклав) і так далі
Іноді в стеку взагалі нічого запам'ятати не треба (коли у вузлі тільки один син, Fx, при переході або
Конкретизуємо стек, специфікація якого представлена раніше, для зберігання в нім вузлів дерева , т.б. Т=PTree
Procedure ITERATION;
Var
Tek:Ptree
S:Stack_Tree
Begin
S.Init;tek:=t;
While tek<>nil do
Begin
P(tek); тут можливі 3 випадки
1) жодного поддерева немає
2) поддерево тільки одне (не важливе праве або ліве)
3) є обидва поддерева
if (tek^left=nil) and(tek^right=nil) then
if S.IsEmpty then tek:=nil
else tek:=S.Pop;
else
if tek^.right=nil then
tek:=tek^.left
else
if tek^.left=nil then
tek:=tek^.right
else begin
S.Push(tek^.right);
tek:=tek^left
end
end {while};
S.Destray
end;
Можна було відразу покласти в стек nil і тоді порожнечу в стеку перевіряти не треба було.
Але і так процедура вийшла не дуже складна.
Розглянемо дерево
1
2 3
4 6 7
8 9 14
Тощо.
В черзі будуть зберігатися всі не пройдені вершини з двох сусідніх рівнях. Таким чином отримуємо прохід в ширину.
Не добрала весь матеріал с карточки!!!!!!!!!!!!!!