A STACK, or Stack, is a collection of elements used to organize and manipulate elements in a specific order.
A STACK is also called a LIFO (Last-In, First-Out) structure because it follows the principle that the last element added (Last-In) is the first one to be removed (First-Out).
Every time a new element is added to the STACK, it is placed on top. When an element is removed, the last element added is taken out.
This is achieved through two main operations:
- Push: Adds an element to the top of the stack.
- Pop: Removes and returns the element from the top of the stack.
In addition to these basic operations, other operations can also be performed on a STACK, such as checking if it is empty or accessing the top element without removing it.
There are multiple ways to implement a STACK. Generally, a simple Array is used, as it is very efficient for adding and removing the last element.
Properties
Property | Stacks |
---|---|
Frequency of use | 🔻🔻 |
Is mutable | ✔️ |
Is ordered | ✔️ |
Is indexable | ❌ |
Allows duplicates | ✔️ |
When to use a Stack
It makes sense to use a STACK when storing elements during a process that we will later unwind, as it is likely that we will need the elements in reverse order.
A STACK is similar to a stack of physical objects, like a stack of plates, where you can only access the top element. For example, you take the clothes out of the washing machine and stack them up. When you go to pick them up again, you take them in reverse order.
I like to illustrate the use of a stack when disassembling a machine. You remove screws and keep them organized. When you reassemble it, you will need the first screw you removed first. This illustrates the purpose of a stack.
In computing, for example, we have the case of the memory STACK. Every time one function calls another, it passes parameters on a Stack. When the functions finish, the parameters are needed in the reverse order they were put in.
This is not the only example. Whenever you need to store elements throughout a process that you later have to traverse in reverse order, a Stack might fit your needs.
Stack Example in Different Programming Languages
Below are examples of how to implement a stack in different programming languages:
C# has a native Stack called Stack
. So we simply have to use it like this.
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
Stack<int> stack = new Stack<int>();
stack.Push(5);
stack.Push(10);
stack.Push(15);
int topElement = stack.Pop(); // Returns 15
Console.WriteLine(topElement);
}
}
C++ also has a native Stack called stack<T>
, which we can use directly,
#include <iostream>
#include <stack>
using namespace std;
int main()
{
stack<int> stack;
stack.push(5);
stack.push(10);
stack.push(15);
int topElement = stack.top(); // Returns 15
stack.pop();
cout << topElement << endl;
return 0;
}
On the other hand, JavaScript does not have a native Stack. So we can either look for an existing one in a library or implement it ourselves like this,
class Stack {
constructor() {
this.stack = [];
}
push(element) {
this.stack.push(element);
}
pop() {
return this.stack.pop();
}
peek() {
return this.stack[this.stack.length - 1];
}
isEmpty() {
return this.stack.length === 0;
}
}
const stack = new Stack();
stack.push(5);
stack.push(10);
stack.push(15);
const topElement = stack.pop(); // Returns 15
console.log(topElement);
Python also does not have a native Stack. So we can either look for an existing one in a library or implement it ourselves like this,
class Stack:
def __init__(self):
self.stack = []
def push(self, element):
self.stack.append(element)
def pop(self):
return self.stack.pop()
def peek(self):
return self.stack[-1]
def is_empty(self):
return len(self.stack) == 0
stack = Stack()
stack.push(5)
stack.push(10)
stack.push(15)
top_element = stack.pop() # Returns 15
print(top_element)
In the previous examples, we show how to create a stack using the data structures provided by each programming language. Operations for inserting, removing, and accessing the top element of the stack are performed. Conclusions
Efficiency
The efficiency of a STACK will depend on how it has been implemented internally (but let’s assume it has been implemented “well”).
Reading and removing elements in a STACK is done in constant time O(1)
since the last added element is accessed.
Inserting into a STACK is also efficient, as it is added to the end of the stack in constant time O(1)
.
Operation | Stack |
---|---|
Sequential access | ⚫ |
Random access | ⚫ |
Add to beginning | ⚫ |
Remove from beginning | ⚫ |
Add to end | 🟢 |
Remove from end | 🟢 |
Random insertion | ⚫ |
Random removal | ⚫ |
Search | ⚫ |
The rest of the operations do not make sense since you can only access the element at the top of the STACK. You cannot access elements in intermediate positions without popping all the elements above.