Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
osnovy_programmirovanija_v_srede_lazarus.pdf
Скачиваний:
185
Добавлен:
18.03.2015
Размер:
6.53 Mб
Скачать

4.3 Динамические структуры данных

____________________________________________________________________

dispose_tree(ptr_tree); end;

end; 6: begin

writeln(UTF8ToConsole('Обход двоичного дерева слева:')); writeln;

obhod(root);

writeln;

end;

end; { end of case } until choose = 7

end.

4.3.7 Сортировка и поиск с помощью двоичного дерева

Двоичные деревья чаще всего применяются для сортировки и поиска.

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

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

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

сле построения двоичного дерева осуществляется его обход слева. Легко ви-

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

Такие двоичные деревья называются двоичными деревьями поиска или де-

ревья бинарного поиска (binary search tree), поскольку при поиске ис-

пользуется упорядоченность двоичного дерева. Поиск происходит следующим

388

Глава 4 Типовые алгоритмы обработки информации

____________________________________________________________________

образом. В качестве текущего узла принимаем корень. Затем сравниваем значе-

ние искомого элемента со значением текущего узла. Если они равны, то тре-

буемый элемент найден и алгоритм заканчивает свою работу. В противном слу-

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

чать, что искомого элемента в массиве нет.

Выше мы уже отмечали, что деревья обычно не вводятся, а формируются программно. Напишем процедуру формирования двоичного дерева по заданно-

му массиву целых чисел:

procedure insert_node(Elem: integer; var root: PTree); var

p: ^Tree; // текущий узел newTree: ^Tree; // новый узел

begin

p:= root; // начинаем с корня и проходим до нужного узла while (Elem > p^.node) and (p^.right <> nil) or (Elem < p^.node) and (p^.left <> nil) do

if Elem < p^.node then p:= p^.left

else

p:= p^.right;

New(newTree); {Создание нового узла} newTree^.left:= nil; newTree^.right:= nil; newTree^.node:= Elem;

{В зависимости от значения Elem новый

389

4.3 Динамические структуры данных

____________________________________________________________________

узел добавляется либо справа, либо слева}

if Elem > p^.node then

p^.right:= newTree

else

p^.left:= newTree;

end;

Процедуру поиска мы уже разрабатывали в последнем примере предыду-

щего раздела. На этот раз оформим поиск в виде функции:

function Search_Elem(Elem: integer;

var root: PTree): boolean;

var

p: PTree; begin

Search_Elem:= false;

if root = nil then exit; p:= root;

if p^.node = Elem then

Search_Elem:= true // элемент найден else

if Elem < p^.node then

Search_Elem:= Search_Elem(Elem, p^.left) else

Search_Elem:= Search_Elem(Elem, p^.right);

end;

Теперь давайте напишем программу сортировки массива целых чисел по возрастанию и поиска в дереве бинарного поиска нужного элемента. Все нуж-

390

Глава 4 Типовые алгоритмы обработки информации

____________________________________________________________________

ные процедуры у нас уже имеются.

program in_order; {$mode objfpc}{$H+}

uses

CRT, FileUtil;

type

vector = array

of integer;

PTree= ^Tree;

// Указатель на дерево

Tree= record

// Само дерево, имеет тип - запись

node: integer;

// значение вершины (узла) дерева

left: PTree; // Ссылка на левое поддерево right: PTree; // Ссылка на правое поддерево end;

var

i, n, choose: integer; Elem: integer;

sorted_array: vector; // сортируемый массив root: PTree;

{Процедура обхода двоичного дерева слева}

procedure obhod(p: PTree);

begin

if p <> nil then

begin

obhod(p^.left);

write(p^.node, ' ');

obhod(p^.right);

end;

end;

391

4.3 Динамические структуры данных

____________________________________________________________________

{Процедура поиска узла для вставки нового узла}

procedure insert_node(Elem: integer; var root: PTree); var

p: ^Tree; // текущий узел newTree: ^Tree; // новый узел

begin

p:= root; // начинаем с корня и проходим до нужного узла while (Elem > p^.node) and (p^.right <> nil) or (Elem < p^.node) and (p^.left <> nil) do

if Elem < p^.node then p:= p^.left

else

p:= p^.right;

{Создание нового узла}

New(newTree);

newTree^.left:= nil;

newTree^.right:= nil;

newTree^.node:= Elem;

{В зависимости от значения Elem новый узел добавляется либо справа, либо слева}

if Elem > p^.node then

p^.right:= newTree

else

p^.left:= newTree;

end;

{ ========= Сортировка двоичным деревом поиска ======== }

procedure Tree_Sort(var sorted_array: vector);

var

Elem: integer;

392

Глава 4 Типовые алгоритмы обработки информации

____________________________________________________________________

begin

Elem:= sorted_array[0]; New(root); root^.left:= nil; root^.right:= nil; root^.node:= Elem;

for i:= 1 to High(sorted_array) do begin

Elem:= sorted_array[i]; insert_node(Elem, root);

end;

obhod(root); // Обход полученного дерева слева end;

{Функция поиска в бинарном дереве} function Search_Elem(Elem: integer;

var root: PTree): boolean;

var

p: PTree; begin

Search_Elem:= false;

if root = nil then exit; p:= root;

if p^.node = Elem then

Search_Elem:= true // элемент найден else

if Elem < p^.node then

Search_Elem:= Search_Elem(Elem, p^.left) else

393

4.3 Динамические структуры данных

____________________________________________________________________

Search_Elem:= Search_Elem(Elem, p^.right);

end;

begin

writeln(UTF8ToConsole('Введите количество элементов массива'));

readln(n);

SetLength(sorted_array, n);

writeln(UTF8ToConsole('Введите элементы массива'));

for i:= 0 to n - 1 do

read(sorted_array[i]);

repeat

writeln(UTF8ToConsole('Выберите нужное действие:')); writeln(UTF8ToConsole('1-сортировка массива')); writeln(UTF8ToConsole('2-поиск элемента массива')); writeln(UTF8ToConsole('3-выход из программы'));

readln(choose);

case choose of

1: begin {Сортировка}

{Вызов процедуры сортировки массива бинарным деревом поиска}

Tree_Sort(sorted_array); writeln; end;

2: begin {поиск}

writeln(UTF8ToConsole('введите искомый элемент'));

readln(Elem);

if Search_Elem(Elem, root) then

writeln(UTF8ToConsole('Элемент найден'))

else

writeln(UTF8ToConsole('Элемент не найден'));

end;

394

Глава 4 Типовые алгоритмы обработки информации

____________________________________________________________________

end; { end of case }

until choose = 3;

end.

При работе с программой обратите внимание на то, что, прежде чем вызы-

вать функцию поиска, необходимо отсортировать массив, т.е. построить соот-

ветствующее двоичное дерево.

395

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]