Студопедия — Основы теории. Очередь — это линейный список информации, работа с которой происходит по принципу "первым пришел — первым вышел" (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; просмотров: 688. Нарушение авторских прав; Мы поможем в написании вашей работы!



Практические расчеты на срез и смятие При изучении темы обратите внимание на основные расчетные предпосылки и условности расчета...

Функция спроса населения на данный товар Функция спроса населения на данный товар: Qd=7-Р. Функция предложения: Qs= -5+2Р,где...

Аальтернативная стоимость. Кривая производственных возможностей В экономике Буридании есть 100 ед. труда с производительностью 4 м ткани или 2 кг мяса...

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

Принципы резекции желудка по типу Бильрот 1, Бильрот 2; операция Гофмейстера-Финстерера. Гастрэктомия Резекция желудка – удаление части желудка: а) дистальная – удаляют 2/3 желудка б) проксимальная – удаляют 95% желудка. Показания...

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

Билиодигестивные анастомозы Показания для наложения билиодигестивных анастомозов: 1. нарушения проходимости терминального отдела холедоха при доброкачественной патологии (стенозы и стриктуры холедоха) 2. опухоли большого дуоденального сосочка...

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

Сущность, виды и функции маркетинга персонала Перснал-маркетинг является новым понятием. В мировой практике маркетинга и управления персоналом он выделился в отдельное направление лишь в начале 90-х гг.XX века...

Разработка товарной и ценовой стратегии фирмы на российском рынке хлебопродуктов В начале 1994 г. английская фирма МОНО совместно с бельгийской ПЮРАТОС приняла решение о начале совместного проекта на российском рынке. Эти фирмы ведут деятельность в сопредельных сферах производства хлебопродуктов. МОНО – крупнейший в Великобритании...

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