Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Очереди FIFO и обобщенные очереди.doc
Скачиваний:
3
Добавлен:
05.11.2018
Размер:
74.75 Кб
Скачать

Очереди FIFO и обобщенные очереди.

Очередь с дисциплиной FIFO(First-In,First-Out-первым пришел, первым ушел) является еще одним фундаментальным АТД, который подобен стеку магазинного типа, но подчиняется противоположному правилу удаления элемента в операции удалить. Из очереди удаляется не последний вставленный элемент, а наоборот - элемент, который был вставлен в очередь раньше всех остальных.

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

Программа 4.13 Интерфейс АТД “ Очередь FIFO

template <class Item>

class QUEUE

{

private:

// программный код, зависящий от реализации

public:

QUEUE (int) ;

Int empty ( ) ;

Void put (Item) ;

Item get ( ) ;

} ;

Очереди FIFO с завидной частотой встречаются в повседневной жизни. Когда мы стоим в цепочке людей, чтобы посмотреть кинокартину или купить продукты, нас обслуживают в порядке FIFO. Аналогично этому в вычислительных системах очереди FIFO часто используются для обслуживания задач, которые необходимо выполнять по принципу: первым пришел, первым - обслужился. Другим примером, иллюстрирующим различие между стеками и очередями FIFO ,может служить отношение к скоропортящимся продуктам в бакалейной лавке. Если бакалейщик выкладывает новые товары на переднюю часть полки и покупатели берут товары также с передней части полки, получается стек. Бакалейщик может столкнуться с проблемой, поскольку товар на задней части полки может стоять очень долго и попросту испортиться. Выкладывая новые товары на заднюю часть полки, бакалейщик гарантирует, что время, в течение которого товар находится на полке, ограничивается временем, необходимым покупателям для приобретения всех товаров, выставляемых на полку. Этот же базовый принцип применяется во множестве подобных ситуаций.

Определение 4.3. Очередь FIFO-это АТД, который содержит две базовых операции: вставить (put-занести) новый элемент и удалить (get-извлечь) элемент, который был вставлен раньше всех остальных.

Программа 4.13 является интерфейсом для АТД ”Очередь FIFO”. Этот интерфейс отличается от интерфейса стека, рассмотренного в разделе 4.2, только спецификациями - для компилятора два интерфейса совершенно идентичны! Это подчеркивает тот факт, что сама абстракция, которую программисты обычно не определяют формально, является существенным компонентом абстрактного типа данных. Для больших приложений, которые могут содержать десятки АТД, проблема их точного определения является критически важной. В настоящей книге мы работаем с АТД, представляющими важнейшие понятия, которые определяются в тексте, но не при помощи формальных языков (разве что через конкретные реализации). Чтобы понять природу абстрактных типов данных, потребуется рассмотреть примеры их использования и конкретные реализации.

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

В случае реализации АТД ”Очередь FIFO” с помощью связного списка, элементы списка хранятся в следующем порядке: от первого вставленного до последнего вставленного элемента. Такой порядок является обратным по отношению к порядку, который применяется в реализации стека, причем он позволяет создавать эффективные реализации операций над очередями. Как показано на рис.4.7 и в программе 4.14 (реализации), поддерживаются два указателя на этот список: один на начало списка (чтобы можно было извлечь первый элемент) и второй на его конец (для занесения в очередь нового элемента).

Программа 4.14. Реализация очереди FIFO на базе связного списка.

Различие между очередью FIFO и стеком магазинного типа состоит в том, что новые элементы вставляются в конец списка, а не в его начало. Следовательно, в этом классе хранится указатель tail на последний узел списка, и, таким образом, функция put может добавлять в список новый узел, связывая его с узлом, на который ссылается указатель tail, а затем обновляя указатель tail так, чтобы он указывал уже на новый узел. Функции QUEUE, get, empty идентичны аналогичным функциям в реализации стека магазинного типа на базе связного списка из программы 4.8. Поскольку новые узлы всегда вставляются в конец списка, конструктор узлов может устанавливать в null поле указателя каждого нового узла и получать только один аргумент.

template <class Item>

class QUEUE

{

private:

struct node

{ Item item; node* next;

node (Item x)

{ item = x; next = 0; }

} ;

typedef node *link;

link head, tail;

public:

QUEUE (int)

{ head = 0; }