🛠️ User Defined Data Structures
1. Stack (LIFO - Last In, First Out)
Definition: A linear data structure that follows the LIFO (Last In, First Out) principle. The most recently added element is the first one to be removed. Think of a stack of plates: you add to the top and remove from the top.
Operations:
push(item)
: Add item to the top.pop()
: Remove item from the top.peek()
: View the top item without removing it.
class Stack:
def __init__(self):
self.stack = []
def push(self, item):
self.stack.append(item)
def pop(self):
return self.stack.pop()
s = Stack()
s.push(1)
s.push(2)
print(s.pop()) # 2
2. Queue (FIFO - First In, First Out)
Definition: A linear data structure that follows the FIFO (First In, First Out) principle. The first item added is the first one removed. Like a line at a ticket counter.
Operations:
enqueue(item)
: Add item to the rear.dequeue()
: Remove item from the front.
from collections import deque
class Queue:
def __init__(self):
self.queue = deque()
def enqueue(self, item):
self.queue.append(item)
def dequeue(self):
return self.queue.popleft()
q = Queue()
q.enqueue(1)
q.enqueue(2)
print(q.dequeue()) # 1
3. Linked List
Definition: A linked list is a linear data structure consisting of nodes, where each node contains some data and a pointer (reference) linking it to the next node. Unlike arrays, linked lists allow dynamic memory allocation and efficient insertion and deletion operations.
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def insert(self, data):
new_node = Node(data)
new_node.next = self.head
self.head = new_node
def display(self):
curr = self.head
while curr:
print(curr.data, end=' ')
curr = curr.next
ll = LinkedList()
ll.insert(3)
ll.insert(2)
ll.insert(1)
ll.display() # 1 2 3
Types of Linked Lists:
- Singly Linked List: Nodes point only to the next node.
- Doubly Linked List: Nodes point to both previous and next.
- Circular Linked List: Last node points to the first.
1. Singly Linked List
A singly linked list is a collection of nodes, where each node has data and a pointer that points to the next node in the sequence. The last node points to null.
Structure:
[Data | Next] → [Data | Next] → [Data | Next] → null
2. Doubly Linked List
A doubly linked list is similar to a singly linked list, but each node points to both its previous and next node. This enables traversal in both directions.
null ⇄ [Prev | Data | Next] ⇄ [Prev | Data | Next] ⇄ null
3. Circular Linked List
A circular linked list is one where the nodes form a circular chain. The last node points back to the first node, creating a loop.
[Data | Next] → [Data | Next] → [Data | Next] ↑ │ └──────────────────────────────────┘
4. Tree (e.g., Binary Tree)
Definition: A hierarchical data structure with a root node and child nodes, forming a tree-like structure. Each node can have zero or more children. The most common type is the Binary Tree where each node has at most two children.
Variants:
- Binary Search Tree (BST): Left child < parent < right child
- Heap: Complete binary tree with a specific ordering
- Trie: Prefix tree used in text processing
class TreeNode:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
# Sample tree:
# 1
# / \
# 2 3
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
print(root.left.data) # 2
5. Graph (Adjacency List Representation)
Definition: A non-linear data structure consisting of nodes (vertices) and edges connecting them. Edges can be directed or undirected, and graphs can be weighted or unweighted.
class Graph:
def __init__(self):
self.graph = {}
def add_edge(self, u, v):
self.graph.setdefault(u, []).append(v)
self.graph.setdefault(v, []).append(u) # undirected
def show(self):
for node in self.graph:
print(f"{node} -> {self.graph[node]}")
g = Graph()
g.add_edge(1, 2)
g.add_edge(1, 3)
g.show()
Output:
1 -> [2, 3] 2 -> [1] 3 -> [1]