Stacks & Their Applications

স্ট্যাক ও তার ব্যবহার

Read: ~35 min Intermediate 7 practice problems Live code runner

1. LIFO — Last In, First Out

A stack only allows access to the most recently added element. Three operations: push(x) adds, pop() removes the top, top() peeks. All O(1). Think of a stack of plates — you can only take from the top.

Stack হলো প্লেটের স্তূপ। শেষ প্লেটটাই সবার আগে নিতে হয় — এই LIFO ধারণা থেকেই অসংখ্য অ্যালগরিদম তৈরি হয়। CPU-র call stack, browser-এর Back button, text editor-এর Undo — সব কিছুর ভিত্তি stack।
10 ← bottom 20 30 40 ← TOP push / pop here Figure 9.1 — Stack of integers. push(40) added the top; pop() would remove 40 next.

2. Implementing a Stack

std::stack wraps std::deque, but we'll build one over std::vector to see the inside.

my_stack.cpp
#include <bits/stdc++.h>
using namespace std;

template<class T>
struct Stack {
    vector<T> v;
    void push(const T& x) { v.push_back(x); }
    void pop()             { v.pop_back(); }
    T&   top()             { return v.back(); }
    bool empty() const   { return v.empty(); }
    size_t size() const  { return v.size(); }
};

int main() {
    Stack<int> s;
    for (int x : {10, 20, 30, 40}) s.push(x);
    while (!s.empty()) {
        cout << s.top() << " ";
        s.pop();
    }
}

Output: 40 30 20 10 — reverse insertion order.

3. Killer App #1: Balanced Parentheses

Every (, {, [ goes on the stack. Each closing bracket must match the top. Empty stack at the end ⇒ balanced.

balanced.cpp
#include <bits/stdc++.h>
using namespace std;

bool balanced(const string& s) {
    stack<char> st;
    unordered_map<char,char> mate = { {')','('}, {']','['}, {'}','{'} };
    for (char c : s) {
        if (c == '(' || c == '[' || c == '{') st.push(c);
        else if (mate.count(c)) {
            if (st.empty() || st.top() != mate[c]) return false;
            st.pop();
        }
    }
    return st.empty();
}

int main() {
    for (string t : {"({[]})", "(([", "[(])", ""}) {
        cout << "\"" << t << "\" → " << (balanced(t) ? "OK" : "NO") << "\n";
    }
}
প্রতিটি opening bracket stack-এ যায়, প্রতিটি closing bracket-এর সাথে top match করতে হয়। শেষে stack খালি হলেই balanced। এত সহজ অ্যালগরিদম, অথচ পৃথিবীর সব কম্পাইলার এটি ব্যবহার করে।

4. Killer App #2: Monotonic Stack — Next Greater Element

For each element, find the next greater element to its right in O(n). Trick: keep a decreasing stack of indices. When the current element exceeds the index on top, that top found its answer.

Pattern "Next/previous greater/smaller in O(n)" → monotonic stack. Each index is pushed and popped at most once.

5. Other Classic Stack Applications

ProblemStack idea
Infix → Postfix (Shunting-yard)Operator stack with precedence comparison
Evaluate PostfixOperand stack — pop two, apply op, push back
Function call stackEach call pushes a frame; return pops
Editor undo / browser backPush every action; pop to undo
DFS on graphsImplicit recursive stack OR explicit std::stack
Largest Rectangle in HistogramMonotonic increasing stack of bar indices

6. Practice Problems

  1. Find the next greater element for every entry of an array, using a monotonic stack in O(n).
    প্রতিটি element-এর পরের বড় element O(n)-এ বের করুন।
    ✨ Show Answer (উত্তর দেখুন)
    a1.cpp
    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        vector<int> a = {2, 1, 2, 4, 3};
        int n = a.size();
        vector<int> ans(n, -1);
        stack<int> st;
        for (int i = 0; i < n; i++) {
            while (!st.empty() && a[st.top()] < a[i]) {
                ans[st.top()] = a[i]; st.pop();
            }
            st.push(i);
        }
        for (int x : ans) cout << x << " ";
    }
  2. Evaluate a postfix expression like "3 4 + 5 *".
    postfix expression evaluate করুন।
    ✨ Show Answer (উত্তর দেখুন)
    a2.cpp
    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        string e = "3 4 + 5 *";
        stack<long long> st;
        stringstream ss(e); string tok;
        while (ss >> tok) {
            if (isdigit(tok[0])) st.push(stoll(tok));
            else {
                long long b = st.top(); st.pop();
                long long a = st.top(); st.pop();
                if (tok == "+") st.push(a+b);
                else if (tok == "-") st.push(a-b);
                else if (tok == "*") st.push(a*b);
                else st.push(a/b);
            }
        }
        cout << st.top();
    }
  3. Sort a stack using only one extra stack (no other arrays).
    শুধু একটি অতিরিক্ত stack ব্যবহার করে একটি stack sort করুন।
    ✨ Show Answer (উত্তর দেখুন)
    a3.cpp
    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        stack<int> in, out;
        for (int x : {3, 1, 4, 1, 5, 9, 2, 6}) in.push(x);
        while (!in.empty()) {
            int t = in.top(); in.pop();
            while (!out.empty() && out.top() > t) {
                in.push(out.top()); out.pop();
            }
            out.push(t);
        }
        while (!out.empty()) { cout << out.top() << " "; out.pop(); }
    }
  4. Implement a Min-Stack with O(1) getMin().
    O(1)-এ min দেওয়া Min-Stack implement করুন।
    ✨ Show Answer (উত্তর দেখুন)
    a4.cpp
    #include <bits/stdc++.h>
    using namespace std;
    struct MinStack {
        stack<pair<int,int>> st;   // (val, currentMin)
        void push(int x) {
            int m = st.empty() ? x : min(x, st.top().second);
            st.push({x, m});
        }
        void pop()         { st.pop(); }
        int top()          { return st.top().first; }
        int getMin()       { return st.top().second; }
    };
    int main() {
        MinStack ms;
        for (int x : {5, 3, 7, 2, 8}) ms.push(x);
        cout << "min = " << ms.getMin();
    }
  5. Largest rectangle in a histogram (O(n) with monotonic stack).
    Histogram-এ সবচেয়ে বড় rectangle — O(n) monotonic stack দিয়ে।
    ✨ Show Answer (উত্তর দেখুন)
    a5.cpp
    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        vector<int> h = {2,1,5,6,2,3};
        h.push_back(0);
        stack<int> st;
        int best = 0;
        for (int i = 0; i < (int)h.size(); i++) {
            while (!st.empty() && h[st.top()] > h[i]) {
                int top = st.top(); st.pop();
                int w = st.empty() ? i : i - st.top() - 1;
                best = max(best, h[top] * w);
            }
            st.push(i);
        }
        cout << best;
    }
  6. Daily temperatures: for each day, how many days until a warmer one?
    প্রতিটি দিনের জন্য — পরের warmer দিন কতদিন পর?
    ✨ Show Answer (উত্তর দেখুন)
    a6.cpp
    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        vector<int> t = {73,74,75,71,69,72,76,73};
        vector<int> ans(t.size(), 0);
        stack<int> st;
        for (int i = 0; i < (int)t.size(); i++) {
            while (!st.empty() && t[st.top()] < t[i]) {
                ans[st.top()] = i - st.top(); st.pop();
            }
            st.push(i);
        }
        for (int x : ans) cout << x << " ";
    }
  7. Determine if a sequence of pushes (1..n in order) and pops can produce a given output sequence.
    push order 1..n দিয়ে — দেওয়া pop order সম্ভব কিনা যাচাই করুন।
    ✨ Show Answer (উত্তর দেখুন)
    a7.cpp
    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        vector<int> out = {4,5,3,2,1};
        int n = out.size(), nxt = 1, j = 0;
        stack<int> st;
        while (j < n) {
            if (!st.empty() && st.top() == out[j]) { st.pop(); j++; }
            else if (nxt <= n) { st.push(nxt++); }
            else break;
        }
        cout << (j == n ? "YES" : "NO");
    }

Summary — Module 09

A stack is just push / pop / top, but it powers parsers, compilers, DFS, undo systems, and a whole family of monotonic-stack tricks for "next greater" problems. The pattern: when a single direction matters, reach for a stack first.

Stack ছোট কিন্তু শক্তিশালী। parser, undo, DFS, monotonic stack — সব ক্ষেত্রেই এটি কাজ করে। "next greater / smaller" pattern দেখলেই stack-এর কথা মনে রাখবেন।

Next Module → Queues, Deques & Priority Queues — FIFO ও তার variants।