Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2_SAOD_-_Dinamicheskie_struktury_dannykh.doc
Скачиваний:
124
Добавлен:
21.03.2016
Размер:
1.66 Mб
Скачать
  1. Реализация операций над деревом поиска

Поиск элемента с ключом Keyможет быть выполнен с помощью итерации, так как поиск идет по единственному пути от корня к искомому узлу:

function tSearchTree.Addr(Key: tValue): pItem; // адрес элемента с ключом Key

var

Item: pItem;

begin

if Empty

then Addr:= nil

else begin

Item:= fRoot;

while (Item<>nil) and (Item^.Value<>Key) do

ifKey<Item^.Value

then Item:= Item^.Left // спуск по левой ветви

elseItem:=Item^.Right;// спуск по правой ветви

Addr:= Item;

end;

end; // function tSearchTree.Addr

Метод, реализующий поиск по дереву с включением:

functiontSearchTree.Search(Key: tValue):pItem;

// Поиск элемента с заданным ключом Key с включением

procedure IncKey(var Item: pItem); // рекурсивная процедура поиска

begin

ifItem=nil

thenbegin // элемента с ключом Key нет: включение его в качестве листа

Item:= New(pItem); Item^.Value := Key;

Item^.Left:= nil; Item^.Right:=nil;

Result:= Item; Inc(fSize);

end

else

if Key<Item^.Value then IncKey(Item^.Left) // поиск слева

else

if Key>Item^.Value then IncKey(Item^.Right) // поиск справа

else Result:= Item; // элемент найден

end; // procedure IncKey

begin

IncKey(fRoot);

end; // function tSearchTree.Search

При реализации процедуры поиска с исключениемнеобходимо рассмотреть три ситуации и три способа поведения процедуры после исключения элемента:

ситуация 1:элемента с ключомKeyнет в дереве, в этом случае дерево остается неизменным;

ситуация 2:элемент с ключомKeyимеет не более одного потомка – после исключения ближайший потомок поднимается на его место;

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

Ниже приведено исходное дерево поиска (а). Дерево) получается из дерева(а)после исключения элемента 15 и замены его элементом 11 – самым правым элементом левого поддерева узла 15 (в процедуре обхода слева направо он предшествует узлу 15). Дерево(в)получается из дерева (а) после исключения элемента 15 и замены его элементом 18 – самым левым элементом правого поддерева узла 15 (в процедуре обхода следует за узлом 15).

(а) (б) (в)

proceduretSearchTree.Delete(Key: tValue);

// Поиск элемента с заданным ключом Key с исключением

procedureDelKey(varItem: pItem);// основная рекурсивная процедура

var

DelItem: pItem; // указатель на исключаемый элемент

procedure Del(var Addr: pItem);

// Вспомогательная рекурсивная процедура. Возвращает адрес самого

// правого элемента левого поддерева удаляемого узла DelItem

begin

if Addr^.Right<>nil

then Del(Addr^.Right) // поиск правого элемента

elsebegin

// Найден самый правый элемент левого поддерева DelItem

DelItem^.Value:= Addr^.Value; DelItem:= Addr; Addr:= Addr^.Left;

end;

end; //procedure Del

begin

if Item=nil

then WriteLn('Узел с ключом',Key,'не найден.') // ситуация 1

else

if Key<Item^.Value

then DelKey(Item^.Left) // поиск слева

else

if Key>Item^.Value

then DelKey(Item^.Right) // поиск справа

elsebegin

// элемент найден, исключение Item^

DelItem:= Item;

if DelItem^.Right=nil

then Item:= DelItem^.Left // ситуация 2

else

if DelItem^.Left=nil

then Item:= DelItem^.Right // ситуация 2

elseDel(DelItem^.Left);// ситуация 3 – поиск предшественника

Dispose(DelItem);Dec(fSize);// удаление перемещенного элемента

end; // конец исключения Item^

end; // procedure DelKey

begin

DelKey(fRoot);

end; // procedure tSearchTree.Delete

В методе tSearchTree.Deleteиспользуется основная рекурсивная процедураDelKey, которая собственно и выполняет поиск в дереве с удалением. Вспомогательная рекурсивная процедураDelначинает работать только в ситуации 3. Она «спускается» вдоль правой ветви левого поддерева элемента с указателемDelItem, который нужно исключить, и заменяет полеValueэлементаDelItem^на соответствующее значение из самого правого элементаAddr^левого поддерева, после чего от элементаAddr^можно освободиться.

Построение дерева поисказаключается в считывании из входного потока (в данной реализации из текстового файла) элементов с заданными ключами и включении их в дерево поиска с использованием операции поиска по дереву с включениемSearch(Key).

procedure tSearchTree.Build(var f: Text); // построение дерева поиска

var

Key : tValue;

begin

while not Eof(f) do begin

Read(f, Key); if Eoln(f) then ReadLn(f);

Search(Key);// функция Search вызывается как процедура

end;

end; //procedure tSearchTree.Build

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