Очередь. Функциональная спецификация очереди: FIFO и семь операций

Модуль "Очередь и дек" • урок 1 из 7 • ~7 минут

Суть урока. Очередь - динамическая структура данных, работающая по принципу FIFO (первым пришел - первым ушел): добавление идет в один конец (хвост), удаление - с другого (голова). В отличие от стека очередь сохраняет порядок проходящих через нее элементов.
Очередь. Функциональная спецификация очереди: элементы 5, 3 и 8 стоят от головы слева к хвосту справа, ИЗ_ОЧЕРЕДИ забирает элемент с головы, В_ОЧЕРЕДЬ ставит новый элемент в свободное место у хвоста
Голова слева, хвост справа: порядок выхода совпадает с порядком входа

Что это такое

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

Отсюда принцип FIFO, First In - First Out: первым пришел - первым ушел. Сравните со стеком: там оба действия происходят на одном конце, и порядок инвертируется. Очередь порядок сохраняет - элементы выходят ровно в том порядке, в каком вошли.

Зачем это нужно

Очередь - стандартное средство сглаживания разницы в скорости двух процессов, когда поставщик данных работает быстрее потребителя или неравномерно:

Очередь. Функциональная спецификация очереди: семь операций

Функциональная спецификация очереди почти повторяет стековую - меняется только конец, с которого читаем:

Доступ к середине очереди спецификация запрещает - только два конца, у каждого своя роль.

Тренажер: операции очереди по шагам

Выполним над пустой очередью цепочку операций Enqueue 5, 3, 8, Front, Size, Dequeue, Dequeue, Enqueue 1, Dequeue, Dequeue и сравним со стеком: голова очереди слева, хвост справа, а числа взяты те же, что и в тренажере стека.

элемент в очереди операция читает элемент вышедший элемент свободное место
Длина: 0 Первый: - Шаг: 0 / 0
А как в Python? Обычный list для очереди не подходит: pop(0) сдвигает все оставшиеся элементы и работает за O(N). Правильный инструмент - collections.deque: append() в хвост и popleft() из головы работают за O(1).

Интерфейс очереди на C

Как и для стека, функциональная спецификация на C превращается в набор объявлений - без единого слова о том, как элементы хранятся в памяти:

#include <stdbool.h>

typedef int T; /* тип элемента */
typedef struct Queue Queue;

/* Интерфейс очереди (функциональная спецификация) */
void Create(Queue* q);
bool Empty(Queue* q);
void Push(Queue* q, T element);  /* В_ОЧЕРЕДЬ: в хвост */
void Pop(Queue* q);              /* ИЗ_ОЧЕРЕДИ: из головы */
T    Top(Queue* q);              /* ПЕРВЫЙ: смотрит, не удаляя */
int  Size(Queue* q);             /* ДЛИНА */
void Destroy(Queue* q);

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

Коротко: главное

  • Очередь - структура с двумя концами: добавление в хвост, удаление из головы.
  • Принцип FIFO: порядок извлечения совпадает с порядком добавления.
  • Назначение: сглаживание разницы скоростей производителя и потребителя данных.
  • Операции: Create, Empty, Enqueue, Dequeue (разрушающее чтение), Front, Size, Destroy.
  • Стек инвертирует порядок элементов, очередь - сохраняет.

Проверьте себя

В пустую очередь по очереди добавили буквы А, Б, Ц. В каком порядке они будут извлечены?

Как вам урок? Спасибо за отзыв!