Ring Buffer (Circular Buffer)
A fixed-size array used as a circular queue with O(1) enqueue and dequeue by wrapping indices, avoiding memory allocation after initialization.
Syntax
class RingBuffer {
constructor(capacity) {
this.buf = new Array(capacity);
this.head = 0; this.tail = 0; this.size = 0;
}
enqueue(val) { ... } // O(1)
dequeue() { ... } // O(1)
}
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
capacity | number | Yes | Maximum number of elements the buffer can hold at once. |
Returns
RingBuffer — A new fixed-capacity ring buffer.
Throws
Error— Overflow when enqueue is called on a full buffer (or element is dropped, depending on policy).
Examples
class RingBuffer {
#buf; #cap; #head = 0; #tail = 0; #size = 0;
constructor(cap) { this.#cap = cap; this.#buf = new Array(cap); }
get size() { return this.#size; }
isFull() { return this.#size === this.#cap; }
isEmpty() { return this.#size === 0; }
enqueue(val) {
if (this.isFull()) throw new Error('Buffer overflow');
this.#buf[this.#tail] = val;
this.#tail = (this.#tail + 1) % this.#cap;
this.#size++;
}
dequeue() {
if (this.isEmpty()) return undefined;
const val = this.#buf[this.#head];
this.#head = (this.#head + 1) % this.#cap;
this.#size--;
return val;
}
peek() { return this.isEmpty() ? undefined : this.#buf[this.#head]; }
}
const rb = new RingBuffer(3);
rb.enqueue(1); rb.enqueue(2); rb.enqueue(3);
console.log(rb.dequeue(), rb.dequeue());
rb.enqueue(4);
console.log(rb.peek(), rb.size);
Output
1 2
3 2
// Sliding window log: keep last N log entries
const log = new RingBuffer(5);
for (let i = 1; i <= 8; i++) {
if (log.isFull()) log.dequeue(); // drop oldest
log.enqueue(`event-${i}`);
}
const entries = [];
while (!log.isEmpty()) entries.push(log.dequeue());
console.log(entries);
Output
[ 'event-4', 'event-5', 'event-6', 'event-7', 'event-8' ]
Notes
| Operation | Time | Space |
|----------|------|--------------|
| Enqueue | O(1) | O(1) |
| Dequeue | O(1) | O(1) |
| Peek | O(1) | O(1) |
| Total | — | O(capacity) |
Ring buffers are preferred in real-time and embedded systems where
heap allocation must be avoided (audio buffers, network I/O queues).
The modulo (`%`) wraps indices without any data movement.
Can be backed by a power-of-2 capacity to replace `%` with a
bitwise AND: `(i + 1) & (cap - 1)`.