then

begin

SetColor(n+1);

Line(x1,y1+10,x1-(arr[n] div 2),y1+((arr1[n]-20) div 2)+10);

SetColor(n+2);

Line(x1-(arr[n] div 2),y1+((arr1[n]-20) div 2)+10,x1-arr[n],y1+arr1[n]-10);

Strel(x1-arr[n],y1+arr1[n]-10,(arr1[n]-20)/arr[n]);

Wiv(y^.next[1],n+1,x1-arr[n],y1+arr1[n]);

end;

if y^.next[2] <> nil

then

begin

SetColor(n+1);

Line(x1,y1+10,x1+arr[n],y1+arr1[n]-10);

SetColor(n+2);

Line(x1+(arr[n] div 2),y1+((arr1[n]-20) div 2)+10,x1+arr[n],y1+arr1[n]-10);

Strel(x1+arr[n],y1+arr1[n]-10,-(arr1[n]-20)/arr[n]);

Wiv(y^.next[2],n+1,x1+arr[n],y1+arr1[n]);

end;

end;

end;

Begin

ClrScr;

Randomize;

Repeat

new(x);

a:=6;

x^.next[1]:=Nil;

x^.next[2]:=Nil;

Zap(x,0);

Max:=x;

Min:=x;

writeln;

grDriver := Detect;

InitGraph(grDriver, grMode,'c:\tp7\bgi\');

SetFillStyle(solidfill,15);

SetColor(15);

Wiv(x,1,320,50);

Delay(5000);

until KeyPressed;

End.

Задание. Поэкспериментируйте над предложенной программой, внося свои изменения. Результат покажите учителю.

Занятие 2. Представление деревьев. Основные операции над деревом.

Дерево – это сложная динамическая структура данных, применяющаяся для эффективного хранения информации.

Очевидно, что для описания требуются ссылки. Опишем, как переменные с фиксированной структурой – сами вершины, тогда степень дерева будет определять число ссылочных компонент, указывающих на вершины поддеревьев. В бинарном дереве их два: левое и правое.

Type

TreeLink = ^Tree;

Tree = Record

Data : <тип данных>;

Left, Right : TreeLink;

НЕ нашли? Не то? Что вы ищете?

End;

Корень дерева опишем в разделе описания переменных:

Var

kd : TreeLink;

К основным операциям над деревьями относятся:

• занесение элемента в дерево;

• обход дерева;

• удаление элемента из дерева.

Рассмотрим вставку и обход дерева на примере следующей задачи.

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

Опишем процедуру вставки в дерево новой вершины. При вставке в дерево вершина вставляется либо как поддерево уже существующей вершины или как единственная вершина дерева. Поэтому и левая и правая связи новой вершины должны быть Nil. Когда дерево пусто, значение передаваемое в виде параметра ссылки равно Nil. В этом случае нужно изменить ее так, чтобы она указывала на новую вершину, которая была вставлена как корневая. При вставке второго элемента переданный из основной программы параметр t уже не будет равен Nil, и надо принимать решение о том, в какое поддерево необходимо вставить новую вершину.

Procedure InsTree(n : integer; Var t : TreeLink);

Begin

if t=nil

then

begin

new(t);

with t^ do

begin

Left := nil;

Right := nil;

Data := n;

end;

end;

else

if n<=t^.data

then

InsTree(n, t^.Left)

else

InsTree(n, t^.Right)

End;

Опишем процедуру вывода значений элементов двоичного дерева на экран. Для этого необходимо выполнить полный обход дерева. При обходе дерева его отдельные вершины посещаются в отдельном порядке. Вывод двоичного дерева можно производить рекурсивно, выполняя для каждой вершины три действия:

• вывод числа, хранящегося в узле;

• обход левого поддерева;

• обход правого поддерева.

Порядок выполнения этих действий определяет способ обхода дерева. Способы вывода:

• прямой вывод (сверху вниз);

• обратный вывод (слева направо);

• концевой вывод (снизу вверх).

Процедура обратного вывода дерева имеет следующий вид:

Procedure PrintTree(t : TreeLink);

Begin

if t<>Nil

then

begin

PrintTree(t^.Left);

Write(t^.Data:3);

PrintTree(t^.Right);

end;

End;

Задание. Написать процедуры прямого и концевого вывода значений элементов дерева.

Основная программа осуществляет ввод чисел с клавиатуры. Используются: переменная nd типа TreeLink – значение указателя на корень дерева; переменная Digit типа integer для хранения очередного введенного числа.

Begin

writeln('Вводите вершины дерева. Окончание ввода – 0');

kd := nil;

read(Digit);

while Digit <> 0 do

begin

InsTree(Digit, kd);

writeln(' Введите очередное число ');

read(Digit);

end;

PrintTree(kd);

End.

Задание. Напишите программу создания и вывода на экран двоичного дерева, используя свою процедуру вывода. Протестируйте программу и представьте учителю файл и листинг для оценки.

Занятие 3. Самостоятельное решение задач.

Выберите с учителем одну из предложенных задач.

1. Создайте программой числовое двоичное дерево. Опишите рекурсивную логическую функцию, проверяющую наличие заданного числа в сформированном дереве. В программе используйте подпрограммы.

2. Создайте программой числовое двоичное дерево. Опишите рекурсивную числовую функцию, подсчитывающую сумму элементов дерева. В программе используйте подпрограммы.

3. Создайте программой числовое двоичное дерево. Опишите функцию, которая находит наибольший элемент непустого дерева. В программе используйте подпрограммы.

4. Напишите программу, содержащую процедуру, которая каждый отрицательный элемент дерева заменяет на положительный, а положительный превращает в ноль.

5. Напишите программу, содержащую процедуру, которая каждый элемент дерева возводит в квадрат.

6. Создайте программой символьное двоичное дерево. Опишите функцию, возвращающую строку, сформированную на базе этих символов. В программе используйте подпрограммы.

7. Создайте программой символьное двоичное дерево. Опишите логическую функцию, проверяющую, есть ли в непустом дереве хотя бы два одинаковых символа. В программе используйте подпрограммы.

8. Создайте строковое двоичное дерево. Опишите функцию, возвращающую строку, сформированную на базе символов, встречающихся в каждой строке дерева. В программе используйте подпрограммы.

9. Создайте двоичное дерево записей. Проверьте выбранное поле записей на равенство. В программе используйте подпрограммы.

10. Создайте программой два числовых двоичных дерева. Опишите рекурсивно и нерекурсивно логическую функцию, входными параметрами которой являются два дерева, проверяющую на равенство эти деревья. В программе используйте подпрограммы.

Занятие 4. Идеально сбалансированное дерево.

В дереве поиска можно найти место каждого элемента, двигаясь от корня и переходя на левое или правое поддерево в зависимости от значений встречающихся данных.

Использование деревьев поиска значительно сокращает время решения задачи.

Правильно организованным деревом считается идеально сбалансированное дерево, то есть для каждой его вершины количество вершин в левом и правом поддереве различаются не более чем на 1.

Сформируем идеально сбалансированное дерево, элементами которого являются N чисел, вводимых с клавиатуры.

Поскольку требуется построить идеально сбалансированное дерево, то его узлы в процессе построения должны распределяться равномерно. Сформируем правило равномерного распределения узлов при известном их числе:

• Взять один узел в качестве корня.

• Построить левое поддерево с числом узлов n1=N div 2 тем же способом.

• Построить правое поддерево с числом узлов n2=N-n1-1 тем же способом.

Program BalansTree;

Uses

Crt;

Type

Pt = ^Node;

Node = record

Data : integer;

Left, Right : Pt;

end;

Var

n : integer;

kd : Pt;

f : text;

Function Tree(n : integer) : Pt;

Var

NewNode : Pt;

x, n1, n2 : integer;

Begin

if n=0

then

Tree := Nil

else

begin

n1 := n Div 2;

n2 := n–n1–1;

read(f, x);

new(NewNode);

with NewNode^ do

begin

Data := x;

Left := Tree(n1);

Right := Tree(n1);

end;

Tree := NewNode;

end;

End;

Procedure PrintTree(t : Pt; h : integer);

Var

i : integer;

Begin

if t<>nil

then

with t^ do

begin

PrintTree(Left, h+1);

for i := 1 to h do

write(' ');

writeln(Data:6);

PrintTree(Right, h+1);

end;

End;

Begin

ClrScr;

assign(f, 'c:\f. pas');

reset(f);

write('n=');

readln(n);

kd := Tree(n);

PrintTree(kd, 0);

readln;

End.

Задание. Наберите программу, протестируйте ее, вставьте комментарий, приготовьтесь объяснить учителю принцип построения идеально сбалансированного дерева.

Поиск и включение элемента в дерево.

Задача. Задана последовательность слов. Определить частоту вхождения каждого из слов в последовательности.

Для решения задачи любое слово ищется в дереве, которое на начальном этапе пусто. Если слово найдено, то счетчик его вхождений увеличивается на 1, если нет, то слово включается в дерево с единичным значением счетчика.

Program Poisk;

Uses

Crt;

Type

Words = ^WordTree;

WordTree = record

Data : string;

k : integer;

Left, Right : Words;

end;

Var

n : integer;

kd : Words;

x : string;

f : text;

Procedure Tree(x : string; Var p : Words);

Begin

if p=nil

then

begin

new(p);

with p^ do

begin

k := 1;

Data := x;

Left := Nil;

Right := Nil;

end;

end;

else

if x>p^.Data

then

Tree(x. p^.Left)

else

if x<p^.Data

then

Tree(x. p^.Right)

else

Inc(p^.k);

End;

Procedure PrintTree(t : Words; h : integer);

Var

i : integer;

Begin

if t <> Nil

then

with t^ do

begin

PrintTree(Left, h+1);

for i := 1 to h do

write(' ');

writeln(Data, ',(', k, ')');

PrintTree(Right, h+1);

end;

End;

Begin

ClrScr;

assign(f, 'c:\f. dan');

reset(f);

write('n=');

readln(n);

kd := Nil;

while n>0 do

begin

readln(f, x);

Tree(x, kd);

Dec(n);

end;

close(f);

PrintTree(kd, 0);

readln;

End.

Эта задача называется задачей поиска по дереву с включением.

Задание. Наберите программу, протестируйте ее, вставьте комментарий, приготовьтесь объяснить учителю принцип поиска по дереву с включением. По желанию можете усложнить текст задачи, усовершенствовать ее решение или внести еще какие-либо изменения.

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70