
- •Теоретический раздел лекции Тема 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. Индивидуальные задания
- •Курсовая работа
- •Литература
4.2. Списки на основе динамических массивов
Простейшая форма организации списка – это динамический массив данных. Данные, размещенные в массиве имеют свои номера (индексы) и это придает эффект «видимости» каждому элементу. Мы уже научились некоторым приемам работы с массивами и оценили их эффективность.
Рассмотрим как организуется работа со списками на основе динамического массива a переменного размера n.
Напишем класс для работы с таким списком:
Листинг 4.1
type
Tinf=<тип элементов>;
Tms=array[1..1] of Tinf;
Pms=^Тms; //указатель на массив
Tlist=Class(Tobject)
a,a1:pms; n,mt:word;
constructor create;
procedure Addk(с:Tinf);//добавить элемент
procedure Read1(var с:Tinf);//удалить элемент
end;
constructor Tlist.create;
begin
Inherited create;
n:=0; mt:= sizeof(Tinf); a:=Nil; end;
End;
. . . . . . . . . . .
Var turn:Tlist; с1,c2:Tinf;
begin
turn.create; //создадим новую очередь
Read(n); //введем в нее сохраненный ранее список
for i:=1 to n do
begin Read(Fl,c1); turn.Addk(c1) end;
.................//далее работаем с очередью:
turn.Addk(c1); //добавляем элементы
turn.Read1(c2); //читаем и удаляем элементы
. . . . . . . . . .
turn.Free;
При реализации метода Addk добавления нового элемента в список необходимо выделить память на 1 элемент большую, затем скопировать старый список в новый раздел памяти, добавить в нужное место массива еще 1 элемент, после чего освободить ранее выделенную память и установить указатель a на новый раздел памяти:
Листинг 4.2
procedure Tlist.Addk;
begin
GetMem(a1,(n+1)* mt); a1[n+1]:=с;//добавление элемента
if n>0 then begin
for i:=1 to n do a1[i]:=a[i];//копирование элементов
FreeMem(a,mt*n);//освобождение ранее выделенной памяти
End;
a:=a1; n:=n+1;//теперь имя опять a
end;
Аналогично реализуется метод чтения и удаления элемента:
procedure Tlist.Read1;
begin
if n>0 then begin
c:=a[1]; n:=n-1;
if n>0 then begin
GetMem(a1,n* mt);
for i:=1 to n do a1[i]:=a[i+1];//копирование элементов
end else a1:=nil;
FreeMem(a,mt*(n+1));//освобождение ранее выделенной памяти
a:=a1; //теперь имя опять a
end;
end;
Эта простая схема хорошо работает для небольших списков, но у нее есть следующий существенный недостаток. При каждом добавлении приходится менять размер выделенной памяти и, что еще хуже, копировать.
Иногда хороший выход из этой ситуации – организация изменения размера n порциями (например по 20 элементов). Можно сделать размер порции зависимой от текущей длины массива (например 10% от n).
Процедура удаления i-го элемента тоже требует кроме выделения новой памяти и копирования еще и «схлопывания», т.е. сдвига каждого элемента на одну позицию, чтобы заполнить освободившуюся i-го позицию. Вместо удаления заданного элемента, чтобы избежать копирования, его можно пометить как неиспользуемый, поместив в ключ так называемое «мусорное» значение (например ключ=0), а при организации процедур обработки списка предусмотреть это. По мере накопления мусора в списке его надо собирать, что делается за один проход копирования.