Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ДЕРЕВЬЯ.doc
Скачиваний:
23
Добавлен:
13.02.2015
Размер:
241.15 Кб
Скачать

Inf_s : Tree;

next : Stack

end;

Процедура добавления в стек start элемента T :

procedure Push (var start:Stack; T : Tree);

Var p:Stack;

begin

new(p);

p^.inf_S:=T;

p^.next:=start;

start:=p

end;

Процедура извлечения из стека start элемента T :

procedure Pop (var start:Stack; var T : Tree);

Var p:Stack;

begin

p:=start;

T:=start^.inf_S;

start:=start^.next;

dispose(p)

end;

Функция проверки, является ли стек start пустым :

function Empty (start:Stack): boolean;

begin

Empty:=start=nil

end;

Процедура префиксного обхода дерева :

procedure PrefOrd (T : Tree);

Var start : Stack; flag : boolean;

begin

start:=nil; { очистить стек }

flag:=true;

while flag do

begin

{ операция обработки узла дерева , например, writeln( T^.inf );}

{ перейти к следующему узлу }

if T^.L <> nil then { есть левая ветвь }

begin

{ если правая ветвь есть, то ссылку на нее добавить в стек }

if T^.R <> nil then Push(start,T^.R);

T:=T^.L { по левой ветви вниз }

end

else

if T^.R <> nil then { есть правая ветвь }

T:=T^.R { по правой ветви вниз }

else { нет обеих ветвей }

begin

if Empty(start) then { если стек пуст }

flag:=false { конец обхода }

else { извлечь ветвь из стека и идти по ней }

Pop(start,T)

end

end {while}

end; { PrefOrd }

Упражнение 3.1. Описать нерекурсивную процедуру

а) инфиксного обхода дерева;

б) постфиксного обхода дерева.

3.2 Обработка узлов дерева

Рассмотрим двоичное дерево, узлы которого содержат в информационной части целые числа. Назовем их элементами дерева.

Пример 3.5. Описать процедуру вывода дерева, выделяющую каждый уровень h с помощью соответствующего отступа.

procedure PrintTree(T : Tree; h : integer );

Var I : integer;

begin

if T <> nil then

begin

PrintTree (T^.R, h+1);

for i:=1 to h do write(‘ ‘);

writeln( T^.inf );

PrintTree (T^.L, h+1);

end

end; { PrintTree }

Здесь используется не инфиксный обход, а обход справа налево, чтобы дерево не выдавалось в зеркальном отображении.

Так как корень дерева Root находится на нулевом уровне, то обращение к процедуре PrintTree будет иметь вид

PrintTree(Root,0)

Пример 3.6. Описать процедуру MaxEl , определяющую наибольший элемент непустого дерева T.

Алгоритм MaxEl использует префиксный обход дерева: наибольший элемент находится или в узле, или в его левом поддереве, или в его правом поддереве.

procedure MaxEl(T : Tree; var max : integer);

Var m : integer;

begin

if T <> nil then

begin

max:=T^.inf;

if T^.L <> nil then

begin

MaxEl(T^.L, m);

if m > max then max:=m

end;

if T^.R <> nil then

begin

MaxEl(T^.R, m);

if m > max then max:=m

end

end

end; { MaxEl }

Пример 3.7. Описать рекурсивную процедуру Leaf подсчета количества k листьев дерева.

procedure Leaf( T : Tree; var k : integer);

begin

if T <> nil then

if (T^.L=nil) and (T^.R=nil) then

k:=k+1

else

begin

Leaf(T^.L,k);

Leaf(T^.R,k)

end

end; { Leaf }

Количество List листьев дерева Root можно определить, обратившись к процедуре Leaf :

List:=0; Leaf(Root,List);

Если описать реализацию в виде функции, то не придется заботиться о присваивании нуля параметру–результату перед ее вызовом.

function fLeaf ( T: Tree ) : integer;

begin

if T=nil then fLeaf:=0

else

if (T^.L=nil) and (T^.R=nil) then

fLeaf:=1

else fLeaf:= fLeaf(T^.L)+fLeaf(T^.R)

end {fLeaf};

Пример 3.8. Описать рекурсивную функцию Double, которая проверяет, есть ли в дереве T хотя бы два одинаковых элемента.

Один из вариантов проверки состоит в использовании функции Count подсчета числа вхождений заданного элемента El в дерево T. Функция Double поочередно проверяет число вхождений текущего значения T^.inf в дерево: если число вхождений больше 1, то результат проверки – истина, если нет, то такая ситуация может возникнуть в левом поддереве или в правом поддереве.

function COUNT(T : Tree; El :integer ) : integer;