← Back to DSA Course | Chapter 6: Queues | Lesson 3 of 5

Circular Queue

Circular Queue Idea

A circular queue treats the underlying array as a loop, wrapping the last position back around to connect with the first, which lets it reuse space freed by earlier dequeues instead of wasting it like a plain array queue would.

Example: Circular Queue Idea

#include <iostream>
using namespace std;
int main() {
	int capacity = 4;
	int q[4] = {10, 20, 0, 0};
	int front = 0, rear = 1;
	front = (front + 1) % capacity;
	rear = (rear + 1) % capacity;
	q[rear] = 30;
	cout << "front=" << front << " rear=" << rear << " value=" << q[rear];
	return 0;
}
public class Main {
	public static void main(String[] args) {
		int capacity = 4;
		int[] q = {10, 20, 0, 0};
		int front = 0, rear = 1;
		front = (front + 1) % capacity;
		rear = (rear + 1) % capacity;
		q[rear] = 30;
		System.out.println("front=" + front + " rear=" + rear + " value=" + q[rear]);
	}
}
capacity = 4
q = [10, 20, 0, 0]
front, rear = 0, 1
front = (front + 1) % capacity
rear = (rear + 1) % capacity
q[rear] = 30
print("front=", front, "rear=", rear, "value=", q[rear])
#include <stdio.h>
int main() {
	int capacity = 4;
	int q[4] = {10, 20, 0, 0};
	int front = 0, rear = 1;
	front = (front + 1) % capacity;
	rear = (rear + 1) % capacity;
	q[rear] = 30;
	printf("front=%d rear=%d value=%d", front, rear, q[rear]);
	return 0;
}

Enqueue in Circular Queue

Enqueue in a circular queue advances the rear index using the modulo operator (rear = (rear + 1) % capacity), so once rear passes the last array slot, it naturally wraps back to index 0 instead of running out of room.

Example: Enqueue in Circular Queue

#include <iostream>
using namespace std;
int main() {
	int capacity = 5;
	int q[5], rear = -1, size = 0;
	for (int i = 1; i <= 3; i++) {
		rear = (rear + 1) % capacity;
		q[rear] = i * 10;
		size++;
	}
	cout << "rear index=" << rear << " last value=" << q[rear];
	return 0;
}
public class Main {
	public static void main(String[] args) {
		int capacity = 5;
		int[] q = new int[5];
		int rear = -1;
		for (int i = 1; i <= 3; i++) {
			rear = (rear + 1) % capacity;
			q[rear] = i * 10;
		}
		System.out.println("rear index=" + rear + " last value=" + q[rear]);
	}
}
capacity = 5
q = [0] * 5
rear = -1
for i in range(1, 4):
    rear = (rear + 1) % capacity
    q[rear] = i * 10
print("rear index=", rear, "last value=", q[rear])
#include <stdio.h>
int main() {
	int capacity = 5;
	int q[5], rear = -1;
	for (int i = 1; i <= 3; i++) {
		rear = (rear + 1) % capacity;
		q[rear] = i * 10;
	}
	printf("rear index=%d last value=%d", rear, q[rear]);
	return 0;
}

Dequeue in Circular Queue

Dequeue works the same way on the front index, moving it forward with modulo so it also wraps around the array boundary, keeping the queue's logical order intact even as it physically loops through the same memory.

Example: Dequeue in Circular Queue

#include <iostream>
using namespace std;
int main() {
	int capacity = 5;
	int q[5] = {10, 20, 30};
	int front = 0;
	int removed = q[front];
	front = (front + 1) % capacity;
	cout << "removed=" << removed << " new front index=" << front;
	return 0;
}
public class Main {
	public static void main(String[] args) {
		int capacity = 5;
		int[] q = {10, 20, 30};
		int front = 0;
		int removed = q[front];
		front = (front + 1) % capacity;
		System.out.println("removed=" + removed + " new front index=" + front);
	}
}
capacity = 5
q = [10, 20, 30]
front = 0
removed = q[front]
front = (front + 1) % capacity
print("removed=", removed, "new front index=", front)
#include <stdio.h>
int main() {
	int capacity = 5;
	int q[3] = {10, 20, 30};
	int front = 0;
	int removed = q[front];
	front = (front + 1) % capacity;
	printf("removed=%d new front index=%d", removed, front);
	return 0;
}

Full and Empty Conditions

Because front and rear can end up at the same index for both an empty queue and a completely full one, a circular queue implementation needs an explicit way to tell those two states apart, usually a separate size counter or one deliberately unused slot.

Example: Full and Empty Conditions

#include <iostream>
using namespace std;
int main() {
	int capacity = 3, size = 0;
	size++; size++; size++;
	bool isFull = (size == capacity);
	bool isEmpty = (size == 0);
	cout << "isFull=" << isFull << " isEmpty=" << isEmpty;
	return 0;
}
public class Main {
	public static void main(String[] args) {
		int capacity = 3, size = 0;
		size++; size++; size++;
		boolean isFull = (size == capacity);
		boolean isEmpty = (size == 0);
		System.out.println("isFull=" + isFull + " isEmpty=" + isEmpty);
	}
}
capacity = 3
size = 0
size += 3
is_full = (size == capacity)
is_empty = (size == 0)
print("isFull=", is_full, "isEmpty=", is_empty)
#include <stdio.h>
int main() {
	int capacity = 3, size = 3;
	int isFull = (size == capacity);
	int isEmpty = (size == 0);
	printf("isFull=%d isEmpty=%d", isFull, isEmpty);
	return 0;
}

Circular Queue Practice

Circular queues are the standard choice whenever you need a fixed-capacity buffer that's continuously filled and drained, like a producer-consumer buffer or a streaming data pipeline, since they avoid ever needing to shift elements.

Example: Circular Queue Practice

#include <iostream>
using namespace std;
int main() {
	int capacity = 3, q[3], front = 0, rear = -1, size = 0;
	for (int i = 1; i <= 3; i++) { rear = (rear + 1) % capacity; q[rear] = i; size++; }
	cout << "Removed: " << q[front] << endl;
	front = (front + 1) % capacity; size--;
	rear = (rear + 1) % capacity; q[rear] = 4; size++;
	cout << "Buffer wrapped, new value: " << q[rear];
	return 0;
}
public class Main {
	public static void main(String[] args) {
		int capacity = 3;
		int[] q = new int[3];
		int front = 0, rear = -1, size = 0;
		for (int i = 1; i <= 3; i++) { rear = (rear + 1) % capacity; q[rear] = i; size++; }
		System.out.println("Removed: " + q[front]);
		front = (front + 1) % capacity; size--;
		rear = (rear + 1) % capacity; q[rear] = 4; size++;
		System.out.println("Buffer wrapped, new value: " + q[rear]);
	}
}
capacity = 3
q = [0] * 3
front, rear, size = 0, -1, 0
for i in range(1, 4):
    rear = (rear + 1) % capacity
    q[rear] = i
    size += 1
print("Removed:", q[front])
front = (front + 1) % capacity
rear = (rear + 1) % capacity
q[rear] = 4
print("Buffer wrapped, new value:", q[rear])
#include <stdio.h>
int main() {
	int capacity = 3, q[3], front = 0, rear = -1;
	for (int i = 1; i <= 3; i++) { rear = (rear + 1) % capacity; q[rear] = i; }
	printf("Removed: %d\n", q[front]);
	front = (front + 1) % capacity;
	rear = (rear + 1) % capacity; q[rear] = 4;
	printf("Buffer wrapped, new value: %d", q[rear]);
	return 0;
}
🔒

Chapter Quiz — Complete all 5 topics to unlock

0/5 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.