
- •Работает
- •1.1. История создания эвм.
- •1.3. Размещение данных и программ в памяти пэвм.
- •1.4.Файловая система хранения информации
- •1.5.Операционная система.
- •Лекция 2. Как составляются и выполняются программы в системе delphi
- •2.1. Понятие алгоритма и способы его записи
- •2.2. Общая характеристика языка Паскаль
- •2.3. Как составляется программа в системе Delphi
- •2.4. Наша первая программа реализует линейный алгоритм
- •3.1. Данные и их типы.
- •3.2. Операции над переменными основных скалярных типов
- •Алгоритмов
- •4.1. Понятие разветвляющегося алгоритма
- •4.2. Оператор условия if
- •4.3. Оператор выбора Case
- •4.4. Некоторые возможности, предоставляемые Delphi для организации разветвлений
- •Лекция 5. Составление и програмирование циклических алгоритмов
- •5.1. Понятие цикла
- •5.2. Оператор Repeat...Until
- •5.3. Оператор While...Do
- •5.4. Оператор For...Do
- •5.5. Вложенные циклы
- •5.6. Примеры некоторых часто встречающихся циклических алгоритмов Вычисление заданного члена рекуррентной последовательности
- •Вычисления сумм с использованием рекуррентной последовательности
- •6.1. Ошибки на этапе компиляции
- •6.4. Защищенные блоки
- •6.5. Некоторые стандартные типы исключительных ситуаций
- •6.6. Инициирование собственных исключительных ситуаций
- •6.7. Примеры фрагментов программ
- •Лекция 7. Составление программ с использованием массивов
- •7.1. Понятие массива
- •7.2. Некоторые возможности ввода-вывода в Delphi
- •7.3. Примеры часто встречающихся алгоритмов работы с массивами Сумма n элементов одномерного массива:
- •Произведение диагональных элементов квадратной матрицы:
- •Нахождение максимального элемента одномерного массива:
- •8.1. Статическое и динамическое распределение оперативной памяти
- •8.2. Понятие указателя
- •8.3. Наложение переменных
- •8.4. Динамическое распределение памяти
- •8.5. Организация динамических массивов
- •9.1. Понятие подпрограммы
- •9.2. Описание подпрограмм
- •9.3. Передача данных между подпрограммой и вызывающей ее программой
- •9.4. Оформление подпрограмм в библиотечный модуль
- •9.5. Примеры подпрограмм, оформленных в отдельные библиотечные модули
- •Пример программы, использующей модуль RabMas:
- •Множества
- •10.1. Понятие множества
- •10.2. Операции над множествами
- •10.3. Примеры работы с множествами
- •Interface
- •11.1. Зачем нужны строки
- •11.2. Описание переменных строкового типа «Короткие строки»
- •11.3. Основные операции над переменными строкового типа
- •11.4. Некоторые процедуры и функции обработки строк
- •11.5. Примеры алгоритмов обработки строк
- •Лекция 12. Программирование с использованием записей
- •12.1. Понятие записи
- •12.2. Операции над записями
- •12.3. Использование записей для работы с комплексными числами
- •13.1. Понятие файла
- •13.2. Операции над файлами
- •13.2.1. Типизированные файлы
- •13.2.2. Текстовые файлы
- •13.3. Подпрограммы работы с файлами
- •13.4. Компоненты tOpenDialog и tSaveDialog
- •Лекция 14. Программирование с отображением графической информации
- •14.1. Как рисуются изображения
- •14.2. Построение графиков с помощью компонента tChart
- •Лекция 15. Программирование с использованием рекурсии
- •15.1. Понятие рекурсии
- •15.2. Примеры рекурсивных вычислений
- •16.1. Организация работы с базами данных
- •16.2. Поиск в массиве записей
- •16.3. Сортировка массивов
- •16.3.1. Метод пузырька
- •16.3.2. Метод прямого выбора
- •16.3.3. Метод Шелла
- •16.3.4. Метод Хоара (Hoare)
- •17.1. Работа со списками
- •17.2. Добавление нового элемента в список на заданную позицию
- •17.3. Удаления элемента с заданным номером
- •17.4. Пример программы
- •Лекция 18. Связанные списки на основе рекурсивных данных
- •18.1. Что такое стек и очередь
- •18.2. Понятие рекурсивных данных и однонаправленные списки
- •18.3. Процедуры для работы со стеками
- •18.4. Процедуры для работы с односвязными очередями
- •18.5. Работа с двухсвязными очередями
- •18.6. Процедуры для работы с двусвязными очередями
- •19.1. Основные понятия и определения
- •19.2. Прямые методы решения слау
- •19.3. Итерационные методы решения слау
- •20.1. Зачем нужна аппроксимация функций?
- •20.3. Какие бывают многочлены и способы интерполяции?
- •20.4. Что такое среднеквадратичная аппроксимация?
- •20.5. Метод наименьших квадратов (мнк)
- •21.1. Формулы численного дифференцирования
- •21.2. Формулы численного интегрирования
- •22.1. Как решаются нелинейные уравнения
- •22.2. Итерационные методы уточнения корней
- •22.2.2. Метод Ньютона
- •23.1. Постановка задач оптимизации, их классификация
- •23.2. Методы нахождения минимума функции одной переменной
- •24.1. Задачи для обыкновенных дифференциальных уравнений
- •24.2. Основные положения метода сеток для решения задачи Коши
- •24.3. Многошаговые схемы Адамса
- •Литература
Лекция 18. Связанные списки на основе рекурсивных данных
18.1. Что такое стек и очередь
Ранее мы рассмотрели простейшую форму организации списка - на основе динамических массивов данных. Недостатком таких списков является то, что при добавлении или удалении элементов в список приходится копировать динамические массивы и менять размер выделенной памяти, чтобы перестроить массив, сдвигая на одну позицию все элементы расположенные правее места вставки (удаления). Более эффективная организация списка, не требующая копирования динамических массивов, может осуществляться на основе рекурсивного типа данных. Рекурсивный тип данных при своем описании допускает обращение к самому себе. В Pascal рекурсивный тип данных представляет собой запись, содержащую набор полей для хранения информационной части элемента и одного (односвязный) или двух (двухсвязный список) полей, представляющих собой указатели (т. е. адреса) на соседний или соседние элементы списка.
Связанный список - это структура данных в виде списка, элементы которого связаны друг с другом с помощью указателей. Наибольшее распространение получили две формы списка - стек и очередь.
Стек - это список с одной точкой входа. Данные добавляются в список и удаляются из него только с одной стороны списка (вершины стека). Таким образом, реализуется принцип - «последним вошел - первым вышел». Наглядный пример - трубка, запаянная с одного конца и заполняемая шариками, имеющими диаметр, равный внутреннему диаметру трубки. Первый вставляемый шарик всегда будет доставаться последним.
Очередь - это список с двумя точками входа. С одной стороны последовательности данные добавляются в список (в конец очереди), с другой стороны списка данные удаляются из него (из начала очереди). Таким образом, реализуется принцип - «первым вошел - первым вышел». Наглядный пример - трубка, открытая с обеих сторон, заполняемая шариками, имеющими диаметр, равный внутреннему диаметру трубки. С одной стороны трубки шарики добавляются в нее, с другой вынимаются.
18.2. Понятие рекурсивных данных и однонаправленные списки
Рекурсивный тип данных для односвязных списков имеет вид:
Type Tinf=integer; //Описание типа информационной части TSel=ASel; //Описание типа указателя на элемент Sel=record // односвязных списков inf:Tinf; a:TSel; end;
Тип Tinf содержит описание информационной части элемента списка, которая в каждом конкретном случае своя. В данном случае и при последующем изложении материала будет использована эта простейшая структура информационной части. Не следует забывать переопределить её в той или иной конкретной программе.
Как видим, описание типа TSel содержит внутри обращение к самому себе (a:TSel) , т.е. оно рекурсивно. При этом a является указателем на ячейку памяти точно такой же структуры. В поле inf размещается информационная часть элемента списка, причем, по крайней мере, в одном из полей inf, а иногда и в отдельном поле записи расположены сведения, по которым производится поиск или сортировка требуемой информации. Это поле будем обозначать key:Tkey, а сведения называть ключом.
С помощью такого рекурсивного типа организуются однонаправленные связанные списки следующим образом: элементы списка размещаются в ячейках памяти типа TSel, причем в поле a каждой ячейки помещается адрес следующей за ней ячейки (рис. 18.1.):
spi sp2 sp3 sp k-1 sp k
a1 |
► |
a2 |
► |
a3 |
► ► |
ak-1 |
► |
ak |
infi |
|
inf2 |
|
inf3 |
|
infk-1 |
|
infk |
Рис 18.1.
Все ячейки динамически размещаются в куче по адресам sp1, sp2, spk. При такой организации списков очень просто удалять или вставлять новые ячейки. Так, чтобы удалить ячейку с адресом sp2, в адресную часть предшествующей ячейки нужно занести адрес последующей ячейки и освободить память, занимаемую удаляемой ячейкой ( sp1A.a:=sp3; dispose(sp2); см. рис 18.2.).
infk
Для добавлении новой ячейки между ячейками с адресами sp1 и sp2 необходимо создать новую ячейку, занести в нее информационную часть, в адресную часть предшествующей ячейки занести адрес новой ячейки, а в адресную часть новой ячейки адрес последующей ячейки (new(sp); spA.inf:=inf; sp!A.a:=sp; spA.a:=sp2; см. рис. 18.3.).
sp1 sp2
|
a1 |
V » |
a2 |
|
|
\ / |
| ||
inf1 |
inf2 |
aвст
infвст
Рис. 18.3.
Адресная часть последней ячейки spkA.a:=nil; Для стека задается вершина стека, равная адресу 1-й ячейки (в обозначениях рис. 18.1.) w:=sp1;, а для односвязной очереди адрес начала очереди w1:=sp1; и адрес конца очереди (адрес последней ячейки) wk:=spk; .
Пример. Создать стек, содержащий целые числа, и найти количество положительных элементов стека
Type
Tinf=integer; // Описание типа информационной части
TSel=ASel;
Sel=record
inf:Tinf;
a:TSel;
end;
var k,n,kol:integer; w,t:TSel;
begin
n:=strtoint(edit1.Text); // Количество элементов стека w:= nil; Randomize; // Вершина стека
for k:=1 to n do begin
New(t); // Создаем новый элемент
tЛ.inf:=random(101)-50;//Запись информационной части tA.a:=w; // В адресную часть заносим прежнюю вершину w:=t; // Задаем новую вершину
end;
ListBoxl.Clear; t:=w; kol:=0;
while t<>nil do begin
к:=^.^^//Читаем информ. часть текущего элемента
ListBox1.items.add(inttostr(k));
if k>0 then inc(kol);
t:=tA.a; // Задаем адрес следующего элемента end;
label1.Caption:='Кол. полож. элементов стека = '
+inttostr(kol);
end;
Для работы с односвязными списками необходимо создать, например, модуль List1S, содержащий описание рекурсивного типа и набор специализированных процедур.