pascal_lections
.pdf
Динамические структуры данных
Классификация статических данных:
У статических данных взаиморасположение и взаимосвязи между элементами всегда остаются постоянными.
|
|
|
|
|
статические данные |
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
простые (скалярные) данные |
|
|
|
|
составные (агрегатные) данные |
||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
стандартные |
|
|
определяемые |
|
|
|
|
|
|
|
|
|
|
|
|
|
(базовые) |
|
|
программистом |
|
|
|
однородные |
|
|
неоднородные |
|||||
|
типы данных |
|
|
типы данных |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
арифметические |
|
|
|
|
|
|
строки |
|
|
простые записи |
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
натуральные |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
числа |
|
|
|
|
|
|
|
|
|
|
|
|
символьные |
|
|
|
|
|
|
множества |
|
|
вариантные |
|||||
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
записи |
|
|
|
|
|
|
целые числа |
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
логические |
|
|
|
|
|
|
массивы |
|
|
объединения |
|||||
|
|
|
|
|
|
|
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
вещественные |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
числа |
|
|
|
|
|
|
|
|
|
|
|
|
указательные |
|
|
|
|
|
|
|
|
|
|
|
|
объекты |
||
|
(ссылочные) |
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
комплексные |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
числа |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
вектор |
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
матрица
многомерный
массивы простых данных
массивы
однородных
структур
массивы
неоднородных
структур
массивы файлов
Классификация динамических данных У динамических данных внутреннее строение формируется по какому-либо закону, но
количество элементов, их взаиморасположение и взаимосвязи могут динамически меняться во время выполнения программы
51
|
динамические данные |
|
|
|
несвязанные |
|
связанные |
файлы |
динамические |
динамические |
|
|
данные |
|
данные |
текстовые |
|
|
|
|
классификация |
|
|
типизированные |
аналогична |
|
|
статическим |
|
|
|
|
|
|
|
|
данным |
|
|
нетипизированные |
|
|
|
линейные |
кольцевые |
|
разветвленные |
структуры |
структуры |
|
структуры |
односвязные |
односвязный |
|
граф |
|
|
|
|
|
кольцевой список |
|
|
очередь |
|
|
дерево |
|
многосвязный |
|
|
стек |
кольцевой список |
бинарное |
|
|
|
||
дек |
|
|
разветвленное |
список |
|
|
|
многосвязные |
|
|
|
многосвязный |
|
|
|
линейный список |
|
|
|
Распределение памяти
При объявлении данных динамической структуры, в разделе описаний указывается не сама переменная какого-либо типа, а указатель (ссылка) на нее. В результате указатель будет обычной переменной, а переменная на которую он указывает – динамической.
|
|
|
|
Var |
P : ^char |
|
|
P^ : char |
P : ^Char; |
|
|
Begin |
||
|
|
|
|
|
адрес. |
|
|
значение. |
P^ := ‘*’; |
|
|
например: '*' |
... |
|
|
|
|
||
|
|
|
|
|
|
|
|
|
end. |
|
|
|
|
Использование идентификатора указателя в программе означает обращение к адресу ячейки памяти, на которую он указывает. Чтобы обратиться к содержимому ячейки, требуется после идентификатора указателя поставить символ ^ - операция разыменования.
Выделение и освобождение памяти под динамические переменные выполняется процедурами: New, Dispose, GetMem, FreeMem, Mark, Release во время выполнения программы.
Указательная переменная Р может быть в трех состояниях:
52
1. |
Содержать |
адрес какой-либо переменной, память под которую уже выделена |
||||||||||||
|
|
P |
P^ |
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
P |
|||||
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
||||||
2. |
Содержать специальный пустой адрес nil |
|
|
|
|
NIL |
||||||||
|
|
|
|
|||||||||||
|
|
|
|
|
||||||||||
P |
||||||||||||||
|
|
|
|
|
|
|
|
|
||||||
3. |
Находиться в неопределенном состоянии |
|
|
|
||||||||||
|
|
|
|
? |
||||||||||
|
|
|
|
|
|
|||||||||
|
|
|
|
|
|
|||||||||
Различие между состоянием nil и неопределенным состоянием:
P1 |
P2 |
P3 |
P4 |
|
|
? |
? |
|
NIL |
|
|
|
P1 = P2 |
P3 <> P4 |
|
Простейшие действия с указателями:
Процедура New(A) выделяет область памяти соответственно тому типу, который описан для указателя А и записывает адрес выделенной памяти в указатель.
Процедура Dispose(A) освобождает область памяти, на которую указывает указатель А, после чего эта область становится доступной для распределения под другие динамические переменные.
53
Несвязанные динамические данные
Несв.Дин.Дан классифицируются также как статические, и работа с ними аналогична. Отличие в следующем:
-в разделе var объявляется не переменная требуемого типа, а указатель на этот тип;
-перед использование необходимо создать указатель процедурой New, а после использования уничтожить процедурой Dispose.
Сравнение методов работы с аналогичными статическими и несвязанными динамическими данными.
Структура данных |
Обычная переменная |
Динамическая переменная |
||
1. Простая переменная |
Type Tint = 1..100; |
Type Tint = 1..100; |
||
|
Var X: char; |
|
Var PX: ^char; |
|
|
Y: Tint; |
|
PY: ^Tint; |
|
|
Begin |
|
Begin |
|
|
X := ‘*‘; |
|
New(PX); |
|
|
Y := 3; |
|
New(PY); |
|
|
... |
|
PX^ := ‘*‘; |
|
|
End. |
|
PY^ := 3; |
|
|
|
|
... |
|
|
|
|
Dispose(PY); |
|
|
|
|
Dispose(PX); |
|
|
|
|
End. |
|
2. Массив |
Type |
|
Type |
|
|
Vect = array [1..3] |
Vect = array [1..3] |
||
|
|
of byte; |
of byte; |
|
|
Var X: Vect; |
|
Var PX: ^Vect; |
|
|
i: Byte; |
|
i: Byte; |
|
|
begin |
|
begin |
|
|
for i:=1 to 3 do |
New(PX); |
|
|
|
read(X[i]); |
for i:=1 to 3 do |
||
|
... |
|
read(PX^[i]); |
|
|
End; |
|
... |
|
|
|
|
Dispose(PX); |
|
|
|
|
End; |
|
3. Запись |
Type |
|
Type |
|
|
Rec = record |
|
Rec = record |
|
|
A: char; |
B: byte; |
A: char; |
B: byte; |
|
end; |
|
end; |
|
|
Var X: Rec; |
|
Var PX: ^Rec; |
|
|
Begin |
|
Begin |
|
|
X.A := ‘*‘; |
|
New(PX); |
|
|
X.B := 3; |
|
PX^.A := ‘*‘; |
|
|
... |
|
PX^.B := 3; |
|
|
End. |
|
... |
|
|
|
|
Dispose(PX); |
|
|
|
|
End. |
|
54
Связанные динамические данные
Основные определения.
Линейные списки – это данные динамической структуры, которые представляют собой совокупность линейно связанных однородных элементов. Над линейными списками разрешены операции:
-добавление эл-та в начало (голову) списка
-добавление эл-та в конец (хвост) списка
-вставка эл-та между двумя любыми другими эл-ами списка
-удаление любого эл-та списка
Кольцевые списки – это данные динамической структуры, похожие на линейные списки, но имеющие дополнительную связь между последним и первым элементом.
Очередь – частный случай линейного односвязного списка, для которого разрешены только два действия:
-добавление элемента в конец (хвост) очереди
-удаление элемента из начала (головы) очереди
Стек – частный случай линейного односвязного списка, для которого разрешено добавлять и удалять элементы только с одного конца списка – с вершины (головы) стека Деревья – динамические данные иерархической структуры произвольной конфигурации.
Элементы дерева называются узлами (вершинами). Концевые вершины называются листьями. Пирамида (упорядоченное дерево) – дерево, в котором значения вершин всегда возрастают или убывают при переходе на следующий уровень.
Возрастающая пирамида
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
|
|
|
|
|
|
6 |
|
|
|
9 |
|
|
|
8 |
|||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
|
|
|
12 |
|
|
10 |
|
|
|
15 |
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
Убывающая пирамида |
|
|
|
|
|
||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
|
|
|
|
|
31 |
|
|
17 |
|
|
12 |
||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
|
|
8 |
|
|
21 |
|
|
|
11 |
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55
Организация взаимосвязей в связанных динамических данных
Для организации связей между элементами динамической структуры, требуется – чтобы каждый элемент содержал какие-либо информационные значения и хотя бы один указатель. Следовательно, в качестве элементов динамических структур удобно использовать записи, которые могут объединять в единое целое разнородные элементы.
Type
TPtr = ^TElem;
TElem = record Info :real; Link :TPtr;
end;
Info |
Link |
|
|
|
|
Info
Link
Info
Link
NIL
Работа с очередью
Для создания очереди и работы с ней необходимо иметь как минимум два указателя:
-указатель на начало очереди (идентификатор BegQ)
-указатель на конец очереди (идентификатор EndQ)
иеще требуется дополнительный временный рабочий указатель (Р).
Создание очереди.
1 исходное состояние
BegQ:=nil;
EndQ:=nil;
|
BegQ |
EndQ |
|
P |
|
||
|
|
|
|
|
|
|
|
nil |
|
NIL |
nil |
? |
|
|
|
|
|
|
|||||
?
2 выделение памяти под первый элемент очереди
New(P);
|
BegQ |
EndQ |
|
|
P |
||
|
|
|
|
|
|
|
|
nil |
|
NIL |
|
nil |
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
? 


?
3 занесение информации в первый элемент очереди
P^.Info:=3;
P^.Link:=nil;
|
BegQ |
EndQ |
|
|
P |
||
|
|
|
|
|
|
|
|
nil |
|
NIL |
|
nil |
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 


NIL
4 установка указателей BegQ и EndQ на созданный первый элемент
BegQ:=P;
56
EndQ:=P;
BegQ |
|
EndQ |
|
P |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 
NIL
Добавление элемента очереди
1 исходное состояние
BegQ |
|
EndQ |
P |
2 |
4 |
3 |
? |
|
|
NIL |
|
2 выделение памяти под новый элемент очереди и занесение в него информации
New(P);
P^.Info:=5;
P^.Link:=nil;
BegQ |
|
EndQ |
P |
2 |
4 |
3 |
5 |
|
|
NIL |
NIL |
3 установка связи между последним элементом очереди и новым, а также перемещение указателя конца очереди EndQ на новый элемент
EndQ^.Link:=P;
EndQ:=P;
BegQ |
|
EndQ |
P |
2 |
4 |
3 |
5 |
|
|
|
NIL |
Удаление элемента очереди
1 исходное состояние
BegQ |
P |
|
EndQ |
|
|
? |
|
2 |
4 |
3 |
5 |
NIL
2 извлечение информации из удаляемого элемента в переменную VAL и установка на него вспомогательного указателя Р
57
VAL:=BegQ^.Info;
P:=BegQ;
P |
BegQ |
EndQ |
|
|
|
|
|
|
VAL
2 |
2 |
4 |
3 |
5 |
NIL
3 перестановка указателя начала очереди BegQ на следующий элемент, используя значение поля Link, которое хранится в первом элементе очереди. После этого освобождается память начального элемента очереди, используя вспомогательный указатель Р
BegQ:=P^.Link;
Dispose(P);
P |
BegQ |
EndQ |
VAL
2 |
2 |
4 |
3 |
5 |
NIL
Пример. Программа создания и удаления очереди из 10 элементов.
Процедура AddEl – создает первый эл-нт и добавляет последующие в конец очереди. Процедура DelEl – извлекает информацию из первого элемента и удаляет его из очереди.
Program Queue;
Uses crt;
Type
TPtr = ^TElm;
TElm = record
Info :real;
Link :TPtr;
End;
Var
BegQ, EndQ :TPtr;
Value :real;
I :integer;
Procedure AddEl;
Var P:TPtr;
Begin
New(P);
P^.Info:=random(100)/100;
P^.Link:=nil;
If EndQ=nil then
BegQ:=P {если создается первый элемент}
Else
EndQ^.Link:=P; {если создается очередной элемент}
EndQ:=P;
End;
Procedure DelEl(var VAL:real);
Var P:TPtr;
Begin
58
VAL:=BegQ^.Info;
P:=BegQ;
BegQ:=P^.Link;
If BegQ=nil then EndQ:=nil; {если очередь кончилась}
Dispose(P);
End;
BEGIN Clrscr;
{начальная установка} BegQ:=nil;
EndQ:=nil;
{создание очереди из 10 элементов} for I:=1 to 10 do
AddEl;
{удаление очереди} while BegQ<>nil do begin
DelEl(Value);
Writeln(‘Value=’, Value:8:4); end;
END.
Работа со стеком
Для работы со стеком необходимо иметь один указатель на вершину стека (идентификатор Тор) и один вспомогательный указатель (идентификатор Р)
Создание стека
1 исходное состояние
Top:=nil;
Top |
P |
||||||
|
|
|
NIL |
|
|
|
? |
|
|
|
|
|
|
||
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
2 выделение памяти под первый элемент стека и внесение в него информации
New(P);
P^.Info:=5;
P^.Link:=nil;
Top |
P |
NIL
5 


NIL
3 установка вершины стека Тор на созданный элемент
Top:=P;
Top |
P |
5 |
NIL |
59
Добавление элемента стека
1 исходное состояние
P
?
Top
3
1
5
NIL
2 выделение памяти под новый элемент стека
New(P);
P
?
?
Top
3
1
5
NIL
3 внесение значения в информационное поле нового элемента и установка связи между ним и «старой» вершиной стека Тор
P^.Info:=Val; {Val=10} P^.Link:=Top;
P
10
Top
3
1
5
NIL
4 перемещение вершины стека на новый элемент
Top:=P;
60
