- •Тема 1. Стеки, очереди, деки 7
- •Тема 2. Односвязные и двусвязные линейные списки 21
- •Тема 3. Бинарные деревья 40
- •Тема 4. Графы 65
- •Введение
- •Терминология
- •Классификация структур данных по различным признакам
- •Типовые операции над структурами данных
- •Эффективность алгоритмов. O-обозначения
- •Тема 1. Стеки, очереди, деки
- •Операции над стеком
- •Реализация стека
- •Реализация основных операций над стеком
- •Использование стека для преобразования форм записи выражений.
- •Очередь
- •Операции над очередью
- •Операции над деком
- •Реализация очереди и дека
- •Реализация основных операций над очередью и деком
- •Итератор
- •Лабораторная работа 1. Стеки, очереди, деки
- •Тема 2. Односвязные и двусвязные линейные списки
- •Линейный список
- •Операции над линейным списком
- •Реализация линейного списка в виде односвязной динамической структуры
- •Реализация основных операций над односвязным списком
- •Циклический список
- •Операции над циклическим списком
- •Односвязная реализация циклического списка
- •Реализация основных операций над односвязным циклическим списком
- •Реализация линейного списка в виде двусвязной динамической структуры
- •Реализация основных операций над двусвязным списком
- •Циклический двусвязный список
- •Реализация основных операций над двусвязным циклическим списком
- •Лабораторная работа 2. Односвязные и двусвязные линейные списки
- •Тема 3. Бинарные деревья
- •Основные понятия и определения
- •Построение бинарного дерева
- •Операции над бинарным деревом
- •Реализация бинарного дерева
- •Реализация основных операций над бинарным деревом
- •Дерево выражения
- •Дерево поиска
- •Операции над деревом поиска
- •Реализация дерева поиска
- •Реализация операций над деревом поиска
- •Сбалансированные деревья
- •Включение в сбалансированное дерево
- •Лабораторная работа 3. Бинарные деревья
- •Тема 4. Графы
- •Основные понятия и определения
- •Граф g7
- •Операции над графом
- •Реализация графа
- •Реализация основных операций над ориентированным графом
- •Обход ориентированного графа
- •Вычисление расстояния между узлами ориентированного графа
- •Лабораторная работа 4. Ориентированные графы
- •Библиографический список
-
Реализация операций над деревом поиска
Поиск элемента с ключом 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
if Key<Item^.Value
then Item:= Item^.Left // спуск по левой ветви
else Item:= Item^.Right; // спуск по правой ветви
Addr:= Item;
end;
end; // function tSearchTree.Addr
Метод, реализующий поиск по дереву с включением:
function tSearchTree.Search(Key: tValue):pItem;
// Поиск элемента с заданным ключом Key с включением
procedure IncKey(var Item: pItem); // рекурсивная процедура поиска
begin
if Item=nil
then begin // элемента с ключом 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).
(а) (б) (в)
procedure tSearchTree.Delete(Key: tValue);
// Поиск элемента с заданным ключом Key с исключением
procedure DelKey(var Item: pItem); // основная рекурсивная процедура
var
DelItem: pItem; // указатель на исключаемый элемент
procedure Del(var Addr: pItem);
// Вспомогательная рекурсивная процедура. Возвращает адрес самого
// правого элемента левого поддерева удаляемого узла DelItem
begin
if Addr^.Right<>nil
then Del(Addr^.Right) // поиск правого элемента
else begin
// Найден самый правый элемент левого поддерева 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) // поиск справа
else begin
// элемент найден, исключение Item^
DelItem:= Item;
if DelItem^.Right=nil
then Item:= DelItem^.Left // ситуация 2
else
if DelItem^.Left=nil
then Item:= DelItem^.Right // ситуация 2
else Del(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