Циклическая очередь позволяет избежать потери места в обычной реализации очереди с использованием массивов.
DeQueue - удаление элемента из очереди;
FRONT и REAR - два указателя, используемые для отслеживания первого и последнего элементов в очереди.
Как вы можете видеть на изображении выше, после некоторого количества добавления в очередь и удаления из очереди ее размер был уменьшен.
Индексы 0 и 1 могут использоваться только после сброса очереди, когда все элементы сняты.
Как работает круговая очередь
Циклическая очередь работает по процессу циклического приращения, то есть когда мы пытаемся увеличить любую переменную и достигаем конца очереди, мы начинаем с начала очереди по модулю деления с размером очереди.
То есть:
if REAR + 1 == 5 (overflow!), REAR = (REAR + 1)%5 = 0 (start of queue)
Операции с очередями работают следующим образом:
- Два указателя, называемые FRONT и REAR, используются для отслеживания первого и последнего элементов в очереди.
- При инициализации очереди мы устанавливаем значение FRONT и REAR равным -1.
- При добавления элемента мы постепенно увеличиваем значение индекса REAR и помещаем новый элемент в положение, на которое указывает REAR.
- При снятии очереди с элемента мы возвращаем значение, на которое указывает FRONT, и постепенно увеличиваем индекс FRONT.
- Перед постановкой в очередь мы проверяем, заполнена ли очередь.
- Перед снятием очереди мы проверяем, пуста ли очередь.
- При инициализации первого элемента мы устанавливаем значение FRONT в 0.
- При удалении последнего элемента мы сбрасываем значения FRONT и REAR в -1.
Однако проверка на полную очередь имеет новый дополнительный пункт:
- Случай 1: FRONT = 0 && REAR == РАЗМЕР - 1
- Случай 2: ПЕРЕДНЯЯ = ЗАДНЯЯ + 1
Второй случай происходит, когда REAR начинается с 0 из-за кругового приращения, и когда его значение всего на 1 меньше значения FRONT, очередь заполнена.
Реализация циклической очереди на языке программирования
Наиболее распространенная реализация очереди использует массивы, но также может возможна реализация с использованием списков.
Реализация с использованием C-программирования
#include <stdio.h> #define SIZE 5 int items[SIZE]; int front = -1, rear =-1; int isFull() { if( (front == rear + 1) || (front == 0 && rear == SIZE-1)) return 1; return 0; } int isEmpty() { if(front == -1) return 1; return 0; } void enQueue(int element) { if(isFull()) printf("\n Queue is full!! \n"); else { if(front == -1) front = 0; rear = (rear + 1) % SIZE; items[rear] = element; printf("\n Inserted -> %d", element); } } int deQueue() { int element; if(isEmpty()) { printf("\n Queue is empty !! \n"); return(-1); } else { element = items[front]; if (front == rear){ front = -1; rear = -1; } /* В Q есть только один элемент, поэтому мы сбрасываем очередь после ее удаления. */ else { front = (front + 1) % SIZE; } printf("\n Deleted element -> %d \n", element); return(element); } } void display() { int i; if(isEmpty()) printf(" \n Empty Queue\n"); else { printf("\n Front -> %d ",front); printf("\n Items -> "); for( i = front; i!=rear; i=(i+1)%SIZE) { printf("%d ",items[i]); } printf("%d ",items[i]); printf("\n Rear -> %d \n",rear); } } int main() { // Ложь, потому что front = -1 deQueue(); enQueue(1); enQueue(2); enQueue(3); enQueue(4); enQueue(5); // Невозможно поставить в очередь, потому что front == 0 && rear == SIZE - 1 enQueue(6); display(); deQueue(); display(); enQueue(7); display(); // Невозможно поставить в очередь, потому что front == rear + 1 enQueue(8); return 0; }
Когда вы запустите эту программу, получите следующее:
Inserted -> 1 Inserted -> 2 Inserted -> 3 Inserted -> 4 Inserted -> 5 Queue is full!! Front -> 0 Items -> 1 2 3 4 5 Rear -> 4 Deleted element -> 1 Front -> 1 Items -> 2 3 4 5 Rear -> 4 Inserted -> 7 Front -> 1 Items -> 2 3 4 5 7 Rear -> 0 Queue is full!!
Реализация с использованием программирования на C ++
#include <iostream> #define SIZE 5 /* Размер круговой очереди */ using namespace std; class Queue { private: int items[SIZE], front, rear; public: Queue(){ front = -1; rear = -1; } bool isFull(){ if(front == 0 && rear == SIZE - 1){ return true; } if(front == rear + 1) { return true; } return false; } bool isEmpty(){ if(front == -1) return true; else return false; } void enQueue(int element){ if(isFull()){ cout << "Queue is full"; } else { if(front == -1) front = 0; rear = (rear + 1) % SIZE; items[rear] = element; cout << endl << "Inserted " << element << endl; } } int deQueue(){ int element; if(isEmpty()){ cout << "Queue is empty" << endl; return(-1); } else { element = items[front]; if(front == rear){ front = -1; rear = -1; } /* Q имеет только один элемент, поэтому мы удаляем очередь после удаления. */ else { front=(front+1) % SIZE; } return(element); } } void display() { /* Функция для отображения статуса круговой очереди */ int i; if(isEmpty()) { cout << endl << "Empty Queue" << endl; } else { cout << "Front -> " << front; cout << endl << "Items -> "; for(i=front; i!=rear;i=(i+1)%SIZE) cout << items[i]; cout << items[i]; cout << endl << "Rear -> " << rear; } } }; int main() { Queue q; // Ложь, потому что front = -1 q.deQueue(); q.enQueue(1); q.enQueue(2); q.enQueue(3); q.enQueue(4); q.enQueue(5); // Невозможно поставить в очередь, потому что front == 0 && rear == SIZE - 1 q.enQueue(6); q.display(); int elem = q.deQueue(); if( elem != -1) cout << endl << "Deleted Element is " << elem; q.display(); q.enQueue(7); q.display(); // Невозможно поставить в очередь, потому что front == rear + 1 q.enQueue(8); return 0; }
Когда вы запустите эту программу, получите следующее:
Queue is empty Inserted 1 Inserted 2 Inserted 3 Inserted 4 Inserted 5 Queue is full Front -> 0 Items -> 12345 Rear -> 4 Deleted Element is 1 Front -> 1 Items -> 2345 Rear -> 4 Inserted 7 Front -> 1 Items -> 23457 Rear -> 0 Queue is full