LearnFrenzy
Sign in Take a free test

STL: Stack, Queue and Priority Queue · Lesson 23 of 33

stack and queue in C++ STL

6 min read Updated Nov 7, 2026 Saurabh Samir

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, top
  • std::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;
}

Output

current: cpp-stl, depth 3
back to: courses
leaving courses
leaving home

A stack after push("home"), push("courses"), push("cpp-stl")

  1. cpp-stltop – pushed last, popped first
  2. courses
  3. 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;
}

Output

{[()()]} -> balanced
([)] -> not balanced
((a + b) * c -> not balanced
v[i] = f(x); -> balanced

Next 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;
}

Output

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;
}

Output

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).

stackqueue
OrderLIFOFIFO
Addpush (to the top)push (to the back)
Looktopfront, back
Removepop (from the top)pop (from the front)
Classic usesundo, brackets, DFS, monotonic stackscheduling, BFS, buffering

Practice

Try it yourself

  1. 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;
    }

    Output

    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.

Next lesson

Popular