Циклический однонаправленный список
Циклический однонаправленный список похож на линейный однонаправленный список, но его последний элемент содержит указатель, связывающий его с первым элементом.
Для полного обхода такого списка достаточно иметь указатель на произвольный элемент, а не на первый, как в линейном однонаправленном списке. Понятие «первого» элемента здесь достаточно условно и не всегда требуется. Хотя иногда бывает полезно выделить некоторый элемент как «первый» путем установки на него специального указателя. Это требуется, например, для предотвращения «зацикливания» при просмотре списка.
Рисунок 4. Циклический однонаправленный список
Основные операции, осуществляемые с циклическим однонаправленным списком:
-
вставка элемента;
-
просмотр
-
поиск;
-
удаление элемента.
Для описания алгоритмов этих основных операций используем те же объявления данных, что и для линейного однонаправленного списка.
Вставка элемента в список, как уже говорилось, проще, чем для линейного однонаправленного списка и реализуется с помощью одной единственной процедуры: Ins_CicleSingleList. В качестве входных параметров передаются данное для заполнения создаваемого элемента, указатель на начало списка и указатель на текущий элемент в списке, после которого осуществляется вставка. Выходными параметрами процедур является указатель на начало списка (который возможно изменится) и указатель текущего элемента, который показывает на вновь созданный элемент.
procedure Ins_CicleSingleList(DataElem: TypeData;
var ptrHead, ptrCurrent: PElement);
{Вставка элемента в циклический однонаправленный список}
{справа от элемента, на который указывает ptrCurrent}
var
ptrAddition: PElement; {вспомогательный указатель}
begin
New(ptrAddition);
ptrAddition^.Data := DataElem;
if ptrHead = nil then begin {список пуст}
{создаем первый элемент списка}
ptrAddition^.Next := ptrAddition; {цикл из 1 элемента}
ptrHead := ptrAddition;
end else begin {список не пуст}
{вставляем элемент списка справа от элемента,}
{на который указывает ptrCurrent}
ptrAddition^.Next := ptrCurrent^.Next;
ptrCurrent^.Next := ptrAddition;
end;
ptrCurrent := ptrAddition;
end;
Порядок следования операторов присваивания процедуры очень важен. При неправильном переопределении указателей возможен разрыв списка или потери указателя на первый элемент, что приводит к потере доступа к части или всему списку.
Операция просмотра списка заключается в последовательном просмотре всех элементов списка. В отличие от линейного однонаправленного списка здесь признаком окончания просмотра списка будет возврат к элементу, выделенным как «первый».
procedure Scan_CicleSingleList(ptrHead: PElement);
{Просмотр циклического однонаправленного списка}
var
ptrAddition: PElement; {вспомогательный указатель}
begin
if ptrHead <> nil do begin {список не пуст}
ptrAddition := ptrHead;
repeat
writeln(ptrAddition^.Data); {Вывод значения элемента}
ptrAddition := ptrAddition^.Next;
until ptrAddition = ptrHead;
end;
end;
Операция поиска элемента в списке заключается в последовательном просмотре всех элементов списка до тех пор, пока текущий элемент не будет содержать заданное значение или пока не достигнут «первый» элемент списка. В последнем случае фиксируется отсутствие искомого элемента в списке (функция принимает значение false). Входными параметрами являются значение, которое должен содержать искомый элемент и указатель на список. В качестве выходного параметра передается указатель, который устанавливается на найденный элемент или остается без изменений, если элемента в списке нет.
function Find_CicleSingleList(DataElem: TypeData;
var ptrHead,
ptrCurrent: PElement): boolean;
{Поиск в циклическом однонаправленном списке}
var
ptrAddition: PElement; {вспомогательный указатель}
begin
if ptrHead <> nil do begin {список не пуст}
ptrAddition := ptrHead;
repeat
ptrAddition := ptrAddition^.Next;
until (ptrAddition = ptrHead) or {прошли весь список}
(ptrAddition^.Data = DataElem) {элемент найден}
if ptrAddition^.Data = DataElem then begin
Find_CicleSingleList := true;
ptrCurrent := ptrAddition;
end else begin
Find_CicleSingleList := false;
end;
end else begin
Find_CicleSingleList := false;
end;
;
end;
Операция удаления элемента циклического однонаправленного списка осуществляет удаление элемента, на который установлен указатель текущего элемента. После удаления указатель текущего элемента устанавливается на следующий за удаляемым элемент списка. Здесь не требуется отдельных алгоритмов удаления для крайних элементов списка, как это было в линейных списках, но в случае удаления «первого» элемента, необходимо соответствующий указатель переместить на следующий элемент.
procedure Del_CicleSingleList(var ptrHead, ptrCurrent: PElement);
{Удаление элемента из циклического однонаправленного списка}
var
ptrAddition: PElement; {дополнительный указатель}
begin
if ptrCurrent <> nil then begin {вх.параметр корректен}
if ptrHead^.Next <> ptrHead then begin
{Если удаляемый элемент не единственный в списке}
{Устанавливаем вспомогательный указатель на элемент,
предшествующий удаляемому}
ptrAddition := ptrHead;
while ptrAddition^.Next <> ptrCurrent do
ptrAddition := ptrAddition^.Next;
{непосредственное удаление элемента}
ptrAddition^.Next := ptrCurrent^.Next;
if ptrHead = ptrCurrent then {удаляем первый}
ptrHead := ptrCurrent^.Next;
dispose(ptrCurrent);
ptrCurrent := ptrAddition^.Next;
end else begin
ptrHead:=nil;
dispose(ptrCurrent);
ptrCurrent:=nil;
end;
end;
end;
Циклический однонаправленный список, так же как и линейный однонаправленный список имеет только один указатель в элементах, что позволяет минимизировать расход памяти на организацию списка, но обеспечивает переходы между элементами только в одном направлении. Одновременно, здесь упрощены операции вставки и удаления элементов.
Для ускорения доступа к элементам списка путем применения переходов между элементами в обоих направлениях в циклических списках применяют тот же подход, что и в линейных списках: циклический двунаправленный список.
- Содержание
- Основные сведения
- Понятия алгоритма и структуры данных
- Анализ сложности и эффективности алгоритмов и структур данных
- Структуры данных
- Элементарные данные
- Данные числовых типов
- Данные целочисленного типа
- Данные вещественного типа
- Операции над данными числовых типов
- Данные символьного типа
- Данные логического типа
- Данные типа указатель
- Линейные структуры данных
- Множество
- Линейные списки
- Линейный однонаправленный список
- Линейный двунаправленный список
- Циклические списки
- Циклический однонаправленный список
- Циклический двунаправленный список
- Разреженные матрицы
- Матрицы с математическим описанием местоположения элементов
- Матрицы со случайным расположением элементов
- Очередь
- Нелинейные структуры данных
- Мультисписки
- Слоеные списки
- Спецификация
- Реализация
- Деревья
- Общие сведения
- Обходы деревьев
- Спецификация двоичных деревьев
- Реализация
- Основные операции
- Организация
- Представление файлов b-деревьями
- Основные операции
- Общая оценка b-деревьев
- Алгоритмы обработки данных
- Методы разработки алгоритмов
- Метод декомпозиции
- Динамическое программирование
- Поиск с возвратом
- Метод ветвей и границ
- Метод альфа-бета отсечения
- Локальные и глобальные оптимальные решения
- Алгоритмы поиска
- Поиск в линейных структурах
- Последовательный (линейный) поиск
- Бинарный поиск
- Хеширование данных
- Функция хеширования
- Открытое хеширование
- Закрытое хеширование
- Реструктуризация хеш-таблиц
- Поиск по вторичным ключам
- Инвертированные индексы
- Битовые карты
- Использование деревьев в задачах поиска
- Упорядоченные деревья поиска
- Случайные деревья поиска
- Оптимальные деревья поиска
- Сбалансированные по высоте деревья поиска
- Поиск в тексте
- Прямой поиск
- Алгоритм Кнута, Мориса и Пратта
- Алгоритм Боуера и Мура
- Алгоритмы кодирования (сжатия) данных
- Общие сведения
- Метод Хаффмана. Оптимальные префиксные коды
- Кодовые деревья
- Алгоритмы сортировки
- Основные сведения. Внутренняя и внешняя сортировка
- Алгоритмы внутренней сортировки
- Сортировка подсчетом
- Сортировка простым включением
- Сортировка методом Шелла
- Сортировка простым извлечением.
- Древесная сортировка
- Сортировка методом пузырька
- Быстрая сортировка (Хоара)
- Сортировка слиянием
- Сортировка распределением
- Сравнение алгоритмов внутренней сортировки
- Алгоритмы внешней сортировки
- Алгоритмы на графах
- Алгоритм определения циклов
- Алгоритмы обхода графа
- Поиск в глубину
- Поиск в ширину (Волновой алгоритм)
- Нахождение кратчайшего пути
- Алгоритм Дейкстры
- Алгоритм Флойда
- Переборные алгоритмы
- Нахождение минимального остовного дерева
- Алгоритм Прима
- Алгоритм Крускала
- 190000, Санкт-Петербург, ул. Б. Морская, 67