Stacks, queues and deques
Access rules rather than layouts: a stack adds and removes at one end (last in, first out), a queue adds at the back and removes at the front (first in, first out), and a deque does both at both ends.
How they work
MIT’s 6.006 notes define these as special cases of a sequence: a stack only inserts and deletes at the end, a queue inserts at the end and deletes at the front. Any layout that makes those ends O(1) will do. A dynamic array is a fine stack, since append and pop at the end are amortized O(1). It is a poor queue: removing from the front shifts everything, so Python’s tutorial says lists “are not efficient for this purpose” and points to collections.deque, which appends and pops at either end in about O(1).
Deques avoid the shifting in one of two ways. Rust’s VecDeque is a growable ring buffer and Java’s ArrayDeque a resizable array, with most operations in amortized constant time. CPython’s deque is a doubly linked list of arrays, and C++’s std::deque typically uses a sequence of separately allocated fixed-size arrays, with O(1) random access and O(1) insertion at either end; the price is a large minimum footprint, since a std::deque holding one element allocates a whole block (for example 4096 bytes or 16 elements, whichever is larger, on 64-bit libc++).
Java’s docs say ArrayDeque is likely faster than Stack when used as a stack and faster than LinkedList when used as a queue, and recommend Deque over the old Stack class. C++’s std::stack is an adaptor over another container, std::deque by default. In Rust, Vec is the stack and VecDeque the queue; in Go a slice serves as a stack.
Sources
- MIT 6.006 Introduction to Algorithms (Spring 2020), Lecture 2 notes: Data Structures (stack and queue interfaces)
- Python tutorial: Data Structures, Using Lists as Stacks and as Queues
- Python docs: collections.deque (O(1) appends and pops at either end; O(n) for list.pop(0))
- Python wiki: TimeComplexity (collections.deque is a doubly linked list of arrays)
- Rust std docs: VecDeque (a double-ended queue implemented with a growable ring buffer)
- Java SE 21 API: ArrayDeque
- Java SE 21 API: Stack (Deque should be used in preference)
- cppreference: std::deque (complexity and minimum memory cost)
- cppreference: std::stack (container adaptor, std::deque by default)
- Rust std docs: std::collections (use a Vec for a stack, a VecDeque for a queue)