Студопедия — Основы теории. Очередь — это линейный список информации, работа с которой происходит по принципу "первым пришел — первым вышел" (first-in
Студопедия Главная Случайная страница Обратная связь

Разделы: Автомобили Астрономия Биология География Дом и сад Другие языки Другое Информатика История Культура Литература Логика Математика Медицина Металлургия Механика Образование Охрана труда Педагогика Политика Право Психология Религия Риторика Социология Спорт Строительство Технология Туризм Физика Философия Финансы Химия Черчение Экология Экономика Электроника

Основы теории. Очередь — это линейный список информации, работа с которой происходит по принципу "первым пришел — первым вышел" (first-in






Очередь — это линейный список информации, работа с которой происходит по принципу " первым пришел — первым вышел" (first-in, first-out); этот принцип (и очередь как структура данных) иногда еще называется FIFO. Это значит, что первый помещенный в очередь элемент будет получен из нее первым, второй помещенный элемент будет извлечен вторым и т.д. Это единственный способ работы с очередью; произвольный доступ к отдельным элементам не разрешается.

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

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

указатель головы
а
указатель хвоста
А
б
указатель головы
указатель хвоста
в
В
указатель хвоста
А
указатель головы
В
указатель головы
указатель хвоста
г

Рисунок 1 - Очередь с указателями головы и хвоста: a – пустая очередь; б – после добавления записи А; в – после добавления записи В; г – после удаления записи А

 

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

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

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

указатель хвоста
А
В
С
указатель головы
а
б
С
D
E
F
указатель головы
указатель хвоста
указатель головы
указатель хвоста
E
F
G
H
в

Рисунок 2 – Очередь, «ползающая» по памяти: а – очередь с записями А, В и С; б – очереди после добавления D, E и F и удаления A и B; в – вид очереди после добавления G и H и удаления C и D

 

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

Этот способ реализации называется циклической очередью (circularqueue), так как образуется цикл из ячеек памяти, выделенных для очереди (рис. 3). С точки зрения этой очереди последняя ячейка в блоке соседствует с первой.

 

последняя ячейка блока
указатель хвоста
указатель головы
первая ячейка блока
N
O
G
F
H
I
J
K
L
M
Очередь перемещается в этом направлении
б
а
M
L
K
J
I
H
указатель хвоста
указатель головы
Очередь перемещается в этом направлении
последняя ячейка блока
первая ячейка блока
N
O
F
G

Рисунок 3 – Фактическое устройство циклической очереди, содержащей буквы от F до O (а) и ее абстрактное представление, где последняя ячейка блока «граничит» с первой (б)

 

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

Создание очереди описано на псевдокоде

1. r = new (node); //создание нового узла очереди

(*r).elem = Элем; // указатель на первый

//элемент очереди

(*r).sled = NULL; //указатель на следующий

//пустой узел

Рисунок 4 - Первый элемент в очереди

2. no = r; // указатель на начало очереди

ko = r; // указатель на конец очереди


Рисунок 5 - Настройка указателей начала и конца очереди

Итак, мы образовали очередь, состоящую из одного звена.

3. Продолжим заполнение очереди:

r = new (node); // создание еще одного узла

(*r).elem = Элем1; // указатель на первый элемент

(*r).sled = NULL; // указатель на

//следующий(пустой) узел

Рисунок 6 - Создание нового элемента очереди

4. Настроим указатель на конец очереди:

(*ko).sled = r; // указатель на второй узел

ko = r; // указатель на конец очереди

Рисунок 7 – Настройка указателя на конец очереди

Таким образом, очередь уже содержит два звена, таков принцип построения и далее.

Представим описанный алгоритм в виде функции на языке C++:

void POSTROENIE (node *no, node *ko)

// Построение очереди на базе однонаправленного

// линейного списка без заглавного звена:

// *no - указатель на начало очереди,

// *ko - указатель на конец очереди.

{ //открытие тела функции POSTROENIE

node *r; // указатель начала очереди

intel; // целочисленная переменная вводимых элементов

// очереди

cin> > el; // ввод элемента

if (el! =0) // в случае если введено ‘0’

{ // начало if

r = new (node); // создание узла

(*r).elem = el; // указатель на последний введенный

// элемент

(*r).sled = NULL; // указатель на пустой узел

*no = r; //указатель начала очереди равен

//последнему созданному узлу

*ko = r; //указатель хвоста очереди равен последнему

//созданному узлу

cin> > el; // ввод следующего элемента

while (el! =0) // пока он не равен нулю делаем

 

{ // открытие wile

r = new (node); // создание узла

(*r).elem = el; // указатель на последний введенный

// элемент

(*r).sled = NULL; // указатель на пустой узел

(*ko).sled = r;; // присвоение указателя очереди началу

// нового звена

*ko = r; // конец очереди это созданное звено

cin> > el; // ввод следующего элемента

}// закрытие wile

} // завершение if

else // условный оператор иначе

{ r = NULL; *no = r; *ko = r; } // производим

//обнуление указателей

} //закрытие тела функции POSTROENIE

Тут же приведем функцию для просмотра содержимого очереди:

void VYVOD (node *no, node *ko)

// Вывод содержимого очереди.

// *no - указатель на начало очереди,

// *ko - указатель на конец очереди.

{ //открытие тела функции VYVOD

node *r; // указатель начала очереди

cout< < " Очередь: "; // Вывод строки на дисплей

r = *no; // узел очереди это ее начало

while (r! =NULL) // делаем пока не дойдем до конца

//очереди

{ // открытие wile

cout< < (*r).elem< < " "; // вывод элементов очереди

r = (*r).sled; //присвоение узлу очереди следующего

//элемента

} // закрытие wile

cout< < endl; //возврат каретки

}//закрытие тела функции VYVOD

 

Замечание. Очереди целесообразно хранить в памяти ЭВМ в виде кольцевого списка с двумя указателями (один - на начало, другой - на конец очереди):

Рисунок 8 - Представление очереди

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

 







Дата добавления: 2014-11-10; просмотров: 680. Нарушение авторских прав; Мы поможем в написании вашей работы!



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

ТЕОРЕТИЧЕСКАЯ МЕХАНИКА Статика является частью теоретической механики, изучающей условия, при ко­торых тело находится под действием заданной системы сил...

Теория усилителей. Схема Основная масса современных аналоговых и аналого-цифровых электронных устройств выполняется на специализированных микросхемах...

Логические цифровые микросхемы Более сложные элементы цифровой схемотехники (триггеры, мультиплексоры, декодеры и т.д.) не имеют...

Этические проблемы проведения экспериментов на человеке и животных В настоящее время четко определены новые подходы и требования к биомедицинским исследованиям...

Классификация потерь населения в очагах поражения в военное время Ядерное, химическое и бактериологическое (биологическое) оружие является оружием массового поражения...

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

Менадиона натрия бисульфит (Викасол) Групповая принадлежность •Синтетический аналог витамина K, жирорастворимый, коагулянт...

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

Дренирование желчных протоков Показаниями к дренированию желчных протоков являются декомпрессия на фоне внутрипротоковой гипертензии, интраоперационная холангиография, контроль за динамикой восстановления пассажа желчи в 12-перстную кишку...

Studopedia.info - Студопедия - 2014-2024 год . (0.012 сек.) русская версия | украинская версия