
- •Теоретический раздел лекции Тема 1. Программирование с использованием рекурсии
- •1.1. Cтратегии решения задачи разбиением ее на подзадачи
- •1.2. Программирование рекуррентных соотношений
- •Var z:extended;
- •1.3. Условия окончания рекурсии
- •1.4. О целесообразности использования рекурсии
- •Var I,X,y,z:word;
- •1.5 Правила выбора программной реализации рекуррентных соотношений
- •Тема 2. Задачи перебора вариантов
- •2.1. Модель дерева решений
- •2.2. Задача оптимального выбора (задача о рюкзаке)
- •2.3. Метод полного перебора двоичного дерева
- •Var wt,ct:extended;
- •Var j,k:byte;
- •If k in s then begin
- •Var j:byte;
- •Var j:byte;
- •Var wt1,oct1:byte;
- •2.4. Метод ветвей и границ
- •Var n,I:byte;
- •Var wt1,oct1:Extended;
- •Include(s,I);
- •If I in Sopt then writeln(I,a[I].W,a[I].C);
- •2.5. Эвристические методы
- •Тема 3. Поиск и сортировка массивов записей
- •3.1. Применимость сортировки и поиска
- •3.2. Массив записей и поиск в нем
- •Var m:word;
- •3.3. Сортировки массивов
- •Var c: mas; I,j,k:word;
- •Var m:word;
- •Var I,j:Word;
- •Var I,j,l,r:Word; X:Tk; w:Tzp;
- •Тема 4. Связанные списки с использованием рекурсивных данных
- •4.1. Список, стек, очередь
- •4.2. Списки на основе динамических массивов
- •Inherited create;
- •Var turn:Tlist; с1,c2:Tinf;
- •4.3. Рекурсивные данные и однонаправленные списки
- •Inherited create;
- •Var stec,st1,turn,tr1:Tlist; inf:Tinf;
- •4.4. Начальное формирование, добавление и удаление элементов однонаправленного списка
- •4.5. Разновидности связанных списков
- •Inf:Tinf;
- •Тема 5. Поиск и сортировки на связанных линейных списках
- •5.1. Поиск в однонаправленных списках
- •5.2. Сортировка однонаправленных списков
- •1 3Var Inf:tInf;
- •Тема 6. Использование линейных связанных списков
- •6.1. Вычисления арифметических выражений
- •Var ch,ch1,ch2,chr:char;
- •I:byte;ch,ch1:char;
- •6.2. Сложение больших целых чисел
- •Var u,V,s,t:byte;
- •6.3. Работа с разреженными матрицами
- •Inf:Tinf;
- •Inf:tInf;
- •Var proot,p:Ptree;
- •Var bl:boolean;
- •7.2. Бинарное дерево поиска
- •7.3. Основные операции с бинарным деревом поиска
- •Inf:tInf;
- •Var d1:Tree; c:Tinf; k:Tkey;
- •Var bl:Boolean;
- •Var m:Word;
- •Var p:Ttree; m:Word;
- •Тема 8. Хеширование
- •8.1. Что такое хеширование
- •8.2. Схема хеширования
- •Interface
- •Inf:Tinf;
- •8.4. Другие способы хеширования
- •Практический раздел Указания по выбору варианта
- •Индивидуальные практические работы и контрольные работы
- •Индивидуальная практическая работа №1. Программирование с использованием рекурсии
- •1.1. Понятие рекурсии
- •1.2. Порядок выполнения работы
- •1.2.1. Пример решения задачи
- •Индивидуальная практическая работа №2. Организация однонаправленного списка на основе рекурсивных типов данных в виде стека
- •2.1. Основные понятия и определения
- •Inf:tInf; // информация
- •Контрольная работа №1. Программирование с использованием деревьев на основе рекурсивных типов данных
- •1.1. Понятие древовидной структуры
- •Inf:tInf;
- •1.2. Компонент tTreeView
- •1.3. Бинарное дерево поиска
- •Основные операции с двоичным деревом поиска
- •1.4. Порядок написания программы
- •Inf:tInf;
- •Inherited Free;
- •Var tr:Ttree;
- •1.5. Индивидуальные задания
- •Курсовая работа
- •Литература
7.3. Основные операции с бинарным деревом поиска
При использовании организации списков в виде двоичного дерева целесообразно создать класс (Листинг 7.5), реализующий следующие методы:
обход дерева;
вставка информации с новым значением ключа не изменяя свойств дерева поиска;
формирование сбалансированного дерева поиска;
поиск заданного ключа;
поиск минимального (максимального) ключа;
удаление информации с заданным ключом;
удаление дерева.
Type Ttree=^Tre Листинг 7.5
Tre=Record
Inf:tInf;
A1,A2:Ptree;
End;
Tree=Class(tobject)
proot,p,q,v,w:Ttree;//указатель на корень и рабочие
Destructor Free;
Procedure Tree.Add(Inf:TInf);
Procedure Wrt1;
Function poisk(k:Tkey):TInf;
Function Mink:TInf;
Procedure Delk(k:Tkey);
. . . . . . . . . . . .
End;
Destructor Tree.Free;// удаляет все элементы
Procedure Del(var p:Ttree);
begin
If (p<>Nil) then begin
Del(p^.A1);
Del(p^.A2);
Dispose(p);
p:=Nil;
end;
end;
begin Del(proot); inherited free; end;
Работа с деревом начинается с его создания и заканчивается освобождением памяти, например:
Var d1:Tree; c:Tinf; k:Tkey;
. . . . . . .
D1:=Tree.create; //используется конструктор из Tobject
//Здесь находятся процедуры работы с деревом:
D1.Add(c);
D1.poisk(k);
. . . . . .
D1.Free;
Обход бинарного дерева в симметричном порядке:
Листинг 7.6
Procedure Tree.Wrt1;
Procedure Wr(p:Ttree); //рекурсивный обход
begin
if p<>nil then
begin
Wr(p^.A1);
Print(p^.Inf);//печать или запись в файл ставится здесь
Wr(p^.A2);
end;
end;
begin p:=proot; wr(p) end;
При обходе бинарного дерва поиска этим методом будет напечатана информация в порядке возрастания ключа. Если в этом методе поменять местами А1иА2и назвать ееWrt2, то информация будет напечатана в порядке убывания ключа.
Нахождение элемента с заданным ключом k в двоичном дереве поиска:
Листинг 7.7
Function Tree.poisk(k:Tkey):TInf;
begin p:=Proot;
While(p<>nil) and (p^.Inf.key<>k) do
If k<p^.Inf.key then p:=p^.A1
else p:=p^.A2;
if p<>Nil then Result:=p^.Inf
else Print(’Поиск без результата’);
end;
Эффективность этого поиска O(lg2n)
Поиск информации с минимальным (максимальным) ключом:
Листинг 7.8
Function Tree.Mink:TInf;
begin p:=proot;
While p^.A1<>Nil do p:=p^.A1;
Result:=p^.Inf;
end;
При поиске максимального ключа нужно спуститься по правой ветке (Maxk: p^.A2<>Nil, p:=p^.A2) до самого правого листа.
Вставить новый элемент с ключом key не совпадающим ни с одним из ключей, не нарушая свойства дерева поиска.
Вначале напишем алгоритм создания нового листа дерева по адресу в указателе w. Затем напишем алгоритм поиска места добавления нового листа метод добавления нового листа с ключом, находящимся в поле Inf.key помещаемой информации Inf в дерево поиска сохраняя его свойства:
Листинг 7.9
Procedure Tree.Add(Inf:TInf);
Var bl:Boolean;
begin
New(w); // создание нового листа:
P^.Inf:=Inf;
P^.A1:=Nil; P^.A2:=Nil;
if proot=Nil then proot:=w
else begin // поиск места добавления листа:
p:=proot;
repeat
q:=p; //здесь q – указатель на предыдущий элемент
bl:=Inf.key<p^.Inf.key;
if bl then p:=p^.A1
else p:=p^.A2;
until p=Nil; // добавление листа
if bl then q^.A1:=w else q^.A2:=w;
end;
end;
Построение дерева поиска
Пусть имеется некоторый массив a:Tms из n значений данных с разными ключами (Tms=array[1..nr] of Tinf). Построение дерева поиска можно осуществить с помощью вышеописанных методов следующим образом:
Листинг 7.10
Procedure Tree.Make(a:Tms;n:word);
begin
For i:=1 to n do Add(a[i]);
end;
При случайном чередовании ключей в массиве а метод MakeB обычно формирует дерево неплохо сбалансированное. Однако, если ключи в исходном массиве а частично упорядочены, то получаемое таким образом дерево поиска оказывается сильно разбалансированным и его эффективность для организации поиска оказывается сравнимой с линейным поиском в массиве.
Этот способ построения дерева поиска можно использовать для печати в порядке возрастания элементов массива (например расположенного в файле). Для этого достаточно построить дерево с помощью метода MakeB и затем распечатать его методом Wrt1B.
Построение идеально сбалансированного дерева поиска для заданного отсортированного в порядке возрастания ключа массива данных a:Tms можно осуществить с помощью следующей рекурсивной процедуры (2 варианта):
Листинг 7.11
Procedure Tree.BLns(a:Tms;n:word);
Procedure BL(i,j:Word);