Skip to main content

Circular Buffer

A circular buffer, also known as a ring buffer, is a fixed-size data structure that operates in a circular manner, meaning that once the buffer reaches the end, it wraps around to the beginning. It is commonly used in situations where data is produced and consumed at different rates, such as in streaming data or buffering in IO operations.

Key Properties of a Circular Buffer

1. Fixed Size : The buffer has a maximum capacity, and once it is full, new data overwrites the oldest data if no other operation is performed.

2. Wraparound Behavior : When you reach the end of the buffer, it wraps around to the beginning (first position) to continue writing or reading data.

3. Efficient Operations : Access to the head and tail (read and write operations) is efficient, typically constant time O(1).

4. Two Pointers A circular buffer generally uses two pointers:

  • Head pointer: Points to the position where data is to be read.
  • Tail pointer: Points to the position where new data will be written.
class CircularBuffer {
constructor(size) {
this.size = size;
this.buffer = new Array(size);
this.head = 0;
this.tail = 0;
this.count = 0;
}

// Write data to the buffer
write(data) {
if (this.count === this.size) {
console.log('Buffer is full, overwriting data');
this.head = (this.head + 1) % this.size; // Overwrite the oldest data
} else {
this.count++;
}
this.buffer[this.tail] = data;
this.tail = (this.tail + 1) % this.size;
}

// Read data from the buffer
read() {
if (this.count === 0) {
console.log('Buffer is empty');
return null;
}
const data = this.buffer[this.head];
this.head = (this.head + 1) % this.size;
this.count--;
return data;
}

// Check if the buffer is full
isFull() {
return this.count === this.size;
}

// Check if the buffer is empty
isEmpty() {
return this.count === 0;
}

// Peek at the data at the head of the buffer
peek() {
if (this.count === 0) {
console.log('Buffer is empty');
return null;
}
return this.buffer[this.head];
}
}

// Usage
const buffer = new CircularBuffer(3);
buffer.write(10);
buffer.write(20);
buffer.write(30);
console.log(buffer.read()); // 10
buffer.write(40); // Overwrites 20
console.log(buffer.read()); // 20 (overwritten)
console.log(buffer.peek()); // 30