{
  "id": "stacks-queues/circular-queue",
  "version": 1,
  "deterministic": true,
  "url": "/dsa/stacks-queues/circular-queue",
  "topic": {
    "slug": "stacks-queues",
    "title": "Stacks & Queues"
  },
  "title": "Circular Queue",
  "tagline": "A queue in a fixed array that never shuffles — the pointers go round instead.",
  "vizKind": "array",
  "complexity": {
    "time": {
      "best": "O(1)",
      "average": "O(1)",
      "worst": "O(1)"
    },
    "space": "O(capacity)",
    "growth": "constant",
    "note": "Both enqueue and dequeue are O(1) forever, because the data never moves — only the head index does, and % capacity wraps it round. The memory is fixed up front, which is exactly why it suits buffers and streams."
  },
  "code": {
    "javascript": "class CircularQueue {\n  constructor(capacity) {\n    this.a = new Array(capacity).fill(null);\n    this.cap = capacity;\n    this.head = 0;\n    this.size = 0;\n  }\n  enqueue(v) {\n    if (this.size === this.cap) return false;   // full\n    const tail = (this.head + this.size) % this.cap;\n    this.a[tail] = v;\n    this.size++;\n    return true;\n  }\n  dequeue() {\n    if (this.size === 0) return null;           // empty\n    const v = this.a[this.head];\n    this.a[this.head] = null;\n    this.head = (this.head + 1) % this.cap;     // wrap around\n    this.size--;\n    return v;\n  }\n}",
    "python": "class CircularQueue:\n    def __init__(self, capacity):\n        self.a = [None] * capacity\n        self.cap = capacity\n        self.head = 0\n        self.size = 0\n\n    def enqueue(self, v):\n        if self.size == self.cap: return False   # full\n        tail = (self.head + self.size) % self.cap\n        self.a[tail] = v\n        self.size += 1\n        return True\n\n    def dequeue(self):\n        if self.size == 0: return None           # empty\n        v = self.a[self.head]\n        self.a[self.head] = None\n        self.head = (self.head + 1) % self.cap   # wrap around\n        self.size -= 1\n        return v\n",
    "java": "class CircularQueue {\n  int[] a; int cap, head = 0, size = 0;\n\n  CircularQueue(int capacity) {\n    a = new int[capacity];\n    cap = capacity;\n  }\n\n  boolean enqueue(int v) {\n    if (size == cap) return false;            // full\n    int tail = (head + size) % cap;\n    a[tail] = v;\n    size++;\n    return true;\n  }\n\n  Integer dequeue() {\n    if (size == 0) return null;               // empty\n    int v = a[head];\n    head = (head + 1) % cap;                  // wrap around\n    size--;\n    return v;\n  }\n}",
    "cpp": "class CircularQueue {\n  vector<int> a; int cap, head = 0, size = 0;\npublic:\n  CircularQueue(int capacity) : a(capacity), cap(capacity) {}\n\n  bool enqueue(int v) {\n    if (size == cap) return false;            // full\n    int tail = (head + size) % cap;\n    a[tail] = v;\n    size++;\n    return true;\n  }\n\n  int dequeue() {\n    if (size == 0) return -1;                 // empty\n    int v = a[head];\n    head = (head + 1) % cap;                  // wrap around\n    size--;\n    return v;\n  }\n};"
  },
  "defaultInput": [
    4,
    8,
    15,
    16,
    23
  ],
  "defaultTarget": null,
  "inputHint": "Fixed capacity of 6. Watch the tail wrap around into freed slots. −1 means empty.",
  "pitfalls": [
    {
      "wrong": "Forgetting the % capacity when advancing head or tail.",
      "right": "Without the modulo, the pointer runs off the end of the array and crashes. The wrap-around *is* the circular queue."
    },
    {
      "wrong": "Using head == tail to mean 'empty'.",
      "right": "It's ambiguous — head equals tail both when the queue is empty and when it's completely full. Track the size separately, or leave one slot deliberately unused."
    },
    {
      "wrong": "Trying to enqueue into a full queue.",
      "right": "It has a fixed capacity by design. Check `size == capacity` first and refuse, or you'll silently overwrite an item that hasn't been served yet."
    }
  ],
  "quiz": [
    {
      "q": "What problem does a circular queue solve?",
      "options": [
        "Queues that are too small",
        "Dequeue on an array-backed queue shifting every element — O(n)",
        "Queues losing their order",
        "Running out of memory"
      ],
      "answer": 1,
      "why": "A naive array queue shifts everything left on every dequeue. A circular queue moves the head pointer instead, so nothing is ever copied and dequeue stays O(1)."
    },
    {
      "q": "How does the tail get back to the start of the array?",
      "options": [
        "The array is copied",
        "With % capacity — the index wraps round to 0",
        "It doesn't — the queue stops",
        "The array grows"
      ],
      "answer": 1,
      "why": "(index + 1) % capacity sends the pointer round the ring, reusing the slots freed behind the head. That modulo is the entire idea."
    },
    {
      "q": "Why is `head == tail` a bad test for 'empty'?",
      "options": [
        "It's too slow",
        "It's also true when the queue is completely full",
        "head is never equal to tail",
        "It works fine"
      ],
      "answer": 1,
      "why": "The pointers coincide both when the ring is empty and when it has wrapped all the way round and filled. You must track the size separately to tell the two apart."
    }
  ],
  "problems": [
    {
      "name": "Design Circular Queue",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/design-circular-queue/"
    },
    {
      "name": "Design Circular Deque",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/design-circular-deque/"
    },
    {
      "name": "Moving Average from Data Stream",
      "difficulty": "Easy",
      "url": "https://leetcode.com/problems/moving-average-from-data-stream/"
    }
  ],
  "trace": {
    "note": "Each frame is one immutable step: data snapshot, pointers, per-index roles, executing code line, and a one-sentence explanation.",
    "length": 11,
    "frames": [
      {
        "data": [
          {
            "id": "s0",
            "value": -1
          },
          {
            "id": "s1",
            "value": -1
          },
          {
            "id": "s2",
            "value": -1
          },
          {
            "id": "s3",
            "value": -1
          },
          {
            "id": "s4",
            "value": -1
          },
          {
            "id": "s5",
            "value": -1
          }
        ],
        "pointers": [
          {
            "name": "head",
            "index": 0
          }
        ],
        "highlights": [
          {
            "index": 0,
            "role": "discarded"
          },
          {
            "index": 1,
            "role": "discarded"
          },
          {
            "index": 2,
            "role": "discarded"
          },
          {
            "index": 3,
            "role": "discarded"
          },
          {
            "index": 4,
            "role": "discarded"
          },
          {
            "index": 5,
            "role": "discarded"
          }
        ],
        "codeLine": 1,
        "variables": {
          "capacity": 6,
          "size": 0,
          "head": 0
        },
        "explanation": "A fixed array of 6 slots — and it never shifts anything. Instead of moving the data, a circular queue moves the head pointer, and wraps it around the end. −1 means an empty slot.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "active"
      },
      {
        "data": [
          {
            "id": "s0",
            "value": 4
          },
          {
            "id": "s1",
            "value": -1
          },
          {
            "id": "s2",
            "value": -1
          },
          {
            "id": "s3",
            "value": -1
          },
          {
            "id": "s4",
            "value": -1
          },
          {
            "id": "s5",
            "value": -1
          }
        ],
        "pointers": [
          {
            "name": "head",
            "index": 0
          },
          {
            "name": "tail",
            "index": 0
          }
        ],
        "highlights": [
          {
            "index": 1,
            "role": "discarded"
          },
          {
            "index": 2,
            "role": "discarded"
          },
          {
            "index": 3,
            "role": "discarded"
          },
          {
            "index": 4,
            "role": "discarded"
          },
          {
            "index": 5,
            "role": "discarded"
          },
          {
            "index": 0,
            "role": "swap"
          }
        ],
        "codeLine": 10,
        "variables": {
          "enqueued": 4,
          "tail": 0,
          "size": 1
        },
        "explanation": "enqueue(4) — it lands in slot 0, computed as (head + size) % 6.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "s0",
            "value": 4
          },
          {
            "id": "s1",
            "value": 8
          },
          {
            "id": "s2",
            "value": -1
          },
          {
            "id": "s3",
            "value": -1
          },
          {
            "id": "s4",
            "value": -1
          },
          {
            "id": "s5",
            "value": -1
          }
        ],
        "pointers": [
          {
            "name": "head",
            "index": 0
          },
          {
            "name": "tail",
            "index": 1
          }
        ],
        "highlights": [
          {
            "index": 2,
            "role": "discarded"
          },
          {
            "index": 3,
            "role": "discarded"
          },
          {
            "index": 4,
            "role": "discarded"
          },
          {
            "index": 5,
            "role": "discarded"
          },
          {
            "index": 1,
            "role": "swap"
          }
        ],
        "codeLine": 10,
        "variables": {
          "enqueued": 8,
          "tail": 1,
          "size": 2
        },
        "explanation": "enqueue(8) — it lands in slot 1, computed as (head + size) % 6.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "s0",
            "value": 4
          },
          {
            "id": "s1",
            "value": 8
          },
          {
            "id": "s2",
            "value": 15
          },
          {
            "id": "s3",
            "value": -1
          },
          {
            "id": "s4",
            "value": -1
          },
          {
            "id": "s5",
            "value": -1
          }
        ],
        "pointers": [
          {
            "name": "head",
            "index": 0
          },
          {
            "name": "tail",
            "index": 2
          }
        ],
        "highlights": [
          {
            "index": 3,
            "role": "discarded"
          },
          {
            "index": 4,
            "role": "discarded"
          },
          {
            "index": 5,
            "role": "discarded"
          },
          {
            "index": 2,
            "role": "swap"
          }
        ],
        "codeLine": 10,
        "variables": {
          "enqueued": 15,
          "tail": 2,
          "size": 3
        },
        "explanation": "enqueue(15) — it lands in slot 2, computed as (head + size) % 6.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "s0",
            "value": 4
          },
          {
            "id": "s1",
            "value": 8
          },
          {
            "id": "s2",
            "value": 15
          },
          {
            "id": "s3",
            "value": 16
          },
          {
            "id": "s4",
            "value": -1
          },
          {
            "id": "s5",
            "value": -1
          }
        ],
        "pointers": [
          {
            "name": "head",
            "index": 0
          },
          {
            "name": "tail",
            "index": 3
          }
        ],
        "highlights": [
          {
            "index": 4,
            "role": "discarded"
          },
          {
            "index": 5,
            "role": "discarded"
          },
          {
            "index": 3,
            "role": "swap"
          }
        ],
        "codeLine": 10,
        "variables": {
          "enqueued": 16,
          "tail": 3,
          "size": 4
        },
        "explanation": "enqueue(16) — it lands in slot 3, computed as (head + size) % 6.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "s0",
            "value": 4
          },
          {
            "id": "s1",
            "value": 8
          },
          {
            "id": "s2",
            "value": 15
          },
          {
            "id": "s3",
            "value": 16
          },
          {
            "id": "s4",
            "value": 23
          },
          {
            "id": "s5",
            "value": -1
          }
        ],
        "pointers": [
          {
            "name": "head",
            "index": 0
          },
          {
            "name": "tail",
            "index": 4
          }
        ],
        "highlights": [
          {
            "index": 5,
            "role": "discarded"
          },
          {
            "index": 4,
            "role": "swap"
          }
        ],
        "codeLine": 10,
        "variables": {
          "enqueued": 23,
          "tail": 4,
          "size": 5
        },
        "explanation": "enqueue(23) — it lands in slot 4, computed as (head + size) % 6.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "s0",
            "value": -1
          },
          {
            "id": "s1",
            "value": 8
          },
          {
            "id": "s2",
            "value": 15
          },
          {
            "id": "s3",
            "value": 16
          },
          {
            "id": "s4",
            "value": 23
          },
          {
            "id": "s5",
            "value": -1
          }
        ],
        "pointers": [
          {
            "name": "head",
            "index": 1
          },
          {
            "name": "tail",
            "index": 4
          }
        ],
        "highlights": [
          {
            "index": 0,
            "role": "discarded"
          },
          {
            "index": 5,
            "role": "discarded"
          },
          {
            "index": 0,
            "role": "discarded"
          }
        ],
        "codeLine": 18,
        "variables": {
          "dequeued": 4,
          "head": 1,
          "size": 4
        },
        "explanation": "dequeue() — serve 4 from slot 0, then just move head to 1. Nothing shuffled, nothing copied. That's the O(1) an ordinary array queue can't manage.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "s0",
            "value": -1
          },
          {
            "id": "s1",
            "value": -1
          },
          {
            "id": "s2",
            "value": 15
          },
          {
            "id": "s3",
            "value": 16
          },
          {
            "id": "s4",
            "value": 23
          },
          {
            "id": "s5",
            "value": -1
          }
        ],
        "pointers": [
          {
            "name": "head",
            "index": 2
          },
          {
            "name": "tail",
            "index": 4
          }
        ],
        "highlights": [
          {
            "index": 0,
            "role": "discarded"
          },
          {
            "index": 1,
            "role": "discarded"
          },
          {
            "index": 5,
            "role": "discarded"
          },
          {
            "index": 1,
            "role": "discarded"
          }
        ],
        "codeLine": 18,
        "variables": {
          "dequeued": 8,
          "head": 2,
          "size": 3
        },
        "explanation": "dequeue() — serve 8 from slot 1, then just move head to 2. Nothing shuffled, nothing copied. That's the O(1) an ordinary array queue can't manage.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "s0",
            "value": -1
          },
          {
            "id": "s1",
            "value": -1
          },
          {
            "id": "s2",
            "value": 15
          },
          {
            "id": "s3",
            "value": 16
          },
          {
            "id": "s4",
            "value": 23
          },
          {
            "id": "s5",
            "value": 99
          }
        ],
        "pointers": [
          {
            "name": "head",
            "index": 2
          },
          {
            "name": "tail",
            "index": 5
          }
        ],
        "highlights": [
          {
            "index": 0,
            "role": "discarded"
          },
          {
            "index": 1,
            "role": "discarded"
          },
          {
            "index": 5,
            "role": "swap"
          }
        ],
        "codeLine": 10,
        "variables": {
          "enqueued": 99,
          "tail": 5,
          "size": 4
        },
        "explanation": "enqueue(99) — it lands in slot 5, computed as (head + size) % 6.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "s0",
            "value": 88
          },
          {
            "id": "s1",
            "value": -1
          },
          {
            "id": "s2",
            "value": 15
          },
          {
            "id": "s3",
            "value": 16
          },
          {
            "id": "s4",
            "value": 23
          },
          {
            "id": "s5",
            "value": 99
          }
        ],
        "pointers": [
          {
            "name": "head",
            "index": 2
          },
          {
            "name": "tail",
            "index": 0
          }
        ],
        "highlights": [
          {
            "index": 1,
            "role": "discarded"
          },
          {
            "index": 0,
            "role": "swap"
          }
        ],
        "codeLine": 10,
        "variables": {
          "enqueued": 88,
          "tail": 0,
          "size": 5
        },
        "explanation": "enqueue(88) — the tail wrapped around to slot 0, reusing space the head has already left behind. That wrap is the whole trick.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": [
          {
            "id": "s0",
            "value": 88
          },
          {
            "id": "s1",
            "value": -1
          },
          {
            "id": "s2",
            "value": 15
          },
          {
            "id": "s3",
            "value": 16
          },
          {
            "id": "s4",
            "value": 23
          },
          {
            "id": "s5",
            "value": 99
          }
        ],
        "pointers": [
          {
            "name": "head",
            "index": 2
          },
          {
            "name": "tail",
            "index": 0
          }
        ],
        "highlights": [
          {
            "index": 1,
            "role": "discarded"
          }
        ],
        "codeLine": 21,
        "variables": {
          "size": 5,
          "head": 2,
          "capacity": 6
        },
        "explanation": "The data never moved once. head and tail chase each other round the ring with % 6, and both enqueue and dequeue stay O(1) no matter how many times you go around.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "sorted"
      }
    ]
  }
}