Stacks is a fundamental data structure in computer science that follows the LIFO principle LIFO — Last In, First Out.
That means the last element you push onto the stack is always the first one to come out.
Even though stacks sound simple, they power some of the most critical parts of modern software systems like:
In this chapter, I’ll break down:
So, what exactly is a stack?
A stack is a linear data structure that follows the Last In, First Out principle - or LIFO in short.
That simply means: The last item you add is the first one to be removed.
A simple way to picture it is like a stack of plates: You add new plates to the top… and when you need one, you take it from the top.
You can’t remove something from the middle without first removing everything above it.
That’s exactly how a stack works.
This simple rule is what makes stacks so useful. Whenever you need to access the most recently added item first, a stack is the perfect data structure.
Now that you understand what a stack is, lets walk through the common stack operations you will use:
It’s especially useful to prevent popping from an empty stack. And yes, it runs in O(1) time too.
These four operations are the foundation of everything stacks can do. And they’re all constant time, which makes stacks incredibly efficient.
So how do we actually implement a stack?
There are two main ways to implement a stack from scratch — each with its own strengths and trade-offs.
This is the most common and straightforward approach to implement a stack.
You maintain two things:
top to track the index of the last inserted element. It is initially set to -1 to represent an empty stack.With this setup, you perform all stack operations at the end of the array, which makes them run in O(1) time.
stack[top] and then decrement top.top is still at -1, which means no elements have been added yet.The main limitation of this approach is that the stack size is fixed.
Once the array is full, you can’t push new elements unless you manually resize it.
That’s why many modern languages provide dynamic arrays (like ArrayList in Java or list in Python) that handle resizing under the hood.
Another popular way to implement a stack is by using a linked list.
In this approach, the head of the linked list represents the top of the stack.
That means:
Since all operations are focused at the head, they run in O(1) time — just like the array implementation.
Since the size of linked list is dynamic, you don’t need to worry about resizing like you would with a static array.
The trade-off is that each node stores an extra pointer (next), which means more memory is used compared to a plain array.
In most real-world applications and even coding interviews, you rarely need to implement a stack from scratch. That’s because most modern programming languages already offer efficient, battle-tested stack implementations.
Java provides two main ways to work with stacks
Legacy stack class and recommended Deque interface.
ArrayDeque is faster and more memory-efficient than Stack. It supports all standard stack operations and is the preferred choice for new code.
Python doesn’t have a built-in Stack class — but you can easily use a list to simulate a stack.
Just use a list with append() for push and pop() for pop.
Python lists are dynamic arrays under the hood, so append() and pop() from the end are both O(1) operations.
C++ provides the std::stack container adapter in the Standard Template Library (STL).
These built-in options are highly optimized and cover all common use cases. Unless you're explicitly asked to implement a stack from scratch, it’s usually best to use the standard library.