Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
attachments_03-09-2012_10-20-12 / Связные списки,стеки, очереди.doc
Скачиваний:
32
Добавлен:
21.05.2015
Размер:
256 Кб
Скачать

Прохождение связного списка

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

var

HeadList, TempNode : PElem;

begin

…….

TempNode:=HeadList; {Для прохождения по списку нельзя использовать адрес первого элемента HeadList, т.к. потеряем весь список}

WhileTempNode<>nildo { пока список не пустой}

begin

Writeln(TempNode^.Data); {печатаем значение в текущем узле}

TempNode:=TempNode^.Next; {переставляем указатель на следующий элемент}

end;

…….

Очистка связного списка тре­бует небольшого изменения алгоритма, чтобы гарантировать, что мы не ссылаемся на поле Next после освобождения узла (типичная ошибка).

var

HeadList, TempNode : PElem;

begin

…….

WhileHeadList<>nildo { Пока список не пустой}

begin

TempNode:=HeadList{запоминаем адрес первого элемента }

HeadList:=HeadList^.Next; {переставляем указатель начала списка на следующий элемент}

Dispose(TempNode); {удаляем предыдущий элемент }

end;

…….

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

Теперь, когда мы научились проходить по узлам связного списка, давайте вер­немся к вопросу, который, наверное, появился у вас пару абзацев назад. А что если нам нужно вставить узел перед заданным узлом? Как это сделать? Единствен­ным решением такой задачи для односвязного списка является прохождение спис­ка и поиск узла, перед которым мы должны вставить новый узел. При прохожде­нии будут использоваться две переменных: одна будет указывать на текущий (This), а вторая на предыдущий узел (Pre). Когда будет найден заданный узел, у нас будет указатель на предыдущий узел, что позволит использовать алгоритм вставки после заданного узла. Вставка нового узла будет происходить между узлами Pre и This. В коде это выглядит следующим образом:

var

HeadList , NewNode, Pre,This : PElem;

Found:Boolean; X, Xnew:integer;

begin

………….

Pre:=nil;

This:=HeadList;

Found:=False; {Место вставки еще не найдено}

While(This<>nil)andnotFounddo{Второе условие – признак окончания поиска при обнаружении позиции вставки, например,This^.data=X. В этом случае вставка нового элемента будет сделана перед элементом со значением, равным Х.}

Begin

Pre:=This;

Found:= This^.data=X;

This:=This^.next;

End;

If Found then

Begin

{Если позиция вставки найдена, то добавляем новый узел между Preи This}

New(NewNode); {выделяем память под новый узел, указатель - NewNode}

NewNode^.Data:=Xnew {заполняем поле Data для нового узла значением Хnew}

Pre^.next:=NewNode; {связываем предыдущий элемент Pre с новым NewNode}

NewNode^.next:=This; {связываем новый элемент NewNode с текущим This }

End;

……

Рис.4 Вставка нового элемента перед заданным узлом.

Работа алгоритма продемонстрирована на Рис.4. Данная вставка не работает, если добавление должно происходить перед первым узлом списка. Для этого необходимо предусмотреть дополнительный код, проверяющий условие This=HeadListилиPre=nil. В этом случае необходимо изменить значение адреса первого узла списка. Например, так

……….

New(NewNode); {выделяем память под новый узел, указатель - NewNode}

NewNode^.Data:=Xnew {заполняем поле Data для нового узла значением Хnew}

NewNode^.next:= HeadList;{связываем новый элемент NewNode с первым HeadList}

HeadList:=NewNode; {связываем первый элемент HeadList с новым NewNode}

……….