
- •Динамическая память.
- •Указатель.
- •Стандартные процедуры размещения и освобождения динамической памяти.
- •1. С помощью стандартной процедуры New:
- •2. С помощью стандартной процедуры GetMem.
- •С помощью стандартной процедуры Dispose
- •С помощью стандартной процедуры fRееМеm.
- •Стандартные функции обработки динамической памяти.
- •Примеры и задачи.
- •Организация списков.
- •Задачи включения элемента в линейный однонаправленный список без головного элемента.
- •Формирование пустого списка.
- •Формирование очередного элемента списка.
- •Подсчет числа элементов списка.
- •Вставка элемента в начало списка.
- •Включение элемента в конец списка.
- •Включение в середину (после I-ого элемента).
- •1.1Задачи на удаление элементов из линейного однонаправленного списка без головного элемента.
- •Удаление элемента из начала списка.
- •Удаление элемента из конца списка.
- •Удаление элемента из середины списка (в данном случае I-ого элемента).
- •Удаление всего списка с освобождением памяти.
- •Задачи на замену элементов в линейном однонаправленном списке без головного элемента.
- •Стеки, деки, очереди.
- •Использование рекурсии при работе со списками.
Удаление всего списка с освобождением памяти.
Procedure Delete_List ( Var First : el);
Var
P, q : el;
Answer : string;
Begin
If First <> Nil
Then Begin { список не пуст }
writeln ( ' Вы хотите удалить весь список ? (Y/N)' );
readln ( answer );
if answer = 'Y'
then begin
q:=First;
p:=nil;
While ( q <> nil ) do
Begin
p:=q;
q:=q^.Next;
Dispose ( p ) ;
End;
First:=Nil;
{именно этот оператор и
обеспечивает уничтожение списка}
End;
End
Else writeln ('список пуст ');
End;
Можно ли вместо всех указанных действий выполнить только одно – first := nil; ?
Задачи на замену элементов в линейном однонаправленном списке без головного элемента.
Операция замены элемента в списке практически представляет собой комбинацию удаления и вставки элемента.
Читателю дается возможность, используя представленные ранее графические приемы и примеры программ, самому написать процедуры замены элементов.
Перед выполнением операции замены элемента желательно запрашивать у пользователя подтверждение замены.
Действуя аналогично, можно построить графические схемы и программы задач действий с двунаправленными списками.
Работа с головным элементом
Назначение головного элемента.
Головной элемент содержит основные характеристики списка – адрес первого элемента, адрес последнего элемента, текущее количество элементов списка. Это даёт возможность не создавать и не применять постоянно подпрограммы определения текущего количества элементов списка, поиска адреса последнего элемента списка. Особенно наличие головного элемента облегчает работу с симметричным списком. Кроме того, при работе со списком циклы WHILE … DO и REPEAT…UNTIL могут быть заменены циклами FOR.
Структура головного элемента (приведен минимальный набор полей, последовательность их расположения произвольна)
-
First
N
Last
где:
First – адрес первого элемента списка;
Last - адрес последнего элемента списка;
N - текущее количество элементов списка;
Описание и использование головного элеме hd : hd_el;нта
Использование статической памяти:
{ нерекомендуемый вариант }
type
head_element=record
First : el; {адрес первого элемента списка }
last : el ; { адрес последнего элемента
списка }
{ el – адресный тип, связанный
с элементом списка }
n : integer; { текущее количество
элементов списка }
end;
var
hd : head_element;
begin
…
hd.first := nil;
hd.last := nil;
hd.n := 0;
{ инициализация полей головного элемента }
{ состояние - список пуст}
…
{ дальше – действия с полями hd.first и hd.last –
как с переменными first и last }
if hd.first = nil
then { список пуст}
begin
…
end
end.
Использование динамической памяти:
{ рекомендуемый вариант }
type
head_element=record
First : el; {адрес первого элемента списка }
last : el ; { адрес последнего элемента
списка }
n : integer; { текущее количество
элементов списка }
end;
head_el = ^ head_element;
var
hd : head_el;
begin
hd := nil; { состояние: список не существует }
…
new ( hd ); { выделение памяти под головной элемент }
hd^.first := nil;
hd^.last := nil;
hd^.n := 0;
{ инициализация полей головного элемента }
{ состояние - список существует, но ОН пуст}
…
{ дальше – действия с полями hd^.first и hd^.last –
как с переменными first и last }
…
{ ТИПИЧНОЕ НАЧАЛО РАБОТЫ СО СПИСКОМ, ИМЕЮЩИМ
инамический ГОЛОВНОЙ ЭЛЕМЕНТ : }
if hd = nil
then { список НЕ СУЩЕСТВУЕТ}
begin
…
end
ELSE if hd^.first = nil
then { список СУЩЕСТВУЕТ, но пуст}
begin
…
end
ELSE { список СУЩЕСТВУЕТ }
begin
…
end
…
{ работа со списком}
…
dispose ( hd ); { освобождение памяти
от головного элемента.
перед этим список должен
быть уничтожен
с освобождением памяти}
…
end.
фрагмент программы:
вставка элемента списка с адресом р
в начало линейного однонаправленного списка
…
if hd = nil
then { список НЕ СУЩЕСТВУЕТ}
begin
…
end
ELSE if hd^.first = nil
then { список пуст}
begin
hd^.first:= p;
hd^.last := p;
hd^.n := 1;
end
else { список не пуст}
begin
p^.next := hd^.first;
hd^.first := p;
hd^.n := hd^.n + 1;
end;
фрагмент программы:
вставка элемента списка с адресом р
в КОНЕЦ линейного однонаправленного списка
…
if hd = nil
then { список НЕ СУЩЕСТВУЕТ}
begin
…
end
ELSE if hd^.first = nil
then { список пуст}
begin
hd^.first:= p;
hd^.last := p;
hd^.n := 1;
end
else { список не пуст}
begin
hd^.LAST := p;
p^.next := NIL;
hd^.n := hd^.n + 1;
end;
ПРОВЕРКА КОРРЕКТНОСТИ НОМЕРА
ОБРАБАТЫВАЕМОГО ЭЛЕМЕНТА СПИСКА
…
if ( I < 1 ) OR ( I > hd^. n )
then begin
Writeln ( ' I = ' , I , ' ЗАДАНО НЕВЕРНО ' );
…
end