STL: Stack, Queue and Priority Queue · Lesson 23 of 33
stack and queue in C++ STL
A stack is last-in, first-out (LIFO): like a pile of plates, you take the one you put down last. A queue is first-in, first-out (FIFO): like a line at a counter. The STL provides both as container adapters – thin wrappers around a deque that expose only the operations that make sense. They're the backbone of undo systems, expression parsing, BFS and many interview problems.
In this lesson
std::stack: push, pop, topstd::queue: push, pop, front, back- Balanced brackets and next greater element (monotonic stack)
- Processing in order with a queue
std::stack
#include <iostream>
#include <stack>
#include <string>
int main() {
std::stack<std::string> history; // browser back button
history.push("home");
history.push("courses");
history.push("cpp-stl");
std::cout << "current: " << history.top() << ", depth " << history.size() << '\n';
history.pop(); // pop removes but returns nothing
std::cout << "back to: " << history.top() << '\n';
while (!history.empty()) { // always check empty() before top()/pop()
std::cout << "leaving " << history.top() << '\n';
history.pop();
}
return 0;
}
current: cpp-stl, depth 3 back to: courses leaving courses leaving home
A stack after push("home"), push("courses"), push("cpp-stl")
- cpp-stltop – pushed last, popped first
- courses
- homebottom – pushed first, popped last
pop() returns void
Read the value with top() (or front() for a queue) first, then call pop(). Calling top() or pop() on an empty stack is undefined behaviour.
Balanced brackets
#include <iostream>
#include <stack>
#include <string>
bool balanced(const std::string& s) {
std::stack<char> open;
for (char c : s) {
if (c == '(' || c == '[' || c == '{') {
open.push(c);
} else if (c == ')' || c == ']' || c == '}') {
if (open.empty()) return false;
char o = open.top();
open.pop();
if ((c == ')' && o != '(') || (c == ']' && o != '[') || (c == '}' && o != '{')) return false;
}
}
return open.empty(); // nothing left unclosed
}
int main() {
for (std::string s : {"{[()()]}", "([)]", "((a + b) * c", "v[i] = f(x);"}) {
std::cout << s << " -> " << (balanced(s) ? "balanced" : "not balanced") << '\n';
}
return 0;
}
{[()()]} -> balanced
([)] -> not balanced
((a + b) * c -> not balanced
v[i] = f(x); -> balancedNext greater element: the monotonic stack
For each element, find the next element to its right that's larger. Comparing every pair is O(n²); a stack that keeps "waiting" elements in decreasing order does it in O(n), because each element is pushed and popped at most once:
#include <iostream>
#include <stack>
#include <vector>
std::vector<int> next_greater(const std::vector<int>& a) {
std::vector<int> result(a.size(), -1);
std::stack<int> waiting; // indexes still waiting for a greater value
for (int i = 0; i < static_cast<int>(a.size()); i++) {
while (!waiting.empty() && a[waiting.top()] < a[i]) {
result[waiting.top()] = a[i]; // a[i] is their next greater element
waiting.pop();
}
waiting.push(i);
}
return result;
}
int main() {
std::vector<int> prices{73, 74, 75, 71, 69, 72, 76, 73};
auto ng = next_greater(prices);
for (std::size_t i = 0; i < prices.size(); i++) std::cout << prices[i] << "->" << ng[i] << ' ';
std::cout << '\n';
return 0;
}
73->74 74->75 75->76 71->72 69->72 72->76 76->-1 73->-1
Interview angle
The monotonic stack solves a whole family of problems: daily temperatures, stock span, largest rectangle in a histogram and trapping rain water. The pattern: keep a stack that's always increasing or decreasing, and pop while the new element breaks the order.
std::queue
#include <iostream>
#include <queue>
#include <string>
int main() {
std::queue<std::string> printer; // print jobs in arrival order
printer.push("report.pdf");
printer.push("photo.png");
printer.push("notes.txt");
std::cout << "next: " << printer.front() << ", last: " << printer.back() << '\n';
while (!printer.empty()) {
std::cout << "printing " << printer.front() << '\n';
printer.pop();
}
std::queue<int> q; // simulate a round-robin scheduler
for (int job : {1, 2, 3}) q.push(job);
int remaining[4] = {0, 2, 1, 3}; // time slices each job needs
while (!q.empty()) {
int job = q.front();
q.pop();
std::cout << job << ' ';
if (--remaining[job] > 0) q.push(job); // not finished: back of the line
}
std::cout << '\n';
return 0;
}
next: report.pdf, last: notes.txt printing report.pdf printing photo.png printing notes.txt 1 2 3 1 3 3
Queues model anything processed in arrival order – job schedulers, message queues, and breadth-first search, which explores a graph level by level (chapter 11).
stack | queue | |
|---|---|---|
| Order | LIFO | FIFO |
| Add | push (to the top) | push (to the back) |
| Look | top | front, back |
| Remove | pop (from the top) | pop (from the front) |
| Classic uses | undo, brackets, DFS, monotonic stack | scheduling, BFS, buffering |
Practice
Try it yourself
Evaluate the postfix expression "5 1 2 + 4 * + 3 -" with a stack.
Show solution
#include <iostream> #include <sstream> #include <stack> #include <string> int main() { std::istringstream in("5 1 2 + 4 * + 3 -"); std::stack<int> st; for (std::string tok; in >> tok;) { if (tok == "+" || tok == "-" || tok == "*") { int b = st.top(); st.pop(); int a = st.top(); st.pop(); st.push(tok == "+" ? a + b : tok == "-" ? a - b : a * b); } else { st.push(std::stoi(tok)); } } std::cout << st.top() << '\n'; return 0; }14
Quick check
What does stack::pop() return?
Nothing (void) – read top() first.
Which container does std::stack use by default?
std::deque.
Why is the monotonic stack O(n)?
Each element is pushed once and popped at most once.
Summary
- stack = LIFO (push, top, pop); queue = FIFO (push, front, back, pop).
- pop() returns nothing; check empty() first.
- Stacks solve brackets and next-greater problems; queues drive scheduling and BFS.
Interview practice: stack and queue problems.
Finished this lesson?
Mark it complete to track your progress, then carry on with the next lesson.