Stack - Linked List Implementation
To implement a stack using a singly linked list, we follow the LIFO (Last In, First Out) principle by inserting and removing elements from the head of the list, where each node stores data and a pointer to the next node.
In the stack Implementation, a stack contains a top pointer. which is the "head" of the stack where pushing and popping items happens at the head of the list. The first node has a null in the link field and second node-link has the first node address in the link field and so on and the last node address is in the "top" pointer.
- The main advantage of using a linked list over arrays is that it is possible to implement a stack that can shrink or grow as much as needed.
- Using an array will put a restriction on the maximum capacity of the array which can lead to stack overflow. Here each new node will be dynamically allocated. so overflow is not possible.
- If we use built in dynamic sized arrays like vector in C++, list in Python or ArrayList in Java, we get automatically growing stack, but the worst case time complexity is not O(1) for push() and pop() as there might be a resizing step once in a while. With Linked List, we get worst case O(1).
Stack Operations
- push(): Insert a new element into the stack (i.e just insert a new element at the beginning of the linked list.)
- pop(): Return the top element of the Stack (i.e simply delete the first element from the linked list.)
- peek(): Return the top element.
- display(): Print all elements in Stack.
Push Operation
- Initialise a node
- Update the value of that node by data i.e. node->data = data
- Now link this node to the top of the linked list
- And update top pointer to the current node
Pop Operation
- First Check whether there is any node present in the linked list or not, if not then return
- Otherwise make pointer let say temp to the top node and move forward the top node by 1 step
- Now free this temp node
Peek Operation
- Check if there is any node present or not, if not then return.
- Otherwise return the value of top node of the linked list
Display Operation
- Take a temp node and initialize it with top pointer
- Now start traversing temp till it encounters NULL
- Simultaneously print the value of the temp node
#include <bits/stdc++.h>
using namespace std;
// Node structure
class Node {
public:
int data;
Node* next;
Node(int new_data) {
this->data = new_data;
this->next = nullptr;
}
};
// Stack using linked list
class Stack {
Node* head;
public:
Stack() {
this->head = nullptr;
}
// Check if stack is empty
bool isEmpty() {
return head == nullptr;
}
// Push an element onto stack
void push(int new_data) {
Node* new_node = new Node(new_data);
new_node->next = head;
head = new_node;
}
// Pop the top element
void pop() {
if (isEmpty()) return;
Node* temp = head;
head = head->next;
delete temp;
}
// Return the top element
int peek() {
if (!isEmpty()) return head->data;
return INT_MIN;
}
};
int main() {
Stack st;
st.push(11);
st.push(22);
st.push(33);
st.push(44);
cout << st.peek() << endl;
st.pop();
st.pop();
cout << st.peek() << endl;
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// Node structure
struct Node {
int data;
struct Node* next;
};
// Check if stack is empty
int isEmpty(struct Node* head) {
return head == NULL;
}
// Push an element onto stack
void push(struct Node** head, int new_data) {
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = *head;
*head = new_node;
}
// Pop the top element
void pop(struct Node** head) {
if (isEmpty(*head)) return;
struct Node* temp = *head;
*head = (*head)->next;
free(temp);
}
// Return the top element
int peek(struct Node* head) {
if (!isEmpty(head)) return head->data;
return INT_MIN;
}
int main() {
struct Node* head = NULL;
push(&head, 11);
push(&head, 22);
push(&head, 33);
push(&head, 44);
printf("%d\n", peek(head));
pop(&head);
pop(&head);
printf("%d\n", peek(head));
return 0;
}
class Node {
int data;
Node next;
Node(int new_data) {
this.data = new_data;
this.next = null;
}
}
// Stack using linked list
class Stack {
Node head;
Stack() {
this.head = null;
}
// Check if stack is empty
boolean isEmpty() {
return head == null;
}
// Push an element onto stack
void push(int new_data) {
Node new_node = new Node(new_data);
new_node.next = head;
head = new_node;
}
// Pop the top element
void pop() {
if (isEmpty()) return;
head = head.next;
}
// Return the top element
int peek() {
if (!isEmpty()) return head.data;
return Integer.MIN_VALUE;
}
}
public class Main {
public static void main(String[] args) {
Stack st = new Stack();
st.push(11);
st.push(22);
st.push(33);
st.push(44);
System.out.println(st.peek());
st.pop();
st.pop();
System.out.println(st.peek());
}
}
# Node structure
class Node:
def __init__(self, new_data):
self.data = new_data
self.next = None
# Stack using linked list
class Stack:
def __init__(self):
self.head = None
# Check if stack is empty
def isEmpty(self):
return self.head is None
# Push an element onto stack
def push(self, new_data):
new_node = Node(new_data)
new_node.next = self.head
self.head = new_node
# Pop the top element
def pop(self):
if self.isEmpty():
return
self.head = self.head.next
# Return the top element
def peek(self):
if not self.isEmpty():
return self.head.data
return float('-inf')
st = Stack()
st.push(11)
st.push(22)
st.push(33)
st.push(44)
print(st.peek())
st.pop()
st.pop()
print(st.peek())
using System;
// Node structure
class Node {
public int data;
public Node next;
public Node(int new_data) {
this.data = new_data;
this.next = null;
}
}
// Stack using linked list
class Stack {
Node head;
public Stack() {
this.head = null;
}
// Check if stack is empty
public bool isEmpty() {
return head == null;
}
// Push an element onto stack
public void push(int new_data) {
Node new_node = new Node(new_data);
new_node.next = head;
head = new_node;
}
// Pop the top element
public void pop() {
if (isEmpty()) return;
head = head.next;
}
// Return the top element
public int peek() {
if (!isEmpty()) return head.data;
return int.MinValue;
}
}
class Program {
static void Main() {
Stack st = new Stack();
st.push(11);
st.push(22);
st.push(33);
st.push(44);
Console.WriteLine(st.peek());
st.pop();
st.pop();
Console.WriteLine(st.peek());
}
}
// Node structure
class Node {
constructor(new_data) {
this.data = new_data;
this.next = null;
}
}
// Stack using linked list
class Stack {
constructor() {
this.head = null;
}
// Check if stack is empty
isEmpty() {
return this.head === null;
}
// Push an element onto stack
push(new_data) {
let new_node = new Node(new_data);
new_node.next = this.head;
this.head = new_node;
}
// Pop the top element
pop() {
if (this.isEmpty()) return;
this.head = this.head.next;
}
// Return the top element
peek() {
if (!this.isEmpty()) return this.head.data;
return Number.MIN_SAFE_INTEGER;
}
}
let st = new Stack();
st.push(11);
st.push(22);
st.push(33);
st.push(44);
console.log(st.peek());
st.pop();
st.pop();
console.log(st.peek());
Output
44 22
Time Complexity: O(1), for all push(), pop(), and peek(), as we are not performing any kind of traversal over the list.
Auxiliary Space: O(n), where n is the size of the stack
Benefits of implementing a stack using a singly linked list
- Dynamic memory allocation: The size of the stack can be increased or decreased dynamically by adding or removing nodes from the linked list, without the need to allocate a fixed amount of memory for the stack upfront.
- Efficient memory usage: Since nodes in a singly linked list only have a next pointer and not a prev pointer, they use less memory than nodes in a doubly linked list.
- Easy implementation: Implementing a stack using a singly linked list is straightforward and can be done using just a few lines of code.
- Versatile: Singly linked lists can be used to implement other data structures such as queues, linked lists, and trees.
Real time examples of stack
Stacks are used in various real-world scenarios where a last-in, first-out (LIFO) data structure is required. Here are some examples of real-time applications of stacks:
- Function Call Stack: When a function is called, its return address and parameters are pushed onto the stack. The stack ensures functions execute and return in reverse order..
- Undo/Redo Operations: In apps like text or image editors, actions are pushed onto a stack. Undo removes the last action, while redo restores it.
- Browser History: Browsers use stacks to track visited pages. Visiting a page pushes its URL onto the stack, and the "Back" button pops the last URL to go to the previous page.
- Expression Evaluation: In compilers, expressions are converted to postfix notation and evaluated using a stack.
- Call Stack in Recursion: Recursive function calls are pushed onto the stack. Once recursion ends, the stack is popped to return to the previous function call.

Linked List Implementation of Stack in C++

Linked List Implementation of Stack in Java
