Coding
Data Structures

Ring Buffer From Scratch

Difficulty

Asked at Citadel Securities, Jump Trading

Theory: Data Structures You Implement, Not Import

Read the problem, hints and solution here. The editor needs a bigger screen: open this page on a laptop to write and run your code.

Available in C++ and Python. You are solving it in C++. Switch to Python

Implement RingBuffer, a fixed-capacity first-in first-out queue over a pre-allocated buffer. push adds at the tail and fails when full. pop takes from the head.

Ring buffers sit in the hot path of low-latency systems: market-data handlers stage packets in them, loggers hand records across threads through them, and gateways queue outbound orders in them. They use a fixed block of memory, no allocation after construction, and index arithmetic instead of pointer chasing.

The interface is:

  • the constructor takes capacity (at least 1) and allocates storage for exactly that many elements, once, there.
  • push(value): appends at the tail; returns false (and changes nothing) when full.
  • pop(): removes and returns the head, or nothing when empty.
  • front(): the head without removing it, or nothing when empty.
  • size(), empty() and full().
template <typename T>
class RingBuffer {
public:
    explicit RingBuffer(std::size_t capacity);
    bool push(const T& value);
    std::optional<T> pop();
    std::optional<T> front() const;
    std::size_t size() const;
    bool empty() const;
    bool full() const;
};

pop() and front() return std::nullopt when empty. No std::deque, std::queue, or std::list: the point is the index arithmetic over contiguous storage (a std::vector<T> sized once in the constructor is fine as the backing store). Indices must wrap; the buffer must keep working through many times capacity operations.

Examples

RingBuffer<int> rb(2);
rb.push(1);   // true
rb.push(2);   // true
rb.push(3);   // false  (rejected: full)

RingBuffer<int> other(2);
other.push(7);
other.push(8);
*other.pop();   // 7
other.push(9);
*other.pop();   // 8
*other.pop();   // 9  (wrap-around preserves FIFO order)

Constraints

  • Element type is copyable; capacity up to \(10^6\).
  • All operations must be \(O(1)\): the hidden tests drive many times capacity operations through a buffer, so per-operation shifting or reallocation will not finish in time. The largest hidden test runs 2,000,000 operations at capacity 1,000,000.
  • Track size explicitly or reserve a slot; both are acceptable, but full() and empty() must be exact (the classic head==tail ambiguity is yours to resolve).
Rate this problem
Language:
C++23Python 3.12
RingBuffer
Rate this problem