Skip to content
BytePatterns

Circular Queue

Stacks & Queues: lesson 8 of 9

A fixed array that never shifts, because the ends wrap around.

Lesson 8 of 9 · 5 min

Circular Queue

Step 1 of 10

Five cells, joined end to end. Two integers describe the queue: head and size.

The Idea

A queue on a plain list is tempting until you see the cost: removing the front shifts everything else down. A ring buffer never moves data. It moves two numbers.

head marks the front, size says how many cells are live, and % capacity folds any index past the end back to the beginning.

Real-World Example

A dashboard camera writing over the oldest footage. The card never grows and nothing is ever copied — the write head simply comes round again and lands on the frames you no longer need.

The Code

class Ring:
    def __init__(self, cap):
        self.buf, self.head, self.size = [None] * cap, 0, 0
    def push(self, x):
        if self.size == len(self.buf): raise IndexError("full")
        self.buf[(self.head + self.size) % len(self.buf)] = x   # wrap with %
        self.size += 1
    def pop(self):
        x = self.buf[self.head]
        self.head = (self.head + 1) % len(self.buf)             # head walks the ring
        self.size -= 1
        return x

r = Ring(3)
for x in "abc": r.push(x)
print(r.pop(), r.pop())     # a b
r.push("d"); r.push("e")    # the two freed cells are reused, nothing shifts
print(r.buf, r.head)        # ['d', 'e', 'c'] 2

Python

Your turn

What does this print?

buf, head, size = [None] * 3, 0, 0
for x in "abc":
  buf[(head + size) % 3] = x; size += 1
head, size = (head + 1) % 3, size - 1
buf[(head + size) % 3] = "d"; size += 1
print(buf)

Mini quiz

1 / 3

What does the modulo do?

New lessons land every few weeks

Leave an address and we will tell you when the next one is up. That is the only reason we will use it.

One address, stored so we can email you. Nothing else, ever.