Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Shpora_po_programmirovaniyu_k_ekzamenu_33_1.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
573.95 Кб
Скачать

Билет 55. Рекурсивная обработка списка.

Рекурсивное определение списка: список м.б. либо пустым, либо состоять из узла, содержащего ссылку на список. Структура рекурсивных процедур обработки списков будет соответствовать определению в том смысле, что процедура будет содержать условный оператор, одна ветвь которого соответствует обработке пустого списка, а другая обрабатывает информацию, содержащуюся в одиночном узле. Для обработки оставшейся части списка процедура рекурсивно обращается сама к себе.

Пр. 2 рекурсивные процедуры: 1 для чтения последовательности символов, др. для печати их в исходном порядке.

program CopyList;

type link = ^node;

node = record

data: char;

next: link end;

var head: link;

procedure AddToList (var p: link);

begin if p=nil then

begin new(p);

p^.next := nil;

read(p^.data); end

else AddToList (p^.next);

end;

procedure PrintList (p: link);

begin if p<>nil then

begin write(p^.data); PrintList (p^.next) end;

end;

BEGIN

head := nil;

while not eof do AddToList (head);

PrintList (head);

END.

Билет 56. Двусвязные кольца.

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

type link = record

next, before: link; {ссылки на следующую и предыдущую компоненты}

data: datatype end;

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

Если мы определим пустое кольцо, как кольцо, состоящее из фиктивной компоненты, ссылающейся сама на себя, процедура обработки кольца заметно упростится.

Вставка объекта NewNode после объекта OldNode.

procedure InsertAfter (NewNode, OldNode: link);

begin NewNode^.Next:= OldNode^.Next;

NewNode^.Before:= OldNode;

OldNode^.Next^.Before:= NewNode;

OldNode^.Next:= NewNode

end;

Вставка объекта NewNode перед объектом OldNode.

procedure InsertBefore (NewNode, OldNode: link);

begin NewNode^.Next:= OldNode;

NewNode^.Before:= OldNode^.Before;

OldNode^.Before^. Next:= NewNode;

OldNode^.Before:= NewNode

end;

Удаление из списка узла CurNode.

procedure DeleteNode (CurNode: link);

begin NewNode^.Next:= OldNode;

NewNode^.Before:= OldNode^.Before;

OldNode^.Before^. Next:= NewNode;

OldNode^.Before:= NewNode

end;

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

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

Просмотр кольца несколько отличается от просмотра списка, необходимо только помнить то место, откуда мы начали.

Пример. Cur:=Start^.Next;

While Cur<>Start do

begin Smth {оператор}

………

Cur:=Cur^.Next

end;

Оператор Smth будет выполнятся по одному разу для каждой компоненты кольца. В момент выполнения оператора переменная Cur будет указывать на текущую компоненту. Оператор Smth не будет выполняться если кольцо пусто. Если вместо переменной Next использовать переменную Before, просмотр кольца будет идти в обратном направлении.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]