Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие 3000555.doc
Скачиваний:
31
Добавлен:
30.04.2022
Размер:
19.12 Mб
Скачать

2.11.2. Динамические списки

В предыдущем примере на каждую динамическую переменную указывала одна статическая. Можно ли и указатели перенести в динамическую память? Да, если воспользоваться связанным списком.

Каждый элемент связанного списка, во-первых, хранит какую-то информацию, во-вторых, указывает на следующий за ним элемент. Лишь на самый первый элемент (голову списка) имеется . отдельный указатель. Последний элемент никуда не указывает

Рис. 2.5

Элемент списка состоит из разнотипных частей (хранимая информация и указатель), и его естественно представить записью. Перед описанием самой записи описывают указатель на нее.

Пример. Описание списка из целых чисел.

type

PElement = ^TElement; {описание указателя}

TElement = record {описание элемента}

Inf: integer;

Next: PElement;

end;

Число элементов связанного списка может расти или уменьшаться в зависимости от того, сколько данных мы хотим хранить в нем. Чтобы добавить новый элемент в список, необходимо:

  • получить память для него;

  • поместить туда информацию;

  • присоединить новый элемент к голове списка.

Пример. Создание списка целых чисел.

program creat_list;

type

PElement = ^TElement; {описание указателя}

TElement = record {описание элемента}

Inf: integer;

Next: PElement;

end;

var

X, Head: PElement; i,n:integer;

begin

Head := nil;

for i:=l to N do begin

new (X);

readln (X^.Inf);

X^.Next:= Head;

Head := X;

end;

end.

Построение списка сводится к последовательному добавлению элементов в первоначально пустой список.

На пустой список указывает пустой указатель

Head = nil.

Для удаления первого элемента из непустого списка необходимо:

  • передвинуть указатель с головы на следующий элемент;

  • освободить память, занятую удаленным элементом.

Пример. Удаление первого элемента из списка.

program creat_first_element; type

PElement = ^TElement; {описание указателя} TElement = record {описание элемента} Inf: integer;

Next: PElement;

end;

var

X, Head: PElement; begin

{ Head указывает на первый элемент списка}

Х:= Head;

Head := Head^.Next;

dispose (X); end.

Важно уметь перебирать последовательно все элементы списка, выполняя над ними какую-то операцию. Это называется прохождением списка.

Пример. Пройти список, найдя сумму хранящихся в нем чисел.

program summa_list;

var

X, Head: PElement; Summa: Integer;

begin

...Summa := 0;

{ Head указывает на первый элемент списка} X := Head;

while X<> nil do

begin

Summa := Summa + X^.Inf;

X := X^.Next;

end;

end.

Список по своей сути является рекурсивной структурой данных, поэтому дадим рекурсивное определение списка.

Список каких-либо элементов — это или отсутствие этих элементов (пустой список) или элемент, за которым следует список.

Первый элемент списка называется головой списка, остальная часть списка называется хвостом списка.

Рекурсивное определение списка позволяет по-новому определить прохождение списка. Пройти список означает посетить голову и пройти список, следующий за головой (пройти хвост).

Печать списка при помощи рекурсивной процедуры.

procedure PrintList (Head: PElement); begin

if Head <> nil then begin

writeln (Head^Inf);

PrintList (Head^. Next)

end;

end;