StudyHub

Algorithms · Linear structures

Queue

Enqueue 5, enqueue 3, then dequeue: you get 5, the first thing you put in. Enqueue 8, and the queue is 3, 8. You add at the back and remove from the front: first in, first out (FIFO). In an array, the trick is to let the front index move and wrap around.

Why it matters: enqueue and dequeue are both $O(1)$ in a circular array, and FIFO order is exactly what fair waiting lines need: print jobs, network packets, and breadth-first search.

Prerequisites

  • Arrays and indices.
  • The modulo operator %.
  • Stack, to contrast LIFO with FIFO.

The analogy

Everyday analogy

Think of a line at a bakery. New customers join at the back, and the person at the front is served first. Nobody cuts in.

A queue keeps that order. In an array we don't move the customers forward; instead the "front of the line" marker moves, and wraps back to slot 0 when it reaches the end.

How it works

Start with a sequence of operations by hand

The queue is an array of 4 slots with front = 0 and size = 0. A new item goes to slot (front + size) % 4. Predict, then open "Check".

Example: predict before you read

Step 1. enqueue 5, enqueue 3. Predict which slots they use.

Check

Slot 0 then slot 1. Now front = 0, size = 2.

Step 2. Cover the next line and guess: what does dequeue return, and does anything shift?

Check

It returns 5, the oldest item. Nothing shifts; front just moves to 1 and size becomes 1.

Step 3. enqueue 8. Predict its slot.

Check

(1 + 1) % 4 = 2. The queue, front to back, is 3, 8.

Circular array queue of capacity 4 after enqueue 5, enqueue 3, dequeue, enqueue 8; the front slot is highlighted
What you just did by hand: the yellow box is the front. Dequeue doesn't shift anything; the front marker moves.

Quick recall: Before reading further, cover the text above and say out loud: why doesn't dequeue shift the remaining items forward?

Check your answer

Because the front index moves instead. Shifting would cost $O(n)$; moving one index costs $O(1)$.

Finish the picture: wrapping around

Continue from front = 1, holding 3, 8 in slots 1 and 2. Enqueue 1, then 2.

  • Enqueue 1. Predict its slot.
    Check

    (1 + 2) % 4 = 3, the last slot.

  • Enqueue 2. Predict its slot: the array looks full at the end.
    Check

    (1 + 3) % 4 = 0: it wraps to slot 0, which was freed by the earlier dequeue. The queue is now full: 3, 8, 1, 2.

Quick recall: Without scrolling up, say out loud: why did the item 2 go into slot 0?

Check your answer

Slot (front + size) % 4 was past the end, so it wrapped around to the free slot at the start.

The rule in plain words

Keep the items in an array with two numbers: front (index of the oldest item) and size.

enqueue writes at (front + size) % capacity. dequeue reads at front and moves it forward, wrapping with %.

Quick recall: Before you read the code, write the steps of enqueue and dequeue in your own words. Then check below.

Check your answer

enqueue: write at (front + size) % capacity, then add 1 to size. dequeue: read at front, move front one step with wrap-around, subtract 1 from size.

The code

Read this code after you have done the operations by hand. It will make more sense.

typedef struct { int data[4]; int front, size; } Queue;   /* capacity 4 */

void enqueue(Queue *q, int v) {            /* caller checks q->size < 4 */
    q->data[(q->front + q->size) % 4] = v;
    q->size++;
}

int dequeue(Queue *q) {                    /* caller checks q->size > 0 */
    int v = q->data[q->front];
    q->front = (q->front + 1) % 4;         /* wrap around */
    q->size--;
    return v;
}

Definition

What you just did, in one line: a queue is a first-in, first-out (FIFO) collection: you enqueue at the back and dequeue from the front.

A circular buffer stores it in an array whose indices wrap around.

flowchart LR
  IN["enqueue"] --> R["back: 8"]
  R --- M["3"]
  M --> F["front: 3 leaves first"]
  F --> OUT["dequeue"]
          
Before you scroll past this diagram, cover the right side and guess: after enqueue 1 and one dequeue on the queue 3, 8, which item leaves? (Answer: 3, the oldest.)

How fast is it?

Quick recall: Before looking at the table, predict: what would dequeue cost if we always kept the front at slot 0?

Check your answer

$O(n)$, because every remaining item would shift one slot left.

Both operations do a fixed amount of index arithmetic. The slot for the next item is:

$$\text{slot} \;=\; (\text{front} + \text{size}) \bmod \text{capacity}$$

No loop runs, so enqueue and dequeue are $O(1)$ however many items are waiting.

OperationCostWhy
enqueue$O(1)$One write at the computed slot
dequeue$O(1)$One read, the front index moves
front / is_empty$O(1)$Read front or size
dequeue in a naive array (shift left)$O(n)$Every item moves one slot
Search for a value$O(n)$Not a queue operation

Warning

Keep a size (or leave one slot empty). With only front and back indices, a full queue and an empty queue look the same: front == back in both cases.

Exam tip

Trace questions use the formula $(\text{front} + \text{size}) \bmod \text{capacity}$. Write front, size and the array after every operation.

Common mistakes

  • Shifting all items on dequeue, which turns $O(1)$ into $O(n)$.
  • Forgetting the % capacity wrap, which writes past the end of the array.
  • Being unable to tell "full" from "empty" because no size is stored.

Try it yourself

Exercise 1 (warm-up)

Starting empty: enqueue 1, enqueue 2, dequeue, enqueue 3, dequeue. Which values are dequeued?

Hint

The oldest item always leaves first.

Answer

1, then 2. The queue ends holding 3.

Exercise 2 (a bit harder)

With capacity 4, start empty and do: enqueue A, B, C; dequeue; dequeue; enqueue D, E. Give front, size and the slot of E. Write your answer down before you open it.

Show answer

After A, B, C: front 0, size 3. Two dequeues: front 2, size 1. D goes to (2+1)%4 = 3, E to (2+2)%4 = 0. Final: front 2, size 3, E in slot 0.

Did you know?

Did you know?

Breadth-first search, the graph algorithm that finds shortest paths in unweighted graphs, is a queue loop: dequeue a node, enqueue its unvisited neighbours.

Your keyboard, network card and printer all use circular buffers like this one, so data arriving faster than it's processed waits in order instead of getting lost.

Key points to remember

If you remember one thing from each line, remember the because.

  • The oldest item leaves first because items are added at the back and removed from the front.
  • Dequeue is $O(1)$ because the front index moves instead of the items.
  • The array is used in a circle because % capacity sends indices past the end back to slot 0.
  • A size counter is needed because otherwise full and empty look identical.
  • BFS uses a queue because nodes must be processed in the order they were discovered.

Self-check questions

Answer these in order, out loud. They follow the page, so your answers become the script of your video.

  1. How is a queue like a line at a bakery?
    Sample answer

    People join at the back and are served from the front, so the first to arrive is the first to leave.

  2. Walk through enqueue 5, enqueue 3, dequeue, enqueue 8 in a 4-slot circular array.
    Sample answer

    5 goes to slot 0, 3 to slot 1; dequeue returns 5 and moves front to 1; 8 goes to slot (1+1)%4 = 2. The queue is 3, 8.

  3. Why does the code use % 4 when computing slots?

    A good answer mentions the end of the array.

    Sample answer

    When an index passes the last slot, % 4 wraps it back to slot 0, reusing the space freed by earlier dequeues.

  4. So what is a queue, in one sentence?
    Sample answer

    A first-in, first-out collection with enqueue at the back and dequeue at the front.

  5. Why is a circular buffer better than shifting items forward?

    A good answer compares the costs.

    Sample answer

    Shifting moves every remaining item on each dequeue, which is $O(n)$. Moving the front index is $O(1)$.

  6. What do enqueue, dequeue and front cost?
    Sample answer

    All three are $O(1)$ in a circular array.

  7. How do you tell a full queue from an empty one?
    Sample answer

    Store the size: empty is size 0, full is size equal to the capacity. With only two indices both cases would look like front == back.

  8. If you had to teach this to a friend in 2 minutes, what would you leave out, and why?
    Sample answer

    I'd leave out the full-versus-empty detail and the exact modulo trace. I'd keep the bakery analogy, the enqueue/dequeue sequence, and "FIFO, $O(1)$ with a circular array, used by BFS".

External resources

Videos

Review schedule

Come back after 3, 7, 14, then 30 days. Spacing beats cramming.

Feynman prompt

Explain this topic in your own words, as if teaching a beginner.

Explain it in your own words first, then record a 2–3 minute video on your phone.

25:00

Ready to record? Open your phone camera now and record a 2–3 minute explanation.

My notes

Saved only in this browser (localStorage). Nothing is uploaded.