
Министерство образования Российской Федерации
Санкт–Петербургский Государственный
Электротехнический Университет
Кафедра МО ЭВМ
Дисциплина: Программирование
Отчёт по лабораторной работе №3
«Бинарные деревья»
Выполнил:
студент группы 3341, Худяков Я.Д.
Проверил:
Преподаватель, Алексеев А. Ю.
Санкт-Петербург
2004
-
Содержательная постановка задачи.
Для заданного леса с произвольным типом элементов:
а) получить естественное представление леса бинарным деревом;
б) вывести изображение леса и бинарного дерева;
Пример решения:
Допустим, что дан лес из 2-х деревьев:
Необходимо получить представление этого леса бинарным деревом:
-
Формальная постановка задачи.
Входные данные
Входные данные представлены в файле der_in.txt в виде строк, сожержащих деревья исходного леса, записанные в скобочном представлении.
Определение скобочного представления:
< лес > ::= пусто | < дерево > < лес >,
< дерево > ::= ( < корень > < лес > ).
Корень определим как любой символ английского алфавита.
Выходные данные
Выходными данными на экран являются сообщения об различных ошибках программы, перевёрнутая картинка исходного леса и полученного бинарного дерева и его скобочное представление(если оно было получено). Выходными данными в файле являются коментарии о чтении строк входного файла, которые имют вид:
Считываю дерево номер #...
Дерево номер # считано. Скобочная запись дерева:
##################
или
Считываю дерево номер #...
Ошибка в записи дерева номер #. Дерево не считано.
Затем картинка исходного леса, полученного бинарного дерева и его скобочное представление(если оно было получено).
Исключительные ситуации
Исключительные ситуации могут возникнуть по следующим причинам:
-
Входной файл содержит строку, не удовлетворяющую правилам скобочной записи дерева. В этом случае будет выдано сообщение о шибке и эта строка будет проигнорирована.
-
Входной файл содержит лес с количеством деревьев, превышающее допустимое. В этом случае будет выдано сообщение об ошибке, ввод деревьев прекратится.
-
Входной файл пуст. В этом случае будет выдано соответствующее сообщение.
-
Описание алгоритма.
Исходный лес F представляется как совокупность трех частей:
1) корня первого дерева Root (Head (F)),
2) леса поддеревьев первого дерева Listing (Head (F)),
3) леса остальных деревьев Tail (F).
Из этих трех частей рекурсивно порождается бинарное дерево B (F), представляющее лес F:
-
B (F) if Null (F) then
else ConsBT (Root (Head (F)),
B (Listing (Head (F))),
B (Tail (F))).
Согласно этому определению корнем бинарного дерева B (F) является корень первого дерева Т1 в лесу F, левым поддеревом бинарного дерева B (F) является бинарное дерево, представляющее лес поддеревьев первого дерева Т1, а правым поддеревом бинарного дерева B (F) является бинарное дерево, представляющее лес остальных (кроме первого) деревьев исходного леса F. Стоит отметить, что для реализации указанного выше определения бинарного дерева леса возникла необходимость описать некоторые тривиальные процедуры для работы с лесом деревьев.
-
Описание программы.
Структуры данных
В данной работе БД реализованы ссылочным представлением в связанной памяти
Структура БД:
-
type
BinT = ^Node; {представление бинарного дерева}
Node = record {узел: }
Info: Elem; { содержимое}
LSub: BinT; { левое поддерево}
RSub: BinT { правое поддерево}
end {Node}
Спецификация процедур и функций
Имя |
Назначение |
procedure Otkaz (n: Byte); |
сообщения об ошибках |
function CreateBT: BinT; |
создание БД |
function NullBT (t: BinT): Boolean; |
проверка пусто ли ДБ |
function RootBT (t: BinT): Elem; |
значание корня БД |
function LeftBT (t: BinT): BinT; |
левое поддерево БД |
function RightBT (t: BinT): BinT; |
правое поддерево ДБ |
function ConsBT (e: Elem; LS, RS: BinT): BinT; |
конструктор дерева |
procedure DestroyBT (var b: BinT); |
удаление дерева |
procedure WriteBT (D : BinT); |
вывод дерева в скоб представлении на экран |
procedure WriteBT1 (D : BinT); |
вывод дерева в скоб представлении в файл |
function Ent : BinT; |
ввод дерева из файла |
procedure DisplayBT1 (b: BinT; n: integer); |
вывод перев изобр дерева на экран |
procedure DisplayBT2 (b: BinT; n: integer); |
вывод перев изобр дерева в файл |
* для реализации леса использована несколько инас структура данных. См. в приложениях.
Иерархия функций
Основное тело
программы
Процедура Go
Процедуры и функции работы с бинарными
деревьями
Процедура В
Процедуры DisplayBT и WriteBT
Процедуры и функции работы с деревьями
(не БД) и лесом
Внешняя спецификация функций
(модуль lab3_re)
Имя |
Назначение |
|
Function TEST(S : string): boolean; |
проверка правильности ввода дерева |
|
Function Go:BinT; |
функция, решающая поставленную задачу |
|
|
function B(F : forest):bint; |
Реализация построения БД леса |
Приложение.
Листинги исходных файлов.
LABA3_re.PAS
unit laba3_re;
INTERFACE
uses crt, derevo2, derevo;
Function TEST(S : string): boolean; {проверка правильности ввода дерева}
Function Go:BinT; {функция, решающая поставленную задачу}
IMPLEMENTATION
Function TEST(S : string): boolean;
const
koren = ['a' .. 'z', 'A' .. 'Z'];
var
znach, itog, temp : boolean;
i, len : integer;
str : string;
cur : char;
procedure scan;
begin
if (i <= len) then
begin
cur := s[i];
inc(i);
end else
begin
cur := '!';
exit;
end;
end; {scan}
function TestBT : boolean;
forward;
function forest:boolean;
var znach : boolean;
begin
znach := true;
if s[i] = '(' then
begin
znach := testbt;
if znach then
begin
znach := forest;
end;
end;
forest := znach;
end;
function TestBT : boolean;
var znach : boolean;
begin
scan;
if (cur = '(') then
begin
scan;
znach := cur in koren;
if znach then
begin
znach := forest;
end;
scan;
if (cur <> ')') then
begin
znach := false;
end;
end else znach := false;
TestBT := znach;
end; {TestBT}
Begin
temp := false;
len := Length(s);
i := 1;
itog := TestBT;
itog := itog and (i <> len);
TEST := itog;
End; {TEST}
{--------END--ANALIZATOR--------------}
Function Go:BinT;
var
i,j,k,schet,num : integer;
F, LST,ls : Forest;
o,tek : Tree;
temp:BiNT;
function B(F : forest):bint;
var
ls,f1 : forest;
begin
if NullF(F) then B := nil else
begin
Listin(Head(f),ls);
Tail(Head(f),f,f1);
B := consBT(roott(Head(F)),B(ls),B(f1));
end;
end;
begin
CreateForest(F);
schet := 1;
i := 1;
if eoln(t) then
begin
writeln('Файл пуст.');
writeln(tt,'Файл пуст.');
end else
BeGin
while not eof(t) do
begin
writeln(tt,'Считываю дерево номер ',schet,'...');
readln(t,st);
y1:=length(st);
for j :=1 to y1 do
begin
if (st[j]=' ') then
begin
delete(st,j,1);
j:=1;
end;
end;
y1:=length(st);
if TEST(st) then BEGIN
tek := EnterT(st);
begin
writeln(tt,'Дерево номер ',schet,' считано. Скобочная запись дерева:');
WriteT1(tek,tt);
writeln(tt);
F[i] := tek;
inc(i);
end;
END else
begin
writeln('Ошибка в записи дерева номер ',schet,'. Дерево не считано.');
writeln(tt,'Ошибка в записи дерева номер ',schet,'. Дерево не считано.');
end;
inc(schet);
end;
dec(i);
writeln(tt,'Обработка леса...');
writeln('Обработка леса...');
{Temp := B(F);
WriteT(F[1]);
writeln; }
{DisplayBT1(Temp,1);}
{DisplayT1(F[1],1,1);}
if (i <> 0) then
begin
writeln('Исходный лес:');
writeln(tt,'Исходный лес:');
end;
for j:=1 to i do
begin
writeln('Дерево ',j,':');
writeln(tt,'Дерево ',j,':');
DisplayT1(F[j],1,1);
DisplayT2(F[j],1,1,tt);
end;
writeln;
writeln(tt);
Temp := B(F);
Go := Temp;
if (temp = nil) then
begin
writeln(tt,'Получено бинарное дерево леса пусто.');
writeln('Получено бинарное дерево леса пусто.');
end else BEGIN
writeln(tt,'Получено бинарное дерево леса:');
writeln('Получено бинарное дерево леса:');
DisplayBT1(Temp,1);
DisplayBT2(Temp,1);
writeln(tt);
writeln;
writeln('Скобочное представление бинарного дерева леса:');
writeln(tt,'Скобочное представление бинарного дерева леса:');
WriteBT(Temp);
WriteBT1(Temp);
END;
EnD;
end;{Go}
End.
DEREVO.PAS
unit Derevo;
INTERFACE
uses crt;
const
NilBT = nil;
type
BinT = ^Node;
Elem = char; {представление бинарного дерева}
{тип Elem описан в GlobalBT}
Node = record {узел:}
Info: Elem; { содержимое}
LSub: BinT; { левое поддерево}
RSub: BinT { правое поддерево}
end {Node};
var
st: string;
i,y,lenght:integer;
t,tt:text;
procedure Otkaz (n: Byte); {сообщения об ошибках}
function CreateBT: BinT; {создание БД}
function NullBT (t: BinT): Boolean; {проверка пусто ли ДБ}
function RootBT (t: BinT): Elem; {значание корня БД}
function LeftBT (t: BinT): BinT; {левое поддерево БД}
function RightBT (t: BinT): BinT; {правое поддерево ДБ}
function ConsBT (e: Elem; LS, RS: BinT): BinT; {конструктор дерева}
procedure DestroyBT (var b: BinT); {удаление дерева}
procedure WriteBT (D : BinT); {вывод дерева в скоб представлении на экран}
procedure WriteBT1 (D : BinT); {вывод дерева в скоб представлении в файл}
function Ent : BinT; {ввод дерева из файла}
procedure DisplayBT1 (b: BinT; n: integer); {вывод перев изобр дерева на экран}
procedure DisplayBT2 (b: BinT; n: integer); {вывод перев изобр дерева в файл}
{ ---------------------------------------------------------------------------------}
IMPLEMENTATION
procedure Otkaz (n: Byte);
begin
Case n of
1: Write ('ОТКАЗ: RootBT (Null_Bin_Tree)!');
2: Write ('ОТКАЗ: LeftBT (Null_Bin_Tree)!');
3: Write ('ОТКАЗ: RightBT (Null_Bin_Tree)!');
4: Write ('ОТКАЗ: исчерпана память!')
else Write ('ОТКАЗ: ?')
end;
Halt
end {Otkaz};
function CreateBT: BinT;
begin
CreateBT := nil
end {CreateBT};
function NullBT (t: BinT): Boolean;
begin
NullBT := (t = nil)
end {NullBT};
function RootBT (t: BinT): Elem;
begin
if t <> nil then RootBT := t^.Info else Otkaz(1)
end {RootBT};
function LeftBT (t: BinT): BinT;
begin
if t <> nil then LeftBT := t^.LSub else Otkaz(2)
end {LeftBT};
function RightBT (t: BinT): BinT;
begin
if t <> nil then RightBT := t^.RSub else Otkaz(3)
end {RightBT};
function ConsBT (e: Elem; LS, RS: BinT): BinT;
var b: BinT;
begin
if MaxAvail >= SizeOf (Node) then
begin
New (b);
b^.Info:= e;
b^.LSub:= LS;
b^.RSub:= RS;
ConsBT:= b
end
else
Otkaz(4)
end {ConsBT};
procedure DestroyBT(var b: BinT);
begin
if b <> nil then
begin
DestroyBt (b^.LSub);
DestroyBt (b^.RSub);
Dispose (b)
end
end {DestroyBT};
procedure WriteBT (D : BinT);
begin
write('(');
write(rootBT(D));
if (LeftBT(D) = nil) then write('0') else WriteBT(LeftBT(D));
if (RightBT(D) = nil) then write('0') else WriteBT(RightBT(D));
write(')');
end;
procedure WriteBT1 (D : BinT);
begin
write(tt,'(');
write(tt,rootBT(D));
if (LeftBT(D) = nil) then write(tt,'0') else WriteBT1(LeftBT(D));
if (RightBT(D) = nil) then write(tt,'0') else WriteBT1(RightBT(D));
write(tt,')');
end;
function Ent : BinT;
var
c : char;
begin
c := st[lenght]; inc(lenght);
if (c = '(') then
begin
c := st[lenght]; inc(lenght);
end;
if (c <> '(') and (c <> ')') then if (c = '0') then Ent := nil else
begin
Ent := ConsBT(c,Ent,Ent);
c := st[lenght]; inc(lenght);
end;
end;
procedure DisplayBT1 (b: BinT; n: integer);
{вывод построчного и повернутого изображения бинарного дерева без возврата каретки}
{n уровень узла}
var i: integer;
begin
if NullBT (b) then {Writeln}
else
begin
Write (' ', RootBT (b));
if NullBT (RightBT (b))
then Writeln {вниз}
else DisplayBT1 (RightBT (b), n+1);
if not NullBT (LeftBT (b)) then
begin
for i := 1 to n do Write (' '); {вправо}
DisplayBT1 (LeftBT (b), n+1);
end;
end;
end; {DisplayBT1}
procedure DisplayBT2 (b: BinT; n: integer);
{вывод построчного и повернутого изображения бинарного дерева без возврата каретки}
{n уровень узла}
var i: integer;
begin
if NullBT (b) then {Writeln}
else
begin
Write (tt,' ', RootBT (b));
if NullBT (RightBT (b))
then Writeln(tt) {вниз}
else DisplayBT2 (RightBT (b), n+1);
if not NullBT (LeftBT (b)) then
begin
for i := 1 to n do Write (tt,' '); {вправо}
DisplayBT2 (LeftBT (b), n+1);
end;
end;
end; {DisplayBT2}
end.
Derevo2.PAS
unit Derevo2;
INTERFACE
uses crt;
const
ForLen = 50;
NilT = nil;
type
Tree = ^tNode;
Forest = array [1..ForLen] of Tree; {лес}
Elem = char; {представление бинарного дерева}
{тип Elem описан в GlobalT}
tNode = record {узел:}
Info: Elem; { содержимое}
Sub1: Tree;
Sub2: Tree;
Sub3: Tree;
Sub4: Tree;
Sub5: Tree;
end {Node};
var
st1: string;
i1,y1,lenght1:integer;
t,tt:text;
procedure Otkaz (n: Byte); {сообщения об ошибках}
function CreateT: Tree; {создание БД}
function NullT (t: Tree): Boolean; {проверка пусто ли ДБ}
function RootT (t: Tree): Elem; {значание корня БД}
function T1 (t: Tree): Tree;
function T2 (t: Tree): Tree;
function T3 (t: Tree): Tree;
function T4 (t: Tree): Tree;
function T5 (t: Tree): Tree;
function Cons_T (e: Elem; L1,L2,L3,L4,L5: Tree): Tree; {конструктор дерева}
procedure DestroyT (var b: Tree); {удаление дерева}
procedure WriteT (D : Tree); {вывод дерева в скоб представлении на экран}
procedure WriteT1 (D : Tree;var tt:text); {вывод дерева в скоб представлении в файл}
function EnterT(s:string) : Tree; {ввод дерева из файла}
procedure DisplayT1 (b: Tree; n,l: integer); {вывод перев изобр дерева на экран}
procedure DisplayT2 (b: Tree; n,l: integer;var tt:text); {вывод перев изобр дерева на экран}
procedure CreateForest(var F : forest); {создание леса}
procedure Listin(T : Tree; var F:forest); {возвращает лес поддеревьев дерева}
procedure Tail(T : Tree; var F,F1 : forest ); {возвразает лес дерева без головы}
function Head (F : forest):Tree; {возвращает головное дерево леса}
function NullF(F:forest):boolean; {проверка пуст ли лес}
{ ---------------------------------------------------------------------------------}
IMPLEMENTATION
procedure Otkaz (n: Byte);
begin
Case n of
1: Write ('ОТКАЗ: RootT (Null_Bin_Tree)!');
2: Write ('ОТКАЗ: LeftT (Null_Bin_Tree)!');
3: Write ('ОТКАЗ: RightT (Null_Bin_Tree)!');
4: Write ('ОТКАЗ: исчерпана память!')
else Write ('ОТКАЗ: ?')
end;
Halt
end {Otkaz};
function CreateT: Tree;
begin
CreateT := nil
end {CreateT};
function NullT (t: Tree): Boolean;
begin
NullT := (t = nil)
end {NullT};
function RootT (t: Tree): Elem;
begin
if t <> nil then RootT := t^.Info else Otkaz(1)
end {RootT};
function T1 (t: Tree): Tree;
begin
if t <> nil then T1 := t^.Sub1 else Otkaz(2)
end {T1};
function T2 (t: Tree): Tree;
begin
if t <> nil then T2 := t^.Sub2 else Otkaz(2)
end {T2};
function T3 (t: Tree): Tree;
begin
if t <> nil then T3 := t^.Sub3 else Otkaz(2)
end {T3};
function T4 (t: Tree): Tree;
begin
if t <> nil then T4 := t^.Sub4 else Otkaz(2)
end {T4};
function T5 (t: Tree): Tree;
begin
if t <> nil then T5 := t^.Sub5 else Otkaz(2)
end {T5};
function Cons_T (e: Elem; L1, L2, L3, L4, L5: Tree): Tree;
var b: Tree;
begin
if MaxAvail >= SizeOf (tNode) then
begin
New (b);
b^.Info:= e;
b^.Sub1:= L1;
b^.Sub2:= L2;
b^.Sub3:= L3;
b^.Sub4:= L4;
b^.Sub5:= L5;
Cons_T:= b
end
else
Otkaz(4)
end {Cons_T};
procedure DestroyT(var b: Tree);
begin
if b <> nil then
begin
DestroyT (b^.Sub1);
DestroyT (b^.Sub2);
DestroyT (b^.Sub3);
DestroyT (b^.Sub4);
DestroyT (b^.Sub5);
Dispose (b)
end
end {DestroyT};
procedure WriteT (D : Tree);
begin
write('(');
write(rootT(D));
if (T1(D) <> nil) then WriteT(T1(D));
if (T2(D) <> nil) then WriteT(T2(D));
if (T3(D) <> nil) then WriteT(T3(D));
if (T4(D) <> nil) then WriteT(T4(D));
if (T5(D) <> nil) then WriteT(T5(D));
write(')');
end;
procedure WriteT1 (D : Tree;var tt:text);
begin
write(tt,'(');
write(tt,rootT(D));
if (T1(D) <> nil) then WriteT1(T1(D),tt);
if (T2(D) <> nil) then WriteT1(T2(D),tt);
if (T3(D) <> nil) then WriteT1(T3(D),tt);
if (T4(D) <> nil) then WriteT1(T4(D),tt);
if (T5(D) <> nil) then WriteT1(T5(D),tt);
write(tt,')');
end;
function EnterT(s:string) : Tree;
var ll:integer;
rrr:tree;
function EntT : Tree;
var
c,temp : char;
begin
c := s[ll]; inc(ll);
{ write(c); readkey; }
if (c = '(') then
begin
c := s[ll]; inc(ll);
end;
{write(c); readkey;}
if (c = ')') then
begin
EntT := nil;
ll := ll -1
end else
begin
EntT := Cons_T(c,EntT,EntT,EntT,EntT,EntT);
c := s[ll]; inc(ll);
end;
end;
begin
ll:=1;
rrr:=entt;
entert := rrr;
end;
procedure DisplayT1 (b: Tree; n,l: integer);
{вывод построчного и повернутого изображения бинарного дерева без возврата каретки}
{n уровень узла}
var i,j,k,r: integer;
begin
k:=1;
r:=1;
for j:=1 to n do k:=k+1;
k:=k+l;
if NullT (b) then {Writeln}
else
begin
for i:=1 to k do write(' ');
Write ({' ',} RootT (b)); writeln;
DisplayT1(T1(b),n+1,k);
DisplayT1(T2(b),n+1,k);
DisplayT1(T3(b),n+1,k);
DisplayT1(T4(b),n+1,k);
DisplayT1(T5(b),n+1,k);
{writeln;}
end;
end; {DisplayBT1}
procedure DisplayT2 (b: Tree; n,l: integer;var tt:text);
{вывод построчного и повернутого изображения бинарного дерева без возврата каретки}
{n уровень узла}
var i,j,k,r: integer;
begin
k:=1;
r:=1;
for j:=1 to n do k:=k+1;
k:=k+l;
if NullT (b) then {Writeln}
else
begin
for i:=1 to k do write(tt,' ');
Write (tt,RootT(b)); writeln(tt);
DisplayT2(T1(b),n+1,k,tt);
DisplayT2(T2(b),n+1,k,tt);
DisplayT2(T3(b),n+1,k,tt);
DisplayT2(T4(b),n+1,k,tt);
DisplayT2(T5(b),n+1,k,tt);
{writeln;}
end;
end; {DisplayBT1}
procedure CreateForest(var F : forest);
var t : integer;
begin
for t := 1 to ForLen do F[t] := nil;
end;
procedure Listin(T : Tree; var F:forest);
begin
CreateForest(F);
F[2] := T2(T);
F[1] := T1(T);
F[3] := T3(T);
F[4] := T4(T);
F[5] := T5(T);
end; {Listing}
procedure Tail(T : Tree; var F,F1 : forest );
var n : integer;
begin
CreateForest(F1);
for n := 1 to ForLen do
begin
if (F[n] <> T) then F1[n] := F[n];
end;
end;
function Head (F : forest):Tree;
var
n : integer;
begin
n:=1;
while ( (nullT(F[n])) and (n <= ForLen)) do inc(n);
if (n=ForLen + 1) then Head := nil else Head := F[n];
end; {Tail}
function NullF(F:forest):boolean;
var n : integer;
begin
n:=1;
while ( (nullT(F[n])) and (n <= ForLen)) do inc(n);
if (n=ForLen + 1) then NullF := true else NullF := false;
end;
end.
LABA3_M.PAS
uses crt, derevo2, DEREVO, laba3_re;
Begin
clrscr;
assign(t,'der_in.txt'); reset(t);
assign(tt,'der_out.txt'); rewrite(tt);
go;
readkey;
close(t);
close(tt);
End.