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

Узлы связного списка

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

type

PElem = ^Elem; {Указатель на элемент списка}

Elem = record {Элемент списка - запись}

Data : TdataType; {Данные, хранящиеся в узле списка (тип - любой) }

Next : PElem; {Указатель на следующий элемент списка}

end;

Тип PElem представляет собой указатель на запись Elem, поле Next которой содержит ссылку на точно такой же узел, а поле Data - сами дан­ные. В приведенном примере тип данных узла задан как TdataType, и должен быть описан пользователем заранее (например, для хранения в списке целых чисел можно записать Type TdataType=Integer). Для перехода по ссылке на следующий элемент нужно написать примерно следующий код:

var

NextNode, CurrentNode : PElem; {где CurrentNode – указатель на текущий элемент,

NextNode – указатель на следующий элемент}

begin

…..

NextNode : = CurrentNode^.Next;

Обращения к данным, находящимся в узле списка с адресом CurrentNode, будет записано так: CurrentNode^.Data:=5; или writeln(CurrentNode^.Data);

Создание односвязного списка

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

Var HeadList : PElem;

Если HeadList содержит nil, списка еще нет. Таким образом, это начальное значение связного списка. Для определенности, в начале программы указателю на начало списка необходимо присвоить значение nil.

HeadList:=nil {инициализация связного списка}

Вставка и удаление элементов в односвязном списке

Каким образом можно вставить новый элемент в связный список? Или удалить? Оказывается, что для выполнения этих операций требуется выполнить небольшую работу с указателями. Для односвязного списка существует только один вариант вставки - после заданного элемента списка. Нужно установить ссылки так, чтобы указатель Nextнашего нового узла указывал на узел после заданного, а указательNextзаданного узла - на наш новый узел. В коде это выглядит следующим образом:

var

GivenNode, NewNode : PElem; { GivenNode – указатель на заданный узел}

begin

New(NewNode);

Newnode^.Data:=15 ; {задаем значение поля Data}

NewNode ^. Next := GivenNode ^. Next ;

GivenNode ^. Next : = NewNode;

Рис.2 Вставка нового узла в односвязный список.

Аналогично, для удаления простейшим вариантом является удаление элемента, находящегося после заданного узла (GivenNode). В этом случае мы устанавливаем, чтобы указатель Next заданного узла указывал на узел, расположенный после удаляемого. После этого удаляемый узел уже выделен из списка и может быть освобожден. В коде это выглядит следующим образом:

var

GivenNode, NodeToGo : PElem

begin

………………

NodeToGo := GivenNode^.Next;

GivenNode^.Next := NodeToGo^.Next; {b}

Dispose(NodeToGo); {c}

Указатель NodeToGo – используется как вспомогательный.

Рис.3 Удаление узла из односвязного списка

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

var

HeadList , NewNode : PElem;

begin

………….

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

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

NewNode^.Next : = HeadList; {связываем новый узел с первым элементом – головой списка}

HeadList: = NewNode ; {список начинается с нового элемента}

………….

а удаление будет выглядеть так:

var

HeadList, TempNode : PElem;

begin

…….

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

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

Dispose(TempNode); {освобождаем память, занимаемую бывшим первым элементом }

……………………

Обратите внимание, что код вставки элемента будет работать даже в случае, когда исходный список пуст, т.е. содержит nil (HeadList = nil, после вставки будет создан первый и единственный элемент списка), а код удаления элемента правильно установит указатель на начало связного списка HeadList в nil, если происходит удаление последнего узла.