- •Тема 1. Стеки, очереди, деки 7
- •Тема 2. Односвязные и двусвязные линейные списки 21
- •Тема 3. Бинарные деревья 40
- •Тема 4. Графы 65
- •Введение
- •Терминология
- •Классификация структур данных по различным признакам
- •Типовые операции над структурами данных
- •Эффективность алгоритмов. O-обозначения
- •Тема 1. Стеки, очереди, деки
- •Операции над стеком
- •Реализация стека
- •Реализация основных операций над стеком
- •Использование стека для преобразования форм записи выражений.
- •Очередь
- •Операции над очередью
- •Операции над деком
- •Реализация очереди и дека
- •Реализация основных операций над очередью и деком
- •Итератор
- •Лабораторная работа 1. Стеки, очереди, деки
- •Тема 2. Односвязные и двусвязные линейные списки
- •Линейный список
- •Операции над линейным списком
- •Реализация линейного списка в виде односвязной динамической структуры
- •Реализация основных операций над односвязным списком
- •Циклический список
- •Операции над циклическим списком
- •Односвязная реализация циклического списка
- •Реализация основных операций над односвязным циклическим списком
- •Реализация линейного списка в виде двусвязной динамической структуры
- •Реализация основных операций над двусвязным списком
- •Циклический двусвязный список
- •Реализация основных операций над двусвязным циклическим списком
- •Лабораторная работа 2. Односвязные и двусвязные линейные списки
- •Тема 3. Бинарные деревья
- •Основные понятия и определения
- •Построение бинарного дерева
- •Операции над бинарным деревом
- •Реализация бинарного дерева
- •Реализация основных операций над бинарным деревом
- •Дерево выражения
- •Дерево поиска
- •Операции над деревом поиска
- •Реализация дерева поиска
- •Реализация операций над деревом поиска
- •Сбалансированные деревья
- •Включение в сбалансированное дерево
- •Лабораторная работа 3. Бинарные деревья
- •Тема 4. Графы
- •Основные понятия и определения
- •Граф g7
- •Операции над графом
- •Реализация графа
- •Реализация основных операций над ориентированным графом
- •Обход ориентированного графа
- •Вычисление расстояния между узлами ориентированного графа
- •Лабораторная работа 4. Ориентированные графы
- •Библиографический список
-
Циклический двусвязный список
Так же, как и односвязный, двусвязный список может быть циклическим. Для двусвязного циклического списка отпадает необходимость хранения внешнего указателя на последний элемент списка, так как фактически он является элементом, расположенным слева от первого:
Над циклическим двусвязным списком могут быть выполнены все операции, определенные для циклического односвязного списка.
Класс tDCCircleList может быть описан следующим образом:
type
tDCCircleList=class // класс - циклический двусвязный список
protected
fHead: pItem; // поле - указатель на начало списка
fSize: Word; // поле - число элементов списка
public
// Свойство - число элементов списка (доступ по чтению и записи)
property Size: Word read fSize write fSize;
// Свойство - указатель на начало списка (доступ по чтению и записи)
property Head: Word read fHead write fHead;
// Включение элемента со значением v справа от элемента с адресом Addr
procedure InsertRight(Addr: pItem; v: tValue);
// Включение элемента со значением v слева от элемента с адресом Addr
procedure InsertLeft(Addr: pItem; v: tValue);
// Исключение элемента справа от элемента с адресом Addr
function DeleteRight(Addr: pItem): tValue;
// Исключение из списка элемента с адресом Addr
function Delete(Addr: pItem): tValue;
// Включение элемента со значением v в начало списка
procedure InsertHead(v: tValue);
// Включение элемента со значением v в конец списка
procedure InsertRear(v: tValue);
function DeleteHead: tValue; // исключение из начала
function DeleteRear: tValue; // исключение из конца
// Возвращение адреса элемента со значением v
function Search(v: tValue): pItem;
function Empty: Boolean; // возвращение true, если список пуст
procedure Clear; // очистка списка
// Присоединение списка DCList2 справа
procedure Concat(var DCList2: tDCCircleList);
constructor Create; // конструктор - создание пустого списка
destructor Destroy; override; // деструктор - удаление списка
end; // tDCCircleList
Класс tDCCircleList не является в данном описании наследником класса tDCList по следующим причинам:
– поле Rear класса tDCList не используется;
– вводится новая процедура Concat;
– все методы класса tDCCircleList реализуются иначе, чем одноименные методы класса tDCList.
-
Реализация основных операций над двусвязным циклическим списком
В этом разделе рассмотрим только новые для двусвязного циклического списка операции, реализацию методов, одноименных с методами класса tDCList, предлагается выполнить самостоятельно.
Метод класса tDCCircleList, реализующий включение элемента в конец двусвязного циклического списка, имеет вид:
procedure tDCCircleList.InsertRear(v: tValue);
var
NewItem: pItem; // указатель на новый элемент
begin
NewItem:= New(pItem);
NewItem^.Value:= v;
if Empty
then begin // включение в пустой список
NewItem^.Left:= NewItem;
NewItem^.Right:= NewItem;
fHead:= NewItem; end
else begin // включение в непустой список
NewItem^.Left:= fHead^.Left;
NewItem^.Right:= fHead;
fHead^.Left^.Right:=NewItem;
fHead^.Left:=NewItem;
end;
Inc(fSize); // увеличение числа элементов списка на 1
end; // procedure tDCCircleList.InsertRear
Включение элемента в начало двусвязного циклического списка. При реализации этой операции можно использовать следующий прием: включить элемент в конец, а затем перенести указатель fHead на стоящий слева от него включенный элемент.
procedure tDCCircleList.InsertHead(v: tValue);
begin
InsertRear(v); // включение элемента в конец
fHead:= fHead^.Left;
end; // procedure tDCCircleList.InsertHead
Метод класса tDCCircleList, реализующий исключение элемента из конца двусвязного циклического списка, имеет вид:
function tDCCircleList.DeleteRear: tValue;
var
DisItem: pItem;
begin
DisItem:= fHead^.Left; // исключаемый элемент - последний
DeleteLast:= DisItem^.Value; // чтение последнего элемента списка
if fHead=DisItem
then fHead:=nil // исключается единственный элемент
else begin
fHead^.Left:= DisItem^.Left;
DisItem^.Left^.Right:=fHead; // последним становится предпоследний эл-т
end;
Dispose(DisItem);
Dec(fSize); // уменьшение числа элементов на 1
end; // function tDCCircleList.DeleteRear
Исключение элемента из начала двусвязного циклического списка. При реализации этой операции сначала указатель первого элемента списка fHead передвигается на элемент, стоящий справа от него – бывший первый элемент (который и нужно исключить) становится последним. Его можно исключить из списка с использованием метода исключения справа DeleteRear. Метод класса tCDCircleList, реализующий исключение элемента слева, имеет вид:
function tDCCircleList.DeleteHead: tValue;
begin
fHead:= fHead^.Right;
DeleteHead:= DeleteRear;
end; // function tDCCircleList.DeleteHead
Операции исключения элементов из двусвязного списка DeleteFirst и DeleteLast неприменимы к пустому списку, поэтому перед их выполнением необходимо анализировать значение признака «список пуст».