
- •Теоретический раздел лекции Тема 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. Индивидуальные задания
- •Курсовая работа
- •Литература
Var m:Word;
begin
if i<=j then
begin
m:=i+j div 2;
Add(a[m]);
BL(i,m);
BL(m+1,j);
end;
end;
begin
proot:=Nil; BL(1,n);
end;
Procedure Tree.BLns(a:Tms;n:word);
Function BL(i,j:Word):Ttree;
Var p:Ttree; m:Word;
begin
if i>j then p:=Nil
else begin
m:=i+j div 2;
New(p); p^.inf:=a[m];
p^.A1:=BL(i,m);
p^.A2:=BL(m+1,j);
end;
result:=p;
end;
begin
proot:=BL(1,n);
end;
С помощью метода BLns можно легко построить идеально сбалансированное дерево для любого списка данных, предварительно отсортировав список с помощью методов Make и Wrt1.
Удаление узла с заданным ключом из дерева поиска, сохраняя его свойства. При решении этой задачи метод DelkB отрабатывает три различных ситуации:
Удаление листа с ключом key:
Удаление узла имеющего одну дочь:
3) Удаление узла, имеющего двух дочерей значительно сложнее. Если p – исключаемый узел, то его следует заменить узлом w, который содержит наибольший ключ в левом поддереве p (либо наименьший ключ в правом поддереве). Такой узел w является либо листом, либо самым правым узлом поддерева p у которого имеется только левая дочь.
w
v
p key=7
Procedure Tree.Delk(k:Tkey);
begin
p:=proot;
While (p<>Nil) and (p^.Inf.key<>k) do
begin
q:=p;
if p^.Inf.key>k then p:=p^.A1
else p:=p^.A2;
end;
if p<>Nil then //исключение найденного узла p:
begin
if p=proot then begin new(q); q^.A1:=p end;
if
(P^.A1=Nil) and (P^.A2=Nil) then
if q^.A1=P then q^.A1:=Nil // p - лист
else q^.A2:=Nil случай
else
if
P^.A1=Nil then
if q^.A1=P then q^.A1:=p^.A2 // p имеет
else q^.A2:=p^.A2 1 дочь
else случай 2)
if q^.A1=P then q^.A1:=p^.A1
else q^.A2:=p^.A1
else //две дочери:
begin
w:=p^.A1;
if w^.A2=Nil then w^.A2:=p^.A2
else begin
Repeat v=w; w:=w^.A2;
until w^.A2=Nil; // p имеет
v^.A2:=w^.A1; 2 дочери
w^.A1:=p^.A1; случай 3)
w^.A2:=p^.A2;
end
if q^.A1=P then q^.A1:=w
else q^.A2:=w;
end;
if p=proot then begin proot:=q^.A1; dispose(q) end;
Dispose(p);// исключения узла p
end;
end;// Delk
Тема 8. Хеширование
8.1. Что такое хеширование
Имеется глобальная проблема: поиск данных в списке.
а) Если данные расположены беспорядочно в массиве (линейном списке, файле), то осуществляют линейный поиск его эффективность 0(n/2);
б) Если имеется упорядоченный массив (двоичное дерево), то возможен двоичный поиск с эффективностью 0(log2n);
Однако при работе с двоичным деревом и упорядоченным массивом затруднены операции вставки и удаления элементов, дерево разбалансируется, и требуется балансировка, в массиве требуется сдвиг элементов.
Придумали алгоритм хеширования (hashing) при котором ключи данных записываются в хеш-таблицу. Идея в том, что при помощи некой простой функции i=h(key) алгоритм хеширования определяет положение искомого элемента в таблице по значению его ключа.
Допустим,
имеется набор n
записей с ключами в диапазоне
.
Создадим массив (хеш-таблицу):
H:array[0..K] of <тип записей>;
Вначале его очистим H[i]:=0 и наши n записей помещаем в этот массив в соответствии со значением ключа i=key. Затем, используя операторы
zp:=H[key];//извлекаем из массива
H[key]:=zp;//записываем в массив
Как видим, все изумительно просто и быстро, однако есть одно но!!!
Хорошо если ключи располагаются от 1 до 100. А если это номер страховой карточки с 9 значащими цифрами? Потребуется массив из 109 ячеек!!! Для одного города с миллионным населением в этом массиве будет использоваться только 0,1% ячеек, что абсолютно неприемлемо.
Чтобы все-таки использовать этот изящный способ и придумывают различные схемы хеширования, т.е. установление такой функциональной связи между значением ключа key и местоположением записи в некотором массиве, при котором размер таблицы был бы пропорционален количеству записей, а не величине ключа.