
- •Указатели и динамическая память
- •Объявление указателей
- •Выделение и освобождение динамической память
- •Процедуры и функции для работы с динамической памятью
- •Динамические структуры данных Связные списки, стеки и очереди
- •Односвязные (однонаправленные)списки
- •Узлы связного списка
- •Создание односвязного списка
- •Вставка и удаление элементов в односвязном списке
- •Прохождение связного списка
- •Соображения по поводу эффективности
- •Двухсвязные списки
- •Соображения по поводу эффективности
- •Очередь
Узлы связного списка
Перед началом описания операций со связным списком давайте рассмотрим, как каждый узел списка будет представляться в памяти. Знание структуры узла позволит нам более детально рассматривать основные операции со связными списком. Структура узла списка, не использующего классы и объекты, выглядит следующим образом:
type
SomeDataType=integer;
PSimpleNode = ^TSimpleNode;
TSimpleNode = record
Next : PSimpleNode;
Data : SomeDataType;
end;
Тип PSimpleNode представляет собой указатель на запись TSimpleNode, поле Next которой содержит ссылку на точно такой же узел, а поле Data - сами данные. В приведенном примере тип данных узла задан как SomeDataType. Для перехода по ссылке нужно написать примерно следующий код:
var
NextNode, CurrentNode : PSimpleNode;
begin
• • •
NextNode : = CurrentNode^.Next;
Создание односвязного списка
Это тривиальная задача. В самом простом случае первый узел в связном списке описывает весь список. Первый узел иногда называют головой списка.
var
MyLinkedList : PSimpleNode;
Если MyLinkedList содержит nil, списка еще нет. Таким образом, это начальное значение связного списка.
{инициализация связного списка}
MyLinkedList :=nil;
Вставка и удаление элементов в односвязном списке
А каким образом можно вставить новый элемент в связный список? Или удалить? Оказывается, что для выполнения этих операций требуется выполнить небольшую работу с указателями.
Для односвязного списка существует только один вариант вставки - после заданного элемента списка. Нужно установить так, чтобы указатель Next нашего нового узла указывал на узел после заданного, а указатель Next заданного узла - на наш новый узел. В коде это выглядит следующим образом:
procedure InsertNode(GivenNode: PSimpleNode; D: SomeDataType);
var
NewNode : PSimpleNode;
begin
New(NewNode);
NewNode^.Data:=D; { задать значение поля Data}
NewNode ^. Next : = GivenNode ^. Next ;
GivenNode ^. Next : = NewNode;
end;
Рисунок 3.2. Вставка нового узла в односвязный список
Аналогично, для удаления простейшим вариантом является удаление элемента, находящегося после заданного узла. В этом случае мы устанавливаем, чтобы указатель Next заданного узла указывал на узел, расположенный после удаляемого. После этого удаляемый узел уже выделен из списка и может быть освобожден. В коде это выглядит следующим образом:
procedure DeleteNode(GivenNode: PSimpleNode);
var
NodeToGo : PSimpleNode;
begin
NodeToGo : = GivenNode^.Next;
GivenNode^.Next : = NodeToGo^.Next;
Dispose(NodeToGo);
end;
Рисунок 3.3. Удаление узла из односвязного списка
Тем не менее, в списках без заглавного звена, для обеих операций существует специальный случай: вставка перед первым элементом списка (т.е. новый элемент становиться первым) и удаление первого элемента списка (т.е. первым становится другой элемент). Поскольку в наших рассуждениях первый элемент считается определяющим узлом всего списка, код для этих случаев нужно написать отдельно. Вставка перед первым узлом будет выглядеть следующим образом:
procedure InsertFirstNode(var MyLinkedList : PSimpleNode; D: SomeDataType);
var
NewNode : PSimpleNode;
begin
New(NewNode);
NewNode^.Data:=D; { задать значение поляData}
NewNode^.Next : = MyLinkedList;
MyLinkedLis t: = NewNode ;
end;
а удаление будет выглядеть так:
procedure DeleteFirstNode(var MyLinkedList : PSimpleNode);
var
NodeToGo : PSimpleNode;
begin
NodeToGo : = MyLinkedList; {GivenNode^.Next;}
MyLinkedList: = NodeToGo^. Next;
Dispose(NodeToGo);
end;
Обратите внимание, что код вставки элемента будет работать даже в случае, когда исходный список пуст, т.е. содержит nil, а код удаления элемента правильно установит содержимое связного списка в случае удаления из него последнего узла.