在本教程中,您将学习什么是循环队列。 此外,您还将发现在 C,C++ ,Java 和 Python 中实现循环队列。
循环队列避免了使用数组实现的常规队列中的空间浪费。

循环队列
如您在上图中所看到的,在进行一些入队和出队后,队列的大小已减小。
只有当所有元素都已出队后,才能在重置队列后使用索引 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 == SIZE - 1 - 情况 2:
FRONT = REAR + 1
第二种情况发生在REAR由于循环增量而从 0 开始且其值仅比FRONT小 1 时,队列已满。

循环队列的原理
Python,Java 和 C/C++ 示例
最常见的队列实现是使用数组,但是也可以使用列表来实现。
# Circular Queue implementation in Pythonclass MyCircularQueue(object):def __init__(self, k):self.maxlen = kself.currlen = 0self.queue = [None] * kself.head = -1self.tail = -1# Insert an element into the circular queuedef enQueue(self, value):if self.isFull():return Falsetail = (self.tail + 1) % self.maxlenself.queue[tail] = valueself.tail = tailself.currlen += 1if self.currlen == 1:self.head = 0return True# Delete an element from the circular queuedef deQueue(self):if self.isEmpty():return Falseself.head = (self.head + 1) % self.maxlenself.currlen -= 1if self.isEmpty():self.head = -1self.tail = -1return True# Get the front item from the queuedef Front(self):if self.isEmpty():return -1return self.queue[self.head]# Get the last item from the queuedef Rear(self):if self.isEmpty():return -1return self.queue[self.tail]# Checks whether the circular queue is empty or notdef isEmpty(self):return self.currlen == 0# Checks whether the circular queue is full or notdef isFull(self):return self.currlen == self.maxlen# Display the queuedef Display(self):for i in range(self.head, self.tail):print(self.queue[i], end=" ")# Your MyCircularQueue object will be instantiated and called as such:obj = MyCircularQueue(5)obj.enQueue(1)obj.enQueue(2)obj.enQueue(3)obj.enQueue(4)obj.enQueue(5)print("Initial array")print(obj.Display())print("After removing an element")obj.deQueue()obj.Display()
// Circular Queue implementation in Javapublic class CQueue {int SIZE = 5; // Size of Circular Queueint front, rear;int items[] = new int[SIZE];CQueue() {front = -1;rear = -1;}// Check if the queue is fullboolean isFull() {if (front == 0 && rear == SIZE - 1) {return true;}if (front == rear + 1) {return true;}return false;}// Check if the queue is emptyboolean isEmpty() {if (front == -1)return true;elsereturn false;}// Adding an elementvoid enQueue(int element) {if (isFull()) {System.out.println("Queue is full");} else {if (front == -1)front = 0;rear = (rear + 1) % SIZE;items[rear] = element;System.out.println("Inserted " + element);}}// Removing an elementint deQueue() {int element;if (isEmpty()) {System.out.println("Queue is empty");return (-1);} else {element = items[front];if (front == rear) {front = -1;rear = -1;} /* Q has only one element, so we reset the queue after deleting it. */else {front = (front + 1) % SIZE;}return (element);}}void display() {/* Function to display status of Circular Queue */int i;if (isEmpty()) {System.out.println("Empty Queue");} else {System.out.println("Front -> " + front);System.out.println("Items -> ");for (i = front; i != rear; i = (i + 1) % SIZE)System.out.print(items[i] + " ");System.out.println(items[i]);System.out.println("Rear -> " + rear);}}public static void main(String[] args) {CQueue q = new CQueue();// Fails because front = -1q.deQueue();q.enQueue(1);q.enQueue(2);q.enQueue(3);q.enQueue(4);q.enQueue(5);// Fails to enqueue because front == 0 && rear == SIZE - 1q.enQueue(6);q.display();int elem = q.deQueue();if (elem != -1) {System.out.println("Deleted Element is " + elem);}q.display();q.enQueue(7);q.display();// Fails to enqueue because front == rear + 1q.enQueue(8);}}
// Circular Queue implementation in C#include <stdio.h>#define SIZE 5int items[SIZE];int front = -1, rear = -1;// Check if the queue is fullint isFull() {if ((front == rear + 1) || (front == 0 && rear == SIZE - 1)) return 1;return 0;}// Check if the queue is emptyint isEmpty() {if (front == -1) return 1;return 0;}// Adding an elementvoid 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);}}// Removing an elementint 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 has only one element, so we reset the// queue after dequeing it. ?else {front = (front + 1) % SIZE;}printf("\n Deleted element -> %d \n", element);return (element);}}// Display the queuevoid 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() {// Fails because front = -1deQueue();enQueue(1);enQueue(2);enQueue(3);enQueue(4);enQueue(5);// Fails to enqueue because front == 0 && rear == SIZE - 1enQueue(6);display();deQueue();display();enQueue(7);display();// Fails to enqueue because front == rear + 1enQueue(8);return 0;}
// Circular Queue implementation in C++#include <iostream>#define SIZE 5 /* Size of Circular Queue */using namespace std;class Queue {private:int items[SIZE], front, rear;public:Queue() {front = -1;rear = -1;}// Check if the queue is fullbool isFull() {if (front == 0 && rear == SIZE - 1) {return true;}if (front == rear + 1) {return true;}return false;}// Check if the queue is emptybool isEmpty() {if (front == -1)return true;elsereturn false;}// Adding an elementvoid 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;}}// Removing an elementint deQueue() {int element;if (isEmpty()) {cout << "Queue is empty" << endl;return (-1);} else {element = items[front];if (front == rear) {front = -1;rear = -1;}// Q has only one element,// so we reset the queue after deleting it.else {front = (front + 1) % SIZE;}return (element);}}void display() {// Function to display status of Circular Queueint 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;// Fails because front = -1q.deQueue();q.enQueue(1);q.enQueue(2);q.enQueue(3);q.enQueue(4);q.enQueue(5);// Fails to enqueue because front == 0 && rear == SIZE - 1q.enQueue(6);q.display();int elem = q.deQueue();if (elem != -1)cout << endl<< "Deleted Element is " << elem;q.display();q.enQueue(7);q.display();// Fails to enqueue because front == rear + 1q.enQueue(8);return 0;}
循环队列复杂度
对于(数组实现),循环队列的入队和出队操作的复杂度为O(1)。
循环队列应用
- CPU 调度
- 内存管理
- 交通管理
