Слайд 1Программирование и ОА ч.2
Теоретический материал
к практическому занятию №1
«Списки»
Слайд 3Динамические переменные
Все переменные, которые мы использовали в предыдущих программах являлись
статическими. То есть при компиляции за переменными закреплялась память на
все время работы программы, хотя часть переменных могла использоваться только в части программы. Кроме того статически выделяемая память, как мы видели, ограничена. Для более экономного использования памяти и увеличения ее размера для программ используется динамическое распределение памяти.
Слайд 4 В отличие от статических переменных, Динамические переменные создаются и уничтожаются
во время выполнения программы.
Динамические переменные не имеют имени. Для
работы с ними введены специальные ссылочные типы, или указатели. По существу указатель - это адрес, начиная с которого динамическая переменная размещена в памяти.
Слайд 5Указатель связывается не с конкретной переменной, а с определенным типом
данных. Для описания указателя используется знак “^”.
Пример описания
Type
IP = ^Integer; {тип указателя на целое}
P = ^Zap; {тип указателя на запись Zap}
Zap = record
...
end;
Var
Pointer1 : ^Char; {указатель на Char}
Pointer2 : ^Real; {указатель на Real}
Pointer3 : IP;
Pointer4 : P;
Слайд 6В Турбо Паскале определена лишь одна операция над указателями -
присваивание. Можно присвоить значение одного указателя другому указателю на тот
же тип данных.
NIL -специальное значение, обозначающее пустой указатель, который ни на что не указывает.
Слайд 7Для того, чтобы выделить место в динамической памяти под динамическую
переменную, используется процедура NEW.
type
PE =
^integer;
begin
...
New(PE);
...
end.
Слайд 8В приведенном примере выделяется 4 байтов и адрес начала этой
области возвращается в указателе PE. Для обращения к полученной динамической
переменной используется конструкция вида <имя указателя>^:
PE^:=3;
F :=sqr(PE^);
Для освобождения динамической памяти используется процедура Dispose -
Dispose(PE); {освобождает 4 байтов в куче}
Слайд 9СПИСКИ
Одной из областей, где необходимо использование указателей, является работа со
списками, односвязными и двусвязными. Списки имеют начало и конец. Основные
действия: создание, просмотр, вставка и удаление элемента в указанном месте списка.
Широкое распространение среди односвязных списков получили такие динамические структуры данных, как стеки, очереди и кольцеобразные списки.
Слайд 10Структура односвязного списка
Структура односвязного списка
Список имеет начало N,
конец К и текущий указатель S.
Слайд 11Описание и просмотр элементов списка
type tz = record
inf: integer;
next :
tu;
tu = ^ tz;
var z: tz; N,S,K :tu;
begin {создание не
рассматриваем}
S:=N;
repeat writeln(S^.inf); S:= S^.next; until s=nil;
Слайд 12Стек организован таким образом, что программе доступна лишь его вершина
W: оттуда можно взять элемент или записать его туда. Таким
образом, элементы можно извлечь из стека в порядке, обратном порядку их записи -"последний вошел - первый вышел“ (LIFO)
Слайд 15Добавление второго элемента
Создаем вспомогательный указатель S на запись и заносим
информацию inf2 в поле записи.
Слайд 16Приравниваем поле указателя next вершине W
Слайд 17Приравниваем вершину W указателю S
W
nil
S
Слайд 18Присваиваем указателю S значение nil
W
nil
S
nil
Слайд 19Удаление из вершины
Перенос вершины на первый элемент :
W:= W^.next ;
W
nil
Слайд 20Очередь
Очередь же реализует другой вариант доступа к данным - "первый
вошел - первый вышел’. Новый элемент добавляется в конец очереди,
а выбирается первый (FIFO).
Слайд 22Добавление элемента
Создаем элемент, как в стеке
Слайд 23Вставляем в конец очереди
S^.next := nil; K^.next := S;
Слайд 25Кольцо
Если последний элемент очереди связать с первым элементом, то получится
замкнутый, кольцеобразный список. В нем используется текущий указатель, можно добавлять
или удалять элементы в место, где он находится.