Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Презентации 2часть / Лекция_23_24_ДинамическиеСписки.ppt
Скачиваний:
22
Добавлен:
11.05.2015
Размер:
232.45 Кб
Скачать

Readk взять последний элемент из очереди

Procedure TlistTrn.Reаdk(var Inf:Tinf);

Begin

Inf:=spk.Inf;

if sp1=spk then //если одна

begin Dispose(sp1); sp1:=Nil; spk:=Nil end

else begin

sp:=sp1;//поиск предпоследней

while sp^.A<>Spk do sp:=sp^.A;

Dispose(spk);

spk:=sp;

spk^.A:=Nil;

end

end;

sp1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

spk

 

 

 

 

….

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

I1

A1

Ik-1

 

Ak-1

 

 

 

Ik

nil

 

 

 

 

 

 

 

 

 

 

 

 

 

 

07/02/19

 

 

 

 

41

Некоторые проблемы работы с однонаправленным списком

Как мы видели, в однонаправленном списке довольно сложно взять элемент изнутри списка

Например последний элемент из очереди просто так удалить не получается, хотя имеется его адрес spk

Так же проблематично вставить элемент внутрь очереди перед заданным

Хотя довольно эффективно работают процедуры удаления и вставки элемента после элемента с заданным адресом ReadAftter, AddAftter.

Однако при их регулярном использовании имеется проблема первого элемента – его надо обрабатывать другой процедурой, а значит каждый раз требуется лишняя проверка

Чтобы избавиться от нее, часто используют Список с меткой

07/02/19

42

Список с меткой

sp1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

….

 

 

 

 

 

spk

 

 

 

 

 

I

A

 

 

I1

A1

 

 

 

Ik-1

Ak-1

 

 

 

Ik

nil

 

 

 

 

 

 

 

 

В таком списке от первой ячейки используется только ее адресная часть sp1.A,

в информационной же части могут быть при необходимости размещены данные об этом списке, при этом метка создается методом Add1

Stekm:=create;

Stecm.add1(Infm); .

При работе со стеком sp1 остается неизменным

После создания списка с меткой работа с ним производится с помощью единообразных процедур ReadAfter, AddAfter, PoiskAfter.

07/02/19

43

Циклические связанные списки

sp1

 

 

 

 

 

 

 

….

 

 

 

 

 

 

 

 

 

 

I1

A1

 

 

 

Ik-1

Ak-1

 

 

Ik

sp1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Циклические списки используются, когда нужно обходить набор элементов в бесконечном цикле.

Они так же позволяют получить доступ к списку начиная с любой позиции, что придает списку некоторую симметрию.

Программа может работать со всеми элементами

одинаково без использования меток с помощью процедур RedAfter, AddAfter, PoiskAfter.

07/02/19

44

 

Обход циклического списка

Procedure TlistStk.Printc(sp1:Psel);

begin sp:=sp1;

Repeat

Write(sp^.Inf);

sp:=sp^.A;

Until sp:=sp1;

end;

При работе с циклическим списком необходимо держать в памяти адрес одного из элементов sp1.

07/02/19

45

Двухсвязные списки

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

spk

sp1

 

 

 

I

 

 

 

A1

A2

 

 

 

I

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

nil

 

А2

 

 

 

I

 

 

 

A1

 

nil

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

организуются когда требуется просматривать список как в одном так и в обратном направлениях.

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

Эта проблема легко решается, если ввести рекурсивный тип с двумя адресными ячейками

07/02/19

46

Рекурсивный тип с двумя адресными ячейками

Type

Tseld=^seld;

seld=record

Inf:Tinf;

A1:Tseld;

A2:Tseld;

end;

Tlistd=class(Tobject)

sp1,spk,sp:Tseld;

constructor create;

procedure add1(inf:Tinf);

procedure readk(var inf:Tinf);

. . . . . . . . . .

end;

07/02/19

47

Движение по списку

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

spk

sp1

 

 

 

I

 

 

 

A1

A2

 

 

 

I

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

nil

 

А2

 

 

 

I

 

 

 

A1

 

nil

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

движение вправо

Write(sp1.A2.A2.inf);

sp:=sp1.A2;

движение влево

Write(spk.A1.A1.inf);

sp:=spk.A1;

07/02/19

48

Добавление элемента в начало

Procedure Tlistd.add1(Inf:Tinf);

begin

if sp1=nil then

 

 

 

begin New(sp1);

 

 

 

 

 

 

sp1^.inf:=inf;

 

 

 

 

 

 

Sp1^.A1:=nil;

 

 

 

 

 

 

sp1^.A2:=nil;

 

 

 

 

 

 

spk:=sp1 end

 

 

 

 

else begin

 

 

New(sp);

 

 

 

 

 

 

 

sp^.A1:=Nil; sp^.A2:=sp1;

sp^.inf:=inf; sp1^.A1:=sp;

sp1:=sp; end;

 

 

end;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

sp1

 

 

I

 

 

 

 

A1

 

A2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

nil

 

А2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

I

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

nil A2 07/02/19sp I

I

 

 

 

spk

 

 

 

A1

 

nil

 

 

 

 

 

 

 

49

Добавление в начало

 

 

 

 

 

 

Inf

 

 

 

 

 

 

 

 

 

 

 

Если список был пуст

sp1

 

 

 

I

 

 

 

spk

 

 

 

 

 

 

 

 

 

 

nil

 

 

nil

 

 

 

 

sp1

I

A1 A2

I

spk

 

nil А2

I

A1

nil

A1

A2

 

 

 

sp

I

 

 

 

nil Inf

07/02/19

50