
Очереди
В программировании принцип работы с очередью тот же самый, что и в быту: первым пришел — первым ушел (FIFO — от англ. First — In – First — Out).
Очередь — это структура, в которую новой элемент добавляется только с одной стороны. Эта сторона называется концом или хвостом очереди. Говорят, что элемент добавляется в конец очереди. Взятие элемента из очереди происходит с другой стороны — из начала (или из головы) очереди.
В качестве примера очереди в программировании можно назвать очередь процессов к разделяемому ресурсу под управлением операционной системы.
Основные операции c очередью те же, что и со стеком:
инициализация очереди;
добавление элемента в очередь;
проверка очереди на пустоту;
взятие элемента из очереди.
В зависимости от характера решаемой задачи очередь можно организовать статически или динамически. Если в процессе работы очередь то очень длинная (несколько десятков или сотен элементов), то короткая (один-два элемента), имеет смысл реализовать очередь с использованием динамической структуры (списка). Если заранее известна максимальная длина очереди, то можно использовать статический массив. Рассмотрим оба этих способа.
При динамической реализации основой очереди является линейный односвязный список. Однако, в отличие от динамического стека, который определяется одним указателем (на вершину), для работы с очередью необходимы два указателя: на голову очереди и на ее хвост. Поэтому для определения очереди возьмем класс, содержащую в качестве полей эти два указателя. И тогда при работе с очередью последняя будет характеризоваться только одним параметром. Это описание очереди и основные операции приведены в листинге 8.25.
Листинг 8.25. Очередь, реализованная динамически
namespace SpaceStack
{
class MyStack // Очередь
{
Node top; // голова очереди
Node tail; // хвост очереди
public void Push(object data) // в стек
public object Pop() // взять из стека
public bool isEmpty() // проверка на пустоту
public class Node // узел
// положить в хвост очереди
public void PushQueue(object inf)
{
Node p = new Node(null, inf);
if (isEmpty())
{
top = p; tail = p;
}
else
{
tail.next = p; tail = p;
}
}
}
}
Замечание. Метод Pop() — взятия элемента из очереди — вызывается только в том случае, если очередь не пуста. Обработка пустой очереди производится в вызывающем контексте.
Пример 8.2. Дан массив целых чисел. Создать очередь, в которую из каждой группы подряд идущих одинаковых чисел вставлять только одно.
В листинге 8.26 приводится текст метода TestQueue(), который создает очередь из элементов массива arr[]и выводит ее на экран. Во время вывода очередь уничтожается.
Листинг 8.26. Создание очереди из элементов массива
static void TestQueue()
{
int[] arr = { 1, 1, 1, 2, 2, 3, 4, 4, 4 };
MyStack myQueue = new MyStack();
int e = 0;
for (int i = 0; i<arr.Length; i++)
{
if (myQueue.isEmpty() || (arr[i] != e))
{
e = arr[i];
myQueue.PushQueue(e);
// положить в очередь
}
}
while (!myQueue.isEmpty())
{
e = (int)myQueue.Pop();
Console.Write(e+” ”);
}
}
На экран будут выведены числа: 1 2 3 4.