Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Структуры и алгоритмы / Типы и структуры данных

.pdf
Скачиваний:
153
Добавлен:
23.02.2015
Размер:
451.95 Кб
Скачать

Другие возможные операции над очередью – проверка текущей длины и очистка.

Из рис. 11 ясно, что рано или поздно наступит переполнение очереди. Это может случиться независимо от того, исключались или нет элементы из очереди, так как переполнение означает выход указателя Р2 за пределы отведенного для слотов очереди участка памяти. Такой недостаток схемы можно устранить, если после достижения указателем слота с адресом Amax переводить этот указатель на слот с адресом A1, при условии, что он пуст. Такая очередь называется кольцевой и представлена на рис. 12.

A1

A2

. . .

 

 

Amax

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

P2

P1

Рис. 12. Кольцевая очередь

В ней возможно любое из соотношений:

P1 < P2 , P1 = P2, P1 > P2,

причем второе из этих соотношений соответствует пустой очереди.

Физическая структура очереди представлена на рис. 13. Имя и другая информация об очереди хранятся в дескрипторе, причем каждая очередь имеет свой признак или код.

23

Дескриптор

Q Имя очереди

Адрес верхней границы

Указатель головы

Указатель хвоста

Адрес нижней границы

Описание элемента

Слоты для элементов очереди

Рис. 13. Физическая структура очереди

Алгоритм включения элемента в кольцевую очередь

Пусть информация о включаемом элементе находится в записи DATA. Слоты очереди имеют адреса в диапазоне от A1 до Amax. Причем каждый слот занимает К единиц памяти. P1 - указатель головы, P2 – указатель первого свободного слота в очереди (хвост).

В исходном состоянии очередь может быть пуста. При этом

P1 = P2 = A1.

1.Достигнут ли последний слот? Если P2 = Amax, то идти к шагу 5.

2.Проверка заполненности очереди. Если P2 + К = P1, то установить код ошибки равным единице и завершить выполнение алгоритма (элемент в очередь не включен).

3.Включение нового элемента. Занести информацию из записи DATA в слот очереди, адресуемой указателем P2.

24

4.Модификация указателя. Установить P2 = P2 + К и закончить алгоритм.

5.Проверка заполненности очереди. Если P1 = A1, то установить код ошибки равным единице и завершить алгоритм.

6.Включение элемента. Занести информацию из записи DATA в слот, адресуемый указателем P2.

7.Модификация указателя. Установить P2 = A1 и завершить алгоритм.

Алгоритм исключения элемента из кольцевой очереди

Этот алгоритм предназначен для исключения элементов из кольцевой очереди. Информация об исключаемом элементе из слота помещается в запись DATA.

1.Проверка отсутствия элементов в очереди. Если P1 = P2, то установить код ошибки равным единице и завершить алгоритм (очередь пуста).

2.Извлечение информации об элементе. Прочитать данные из слота, адресуемого указателем головы P1, и поместить их в запись DATA.

3.Переключение указателя головы на первый слот очереди. Если P1 = Amax, то установить P1 = A1 и завершить алгоритм.

4.Перемещение указателя головы на один слот вперед. Установить P1 = P1 + К и закончить выполнение алгоритма.

2.3.3. Деки

Особым типом списка является дек. Его название произошло от английского слова deque – double-ended queue – очередь с двумя концами.

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

Примером дековой структуры может являться схема железнодорожного разъезда, представленная на рис. 14.

25

Путь А

Вход

Выход

Д

Д - Дековый участок

Путь В

Рис. 14. Схема железнодорожного разъезда, иллюстрирующая структуру дека

Частным случаем дека является дек с ограниченным входом и дек с ограниченным выходом. На схеме дек с ограниченным входом получится, если закрыть путь А. Дек с ограниченным выходом получится, если закрыть путь В.

Логическая и физическая структуры дека соответствуют логической и физической структурам очереди, но вместо терминов «хвост» и «голова» применяются термины «левый» и «правый» конец.

Важнейшими операциями над деком, как и над простой очередью, являются операции включения и исключения элементов. Они представляют собой развитие и обобщение соответствующих операций с очередью.

Одним из параметров операций доступа к деку должен быть признак того конца (левого или правого), с которого должна выполняться соответствующая операция.

2.4. Линейные динамические структуры

Динамическая структура характеризуется следующими свойствами:

1.Непостоянство и непредсказуемость размера (числа элементов) структуры в процессе ее обработки. Число элементов динамической структуры может изменяться от

26

нуля до некоторого значения, определяемого спецификой задачи или доступным объемом памяти.

2.Отсутствие физической смежности элементов структуры в памяти.

Логическая последовательность элементов задается в явном виде с помощью одного или нескольких указателей или связок, хранящихся в самих элементах. Из-за отсутствия физической смежности элементов память, занимаемая структурой, не представляет собой непрерывную область, то есть элементы динамической структуры могут быть разбросаны в памяти хаотическим образом. Следовательно, неизбежно усложнение процедур доступа к элементам динамической структуры по сравнению со статическими и полустатическими структурами.

Часто динамические структуры представляются в форме связных списков. Связный список – это такая структура, элементами которой служат записи с одним и тем же форматом, связанные друг с другом с помощью указателей, хранящихся в самих элементах.

Простейшими связными списками являются линейные связные списки – односвязный и двусвязный.

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

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

Линейность односвязного списка следует из линейной логической упорядоченности его элементов: для каждого элемента (кроме первого и последнего) имеются единственный предыдущий и единственный последующий элементы.

Логическая структура односвязного списка представлена на рис. 15.

27

 

Часть логической структуры

Указатель начала списка

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

 

 

Указатель

 

Указатель

 

 

 

 

 

 

Указатель

 

 

 

 

 

 

 

 

 

Данные

 

Данные

 

Данные

 

Данные

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рис. 15. Логическая структура односвязного списка

Физическая структура односвязного списка представляет собой совокупность дескриптора и одинаковых по размеру и формату записей, размещенных произвольно в некоторой области памяти и связанных друг с другом в линейно упорядоченную цепочку с помощью указателей. Таким образом, физическая смежность элементов связного списка в памяти не требуется, причем между элементами одного списка в памяти могут находиться элементы других списков.

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

Из рассмотрения логической структуры односвязного списка видно, что для доступа к желаемому элементу необходимо просматривать список в общем случае с его начала. Это замедляет операции доступа к элементам в односвязном списке.

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

Логическая структура кольцевого односвязного списка представлена на рис. 16.

28

 

 

Указатель начала списка

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Указатель

 

Указатель

 

 

Указатель

 

 

Указатель

 

 

 

 

 

 

 

 

 

 

 

 

Данные

 

Данные

 

 

Данные

 

 

Данные

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рис. 16. Логическая структура кольцевого односвязного списка

Часто при просмотре линейного списка возникает необходи мость продвижения в любом из двух направлений по цепочке элементов.

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

Логическая структура линейного двусвязного списка представлена на рис. 17. Наличие двух указателей в каждом элементе усложняет список и приводит к дополнительным затратам памяти, но обеспечивает более эффективное выполнение операций над списком.

 

Указатель начала списка

 

 

Указатель конца списка

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Прямой

 

Прямой

 

 

Прямой

 

 

указатель

 

указатель

 

 

указатель

 

 

 

 

 

Обратный

 

 

Обратный

 

Обратный

 

 

 

указатель

 

 

указатель

 

указатель

 

 

 

 

 

 

 

 

 

 

Данные

 

Данные

 

 

Данные

 

Данные

 

 

 

 

 

 

 

 

 

 

 

Рис.17. Логическая структура линейного двусвязного списка из четырех элементов

29

 

Указатель начала списка

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Прямой

 

Прямой

 

 

Прямой

 

Прямой

указатель

 

указатель

 

 

указатель

 

указатель

Обратный

 

Обратный

 

 

Обратный

 

Обратный

указатель

 

указатель

 

 

указатель

 

указатель

 

 

 

 

 

 

 

 

Данные

 

Данные

 

 

Данные

 

Данные

 

 

 

 

 

 

 

 

 

Рис.18. Кольцевой двусвязный список из четырех элементов

Из описанного двусвязного списка может получиться кольцевой (рис.18).

Одними из основных операций над списком являются включение элемента в список и исключение элемента из списка.

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

Следует отметить, что в двусвязных списках обе операции усложняются, так как необходимо модифицировать не один, а два указателя в соответствующих элементах.

Операция включения элемента в список

Суть этой операции заключается в том, что в поле связки включаемого элемента заносится содержимое поля связки того элемента, вслед за которым в списке должен быть включен новый элемент (PNTER). Тем самым устанавливается связь включаемого

30

элемента со следующим за ним элементом списка. Затем в поле связки элемента, вслед за которым включается новый элемент, заносится значение указателя нового элемента (NEW). В результате устанавливается связь нового элемента с предыдущим в списке элементом (рис.19).

DATA

LINK

 

DATA

LINK

 

DATA

LINK

 

DATA

 

 

 

 

 

 

 

 

 

 

 

 

START

PNTER

DATA LINK

 

Рис.19. Схема включения нового элемента в односвязный список

Последовательность действий может быть такой:

1.Формирование поля связки нового элемента. LINK(NEW) = LINK(PNTER)

2.Модификация поля связки предыдущего элемента.

LINK(PNTER) = NEW.

Операция удаления элемента из списка

DATA

LINK

 

DATA

LINK

 

DATA

LINK

 

DATA

 

 

 

 

 

 

 

 

 

 

 

 

START

 

PNTER

PTR

 

Рис. 20. Схема удаления элемента из односвязного списка

Пусть исключению из списка подлежит элемент, который следует за элементом, адресуемым указателем PNTER (рис.20).

31

1.Некоторому вспомогательному указателю PRT присваиваем содержимое поля связки элемента, который адресуется указателем PNTER. PTR = LINK(PNTER).

2.В поле связки элемента, адресуемого указателем PNTER, помещается содержимое поля связки удаляемого элемента. LINK(PNTER) = LINK(PTR).

2.5. Нелинейные связные структуры

Односвязный список всегда линеен. Двусвязный список может быть как линейным, так и нелинейным.

Если второй указатель каждого элемента списка задает порядок произвольного вида, не являющийся обратным по отношению к порядку, устанавливаемому первым указателем, то такой двусвязный список называется нелинейным (рис.21).

Каждый элемент такого обобщенного двусвязного списка содержится одновременно в двух разных односвязных списках.

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

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

Такой многосвязный список как бы «прошит» в разных направлениях многими связками. Поэтому многосвязные списки иногда называют прошитыми списками, или плексами.

32