
- •Теоретический раздел лекции Тема 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. Индивидуальные задания
- •Курсовая работа
- •Литература
Inf:tInf;
A1:Ttree; //A1..Am – указатели на адреса,
A2:Ttree; //по которым расположены сестры
... //если сестра отсутствует, то
Am:Ttree; //соответствующий адрес равен Nil
end;
Размещение данных, в виде древовидной структуры представленной на рисунке 7.1 можно осуществить, например, следующим образом:
Листинг 7.1
Var proot, p:Ttree;//Указатели: на корень и текущий узел
...
New(proot); p:=Proot; p^.Inf:=’a’; p^.A2:=Nil;
New(P^.A3); p:=P^.A3; P^.Inf:=’c’; P^.A1:=Nil;
P^.A2:=Nil; New(P^.A3); p:=P^.A3; p^.Inf:=’g’;
P^.A1:=Nil; p^.A2:=Nil; p^.A3:=Nil; p=Proot; New(P^.A1);
p:=p^.A1; p^.Inf:=’b’; New(P^.A1); P^.A1.Inf:=’d’;
P^.A1^.A1:=Nil; p^.A1^.A2:=Nil; p^.A1^.A3:=Nil;
New(P^.A2); p^.A2.Inf:=’e’; P^.A2^.A1:=Nil;
P^.A2^.A2:=Nil; p^.A2^.A3:=Nil; New(p^.A3); p:=P^.A3;
p^.Inf:=’f’; p^.A2:=Nil; New(p^.A1); p^.A1.Inf:=’k’;
P^.A1^.A1:=Nil; p^.A1^.A2:=Nil; p^.A1^.A3:=Nil;
New(p^.A3); p^.A3.Inf:=’l’; P^.A3^.A1:=Nil;
P^.A3^.A2:=Nil; P^.A3^.A3:=Nil
После того как дерево заполнено информацией, его нужно уметь просмотреть, распечатать, осуществить поиск. Как видно из вышеприведенного фрагмента программы, непосредственное заполнение даже небольшого дерева требует довольно громоздкой последовательности команд. Поэтому для работы с деревьями используют набор специфических алгоритмов.
Обходом дерева называется последовательное обращение ко всем его узлам. Следующая рекурсивная процедура осуществляет такой обход с распечаткой каждого узла:
Листинг 7.2
Procedure Wrttree(var p:Ttree); //p - указатель на текущий узел
begin
if p<>Nil then begin//если дочь отсутствует то выход
<Print(p^.Inf);> //при прямом обходе печать ставить здесь
Wrttree(p^.A1);
Wrttree(p^.A2);
...
Wrttree(p^.Am);
<print(p^.Inf);> //при обратном обходе печать ставить здесь
end;
end;
...При вызове этой процедуры:
p:=proot; Wrttree(p);
Данные, изображенные на рисунке будут распечатаны в следующем порядке:
Прямой обход (печать стоит в начале):
a, b, d, e, f, k, l, c, g.
Обратный обход (печать стоит в конце):
d, e, k, l, f, b, g, c, a.
Нахождение информации по заданному ключу k, который находится
Листинг 7.3
в поле Inf.key:
Var proot,p:Ptree;
Function Poisktree(k):Tinf
Var bl:boolean;
Procedure Po(var p:Ttree);//рекурсивный
Begin
If (p<>Nil) or bl then
If p^.key<>k then
begin
Po(p.A1);
Po(p.A2);
...
Po(p.Am);
end
else bl:=false;
end;//Po
begin
p:=proot; bl:=true; Po(p);
If bl then Print(’поиск неудачен’)
else Result:=p^.Inf;
End;//Poisk
Обращение: Inf:=Poisktree(k);
Удаление дерева из памяти:
Листинг 7.4
Procedure DeleteTree(var p:Ttree);
Begin
If (p<>Nil) then begin
DeleteTree(p^.A1);
DeleteTree(p^.A2);
DeleteTree(p^.Am);
Dispose(p);
p:=Nil;
end;
end;
Обращение: DeleteTree(proot);
7.2. Бинарное дерево поиска
Наиболее часто для реализации списков используется бинарное дерево поиска. Предположим, что у нас есть набор данных, упорядоченных по ключу:
key: 1, 6, 8, 10, 20, 21, 25, 30.
Организуем
древовидную структуру следующим образом
(N=Nil).
Рис. 7.2.
В дереве на рис. 7.2 ключи расположены таким образом, что для любого узла значения ключа у левого преемника меньше чем у правого. Таким образом организованное дерево получило название двоичное дерево поиска. Ввиду его своеобразной организации эффективность поиска информации в такой динамической структуре данных сравнима с эффективностью двоичного поиска в массиве, т.е. имеет оценку эффективности О(log2n). Заметим что двоичный поиск в линейном связанном списке организовать невозможно, а эффективность линейного поиска имеет порядок О(n/2). Конечно, оценка О(log2n) справедлива для сбалансированного дерева, т.е. такого у которого узлы, имеющие только одну дочь, располагаются не выше двух последних уровней.