Skip to main content

Stacks, Queues & Deques

intermediate14 min readLesson 111 of 148

The constrained interfaces that make linked structures useful: LIFO, FIFO, and both-ends.

Constraints are the feature

A stack is a list you may only touch at one end. A queue is a list you may only append at one end and remove from the other. The constraint is what makes reasoning possible โ€” and the implementation is where the costs live:

  • Stack: head-insert, head-remove. O(1) with a singly-linked list. Nothing else needed.
  • Queue: append at tail, remove at head. With a singly-linked list that means keeping a tail pointer too โ€” and the discipline that every append updates it (tail->next = n; tail = n; and when the queue was empty, head = tail = n).
  • Deque: both ends. A singly-linked list cannot remove from the tail in O(1) โ€” you need a doubly-linked list (or sentinel ring).

The empty/one-element boundary, again

Every queue bug in the wild is one of: append to empty queue forgetting to set head; pop to empty forgetting to clear tail; or popping the last element leaving a stale tail. Write the two-element invariant in a comment โ€” head == NULL <=> tail == NULL โ€” and test the boundary: push one, pop one, push again.

Ownership stays the same

The container owns its nodes; values are copied in and out by value (or borrowed pointers with documented loans). destroy walks and frees exactly once โ€” the same discipline as any list, now wrapped in the constrained API.

Now practice

Doubly List & Deque GymSentinel ring list with O(1) push/pop at both ends.1 challenge ยท ยท ~26 min