
12.3. Средства языка паскаль для организации списков
Элемент списка создается для размещения в нем полезной информации (некоторых данных). Типы этих данных зависит от назначения списка, и могут быть какими угодно. В приводимых ниже примерах эта часть данных элемента списка будет иметь частный характер. Остальные части структуры элемента – переменные, используемые для организации списка, и их типы не зависят от назначения списка, то есть имеют не частный характер.
Структура элемента в Паскале описывается с помощью конструкции типа record.
Для связи элементов между собой используется тип «указатель на элемент».
В программе для связи со списком должны быть объявлены одна или несколько статических переменных-указателей на элемент списка. Это может быть голова списка (Head), конец списка (Tail) и другие.
В качестве примера приведем объявление типа элемента, информационная компонента которого задается полем Data типа TData.
Type PItem
= ^TItem; {указатель на элемент
двухсвязного списка} TItem
= record
{описание
структуры элемента
двухсвязного
списка}
Data : TData; {информационное
поле элемента} Prev
: PItem; {указатель
на предыдущий элемент} Next
: PItem; {указатель
на следующий элемент} end;
{При
работе с односвязным списком
указатель
на предыдущий элемент не нужен:}
PList
= ^TList; {указатель на элемент
односвязного списка} TList
= record
{описание
структуры элемента
односвязного
списка}
Data : TData; {информационное
поле элемента} Next
: PList; {указатель
на следующий элемент} end;
Для создания элемента списка как динамической переменной используют процедуру New:
{Пусть
в программе объявлена следующая
переменная:
} Var
P
: Pitem: {рабочая
переменная для временного хранения
указателя
на элемент списка} {Тогда
процедура создания динамической
переменной для элемента списка
может быть записана следующим образом:} New(P);
12.4. ТИПОВЫЕ АЛГОРИТМЫ РАБОТЫ СО СПИСКАМИ
При
рассмотрении алгоритмов тип информационного
поля в них может отличаться. А
var Head
: Pitem; { Указатель
на голову списка
} Tail
: Pitem; {
Указатель на «хвост» списка
} P
: Pitem; {
Указатель на элемент списка
}
А
Procedure
InitList; begin Head
:=
NIL; Tail
:= NIL; end;
А2. Добавить элемент в конец односвязного списка
В процедуре реализован следующий алгоритм (для случая односвязного списка, то есть для случая, когда:
создать элемент, подлежащий добавлению (зарезервировать память)
полям данных присвоить значения входных параметров
Если список не пуст:
установить указателю Next последнего элемента ссылку на новый
присвоить указателю Next нового элемента NIL
передвинуть Tail на новый элемент
Если список пуст
установить указатель Head на новый элемент
установить указатель Tail на новый элемент
присвоить указателю Next нового элемента NIL
Var pnew
:PList;
{указатель на новый элемент} begin
new(pnew);
pnew.data:=indata;
{присвоить
полю Data
значение} if
Head <> nil then
{список непустой ?}
Tail^.Next
:= pnew else
Head
:= pnew; {end
if}
pnew.Next:=nil; Tail
:= pnew; end;
А3. Исключить элемент из начала списка (вернув поле данных)
Procedure
OutList(var
OutDat:TData); Var
P:Plist; begin OutData
:= Head^.Data; p:=Head;
Head:=Head^.Next;
{присвоить
указателю
на
голову списка ссылку на новый первый
(бывший
второй) элемент}
Dispose(p);
{освободить
память, занятую элементом} end;
А4. Удалить элемент из середины списка с освобождением памяти
(для случая односвязного списка):
Р – указатель на удаляемый элемент
Prev
- указатель на элемент, стоящий перед
удаляемым элементом
Ф
P
:= Prev^.next;
Prev^.Next
:= P^.Next;
Dispose(P);
{освободить
память}
А5. Включить элемент (pnew) в середину списка
{Для
случая односвязного списка}
pnew^.next:=prev^.next;
prev^.next:=pnew;
А6. Обработать каждый элемент линейного списка
P
:= Head;
while
P
<> NIL do
begin
Выполнить
операцию обработки элемента P^
P
:= P^.Next;
{перейти к следующему элементу}
end;
П
Count
:= 0;
P
:= Head;
while
P <> NIL do
begin
if
P^.Data
> Value
then
Count
:= Count +1;
{end
if}
P
:= P^.Next;
end;
А7. Найти первый элемент, удовлетворяющий некоторому условию
Var
flagFound
: boolean;
begin
P
:= Head;
flagfound
:= false;
while
(P<>NIL)
and
(not
flagfound) do
if
(выполнено условие) then
flagfound
:= true {элемент
найден}
else
P
:= P^.Next;
end;
А8. Уничтожить список с освобождением памяти
В данном алгоритме используется следующий принцип: удалять последовательно элементы, начиная с первого в списке.
Это производится следующим образом: Вначале указатель на первый элемент (тот, который записан в указателе на голову списка Head) помещается в рабочую переменную Р. Затем переменнойHeadприсваивается значение указателя на следующий за ним. Это значение в односвязном списке размещается только в поле предыдущего (т.е. удаляемого) элемента. С этого момента бывший первый элемент выведен из списка, и его можно удалить из памяти компьютера, выполнив процедуру Dispose.
P
:= Head;
{Установить
указатель на удаляемый элемент}
while
P<>NIL
do begin
Head
:= P^.Next;
{установить
ссылку на следующий}
Dispose(P);
{освободить
память,
занятую
удаляемым элементом}
P
:= Head;
{установить
новый удаляемый элемент
}
end;