V Talks Tech · 29 APR 2026

Data Structures #4: The Stack - Rules for Order

Stacks are Abstract Data Types following the Last-In, First-Out (LIFO) rule. Built on arrays or linked lists, they provide constant O(1) push and pop operations.

By
Vibhishan Ranga
Read
5 min
Tags
data structuresalgorithmsstacks
Cover image for Data Structures #4: The Stack - Rules for Order

So far in this series, we've looked at data structures defined by how they sit in your computer's RAM: the contiguous memory of an Array, the scattered nodes of a Linked List, and the clever indexing of a Hash Table.

Today, we look at the Stack. The Stack is slightly different; it is an Abstract Data Type (ADT). This means a stack isn't defined by where it lives in memory, but rather by the rules of how you can interact with it.

To understand a stack, imagine a heavy stack of physical books on your desk. If you want to add a new book, you place it securely on the top. If you want to read a book, you take the one directly off the top. If you want the book at the very bottom, you have to remove every single book above it first. You cannot magically slide a book out of the middle without the whole pile toppling over.

This strict rule is the defining characteristic of a stack, known as LIFO: Last-In, First-Out. The last item you put into the stack is the very first item you take out.

Under the Hood: Enforcing the Rules

Because a stack is an abstract concept, it actually has to be built on top of another data structure, usually a Dynamic Array or a Linked List. We simply restrict the operations to enforce the LIFO rule.

A stack exposes three primary operations:

  1. Push: Add an element to the top.

  2. Pop: Remove the element from the top.

  3. Peek (or Top): Look at the element on the top without removing it.

By deliberately restricting access (forbidding arbitrary insertions or deletions in the middle), we guarantee incredible performance. As long as the underlying structure is implemented correctly (like adding to the end of a dynamic array or the head of a linked list), push, pop, and peek all operate in constant O(1) time.

Language Implementations: The Wrapper Concept

Let's see how modern languages handle this abstraction. In many compiled languages, the Stack is implemented as an "Adapter" or "Wrapper" class—it takes an existing array or list and forces it to behave like a stack.

C++: std::stack (The Container Adapter)

C++ provides a specific stack adapter. By default, it wraps a std::deque (a double-ended queue), but you can tell it to wrap a std::vector or std::list if you prefer.

#include <iostream>
#include <stack>
#include <vector>

int main() {
    // A standard stack
    std::stack<int> bookStack;
    
    bookStack.push(1); // Bottom book
    bookStack.push(2);
    bookStack.push(3); // Top book
    
    std::cout << "Top book: " << bookStack.top() << std::endl; // Outputs 3
    
    bookStack.pop(); // Removes 3
    std::cout << "New top book: " << bookStack.top() << std::endl; // Outputs 2
    
    // You can also explicitly back it with a Vector (Dynamic Array)
    std::stack<int, std::vector<int>> arrayBackedStack;
    return 0;
}

Java: The Deque Interface

Java has an old java.util.Stack class, but you should almost never use it. It extends Vector, which has outdated synchronization overhead and breaks the LIFO rule by allowing index-based access.

The modern, correct way to implement a stack in Java is using the Deque (Double Ended Queue) interface, specifically the ArrayDeque implementation.

import java.util.ArrayDeque;
import java.util.Deque;

public class Main {
    public static void main(String[] args) {
        // The recommended way to create a stack in Java
        Deque<String> stack = new ArrayDeque<>();
        
        stack.push("Harry Potter");
        stack.push("Lord of the Rings");
        
        System.out.println("Top of stack: " + stack.peek()); // Lord of the Rings
        System.out.println("Removed: " + stack.pop());       // Lord of the Rings
    }
}

Internals: ArrayDeque uses a resizable array under the hood, making push and pop incredibly fast and cache-friendly.

Python: Lists as Stacks

Python doesn't have a dedicated stack primitive because its built-in list is specifically designed to act as one seamlessly.

# A standard Python list acts as a perfect stack
stack = []

stack.append("Book A") # Push
stack.append("Book B") # Push

print(f"Top book: {stack[-1]}") # Peek: Outputs 'Book B'

removed_book = stack.pop()      # Pop
print(f"Removed: {removed_book}")

Internals: Python lists are dynamic arrays.append() and pop() manipulate the very end of the array memory block, ensuring O(1) amortized performance. If you need a stack for multi-threaded environments, Python provides collections.deque.

JavaScript: Native Arrays

Similar to Python, JavaScript developers simply use standard arrays and restrict themselves to the push and pop methods.

const stack = [];

stack.push(10);
stack.push(20);

console.log(stack[stack.length - 1]); // Peek: 20
console.log(stack.pop());             // Pop: 20

Internals: The V8 Engine heavily optimizes push and pop operations on contiguous arrays, making this the most performant way to write a stack in JS.

Famous Algorithms & Tricks

Stacks are the masters of "state-tracking" and history. Because they remember the order in which things happened, they are used to solve incredibly specific programmatic problems.

  1. Valid Parentheses / Brackets: A legendary interview question. Given a string like "{[()]}", is it valid? You iterate through the string. If you see an opening bracket (, [, {, you push it onto the stack. If you see a closing bracket, you pop the top of the stack and check if it matches. If the stack is empty at the end, the string is valid.

  2. The Function Call Stack: This is how your computer actually runs code! When Function A calls Function B, the computer pushes the state (and local variables) of Function A onto the memory stack. When Function B finishes running (returns), it is popped off the stack, and the computer resumes Function A exactly where it left off.

  3. Undo/Redo Mechanisms: Every time you type a word in a text editor, that action is pushed onto an "Undo" stack. When you hit Ctrl+Z, the editor pops the top action off the stack and reverses it.

  4. The Monotonic Stack Trick: A slightly advanced but incredibly powerful algorithmic trick. A monotonic stack is simply a stack that is strictly increasing or strictly decreasing. It is the optimal way to solve "Next Greater Element" problems (e.g., "For each day in an array of temperatures, find how many days you have to wait until a warmer temperature").

Conclusion: The Power of Constraint

Sometimes, adding rules makes a system stronger. By restricting an array or linked list so that we can only touch the "top", the Stack gives us O(1) guarantees and a perfect mechanism for reversing history, evaluating mathematical expressions, and executing programs.

The Stack proves that in software engineering, you don't always need complex logic to solve a problem but sometimes, you just need a pile of books.

All posts →

Pit wall · Newsletter

Want to stay updated?

Get new posts in your inbox as soon as they're out. No spam, just the latest from V Talks Tech.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.