Stacks, queues & deques — across Python, Go, TypeScript & C++

Use the right end for stacks; use a real front operation for FIFO queues. End operations are O(1) on the right structure; front operations on arrays/lists are the common trap.

Stack — last in, first out

PythonGoTypeScriptC++
createst = []st := []int{}const st: number[] = []stack<int> st;
push — O(1) avgst.append(x)st = append(st, x)st.push(x)st.push(x);
pop — O(1)x = st.pop()x := st[len(st)-1]
st = st[:len(st)-1]
const x = st.pop()!x = st.top();
st.pop();
peek — O(1)x = st[-1]x := st[len(st)-1]const x = st[st.length - 1]x = st.top();
empty / size — O(1)if st: ...; len(st)len(st) == 0st.length === 0st.empty(); st.size();

FIFO queue — first in, first out

PythonGoTypeScriptC++
createfrom collections import deque
q = deque()
q := []int{}
head := 0
let q: number[] = []
let head = 0
queue<int> q;
enqueue back — O(1) avgq.append(x)q = append(q, x)q.push(x)q.push(x);
dequeue front — O(1)x = q.popleft()x := q[head]
head++
const x = q[head++]x = q.front();
q.pop();
peek front — O(1)x = q[0]x := q[head]const x = q[head]x = q.front();
empty / size — O(1)if q: ...; len(q)head == len(q)
len(q)-head
head === q.length
q.length - head
q.empty(); q.size();

Deque — both ends

PythonGoTypeScriptC++
createfrom collections import deque
d = deque()
import "container/list"
l := list.New()
const d = new Map<number, T>()
let lo = 0, hi = 0
deque<int> d;
push left — O(1)d.appendleft(x)l.PushFront(x)d.set(--lo, x)d.push_front(x);
push right — O(1) avgd.append(x)l.PushBack(x)d.set(hi++, x)d.push_back(x);
pop left — O(1)x = d.popleft()e := l.Front()
x := e.Value.(int)
l.Remove(e)
const x = d.get(lo)!
d.delete(lo++)
x = d.front();
d.pop_front();
pop right — O(1)x = d.pop()e := l.Back()
x := e.Value.(int)
l.Remove(e)
const x = d.get(--hi)!
d.delete(hi)
x = d.back();
d.pop_back();
peek ends — O(1)left, right = d[0], d[-1]l.Front().Value; l.Back().Valued.get(lo); d.get(hi - 1)d.front(); d.back();

Gotchas

PythonGoTypeScriptC++
  • list is fine for a stack; pop(0) and insert(0, x) are O(n), so use collections.deque for queues.
  • deque.pop() and deque.popleft() raise IndexError on empty; check if q: first.
  • deque is O(1) at both ends but O(n) in the middle; use list for fast random access.
  • append can reallocate; always keep the returned slice: st = append(st, x).
  • A slice queue with head++ can keep old objects alive; clear consumed slots or compact occasionally.
  • container/list is not generic; Value is any, and Front()/Back() return nil on empty.
  • push/pop are the fast stack pair; shift()/unshift() move array indexes and are O(n).
  • For FIFO queues, keep a head index instead of calling shift(); compact when head grows large.
  • pop() returns undefined on empty; check length if undefined could be a real value.
  • stack and queue are adaptors: no iteration, no indexing. Use deque directly when you need both ends.
  • pop() returns void; read with top(), front(), or back() before popping.
  • deque middle insert/erase is O(n), and mutations can invalidate iterators; do not keep iterators across edits.

Docs: https://docs.python.org/3/tutorial/datastructures.html#using-lists-as-stacks · https://docs.python.org/3/library/collections.html#collections.deque · https://pkg.go.dev/container/list · https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift · https://en.cppreference.com/w/cpp/container/deque