Data structures are the backbone of efficient software development. Selecting the right structure can dramatically improve time complexity, reduce memory usage, and simplify code maintenance. This tutorial provides a professional, language‑agnostic overview of the most essential data structures, illustrated with examples in Python, Java, and C++.
Why Data Structures Matter in Algorithm Design
Algorithms operate on data. The way data is organized determines how quickly an algorithm can access, modify, or traverse that data. Understanding the trade‑offs of each structure enables you to design solutions that meet performance, scalability, and readability goals.
The choice of data structure often has a larger impact on runtime than the choice of algorithm itself.
Core Categories of Data Structures
- Linear structures (arrays, linked lists, stacks, queues)
- Tree structures (binary trees, AVL, red‑black trees, B‑trees)
- Graph structures (adjacency lists, adjacency matrices)
- Hash‑based structures (hash tables, hash sets)
- Specialized structures (heaps, tries, disjoint sets)
Linear Data Structures
Array
An array stores elements in contiguous memory locations, providing O(1) random access. However, inserting or deleting at arbitrary positions can be O(n) due to shifting.
numbers = [10, 20, 30, 40]
print(numbers[2]) # 30
int[] numbers = {10, 20, 30, 40};
System.out.println(numbers[2]); // 30
#include <iostream>
int arr[] = {10,20,30,40};
std::cout << arr[2]; // 30
Linked List
A linked list consists of nodes where each node holds data and a reference to the next node. It excels at O(1) insertions and deletions at the head, but random access is O(n).
class Node:
def __init__(self, data, next=None):
self.data = data
self.next = next
head = Node(1, Node(2, Node(3)))
class Node {
int data;
Node next;
Node(int d) { data = d; }
}
Node head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(3);
Stack
A stack follows a Last‑In‑First‑Out (LIFO) order. Typical operations are push, pop, and peek.
stack = []
stack.append(5) # push
stack.append(10)
print(stack.pop()) # 10
Stack<Integer> stack = new Stack<>();
stack.push(5);
stack.push(10);
System.out.println(stack.pop()); // 10
Queue
A queue implements First‑In‑First‑Out (FIFO). Common operations are enqueue and dequeue.
from collections import deque
q = deque()
q.append(1) # enqueue
q.append(2)
print(q.popleft()) # 1
Queue<Integer> q = new LinkedList<>();
q.offer(1);
q.offer(2);
System.out.println(q.poll()); // 1
Tree Data Structures
Binary Search Tree (BST)
A BST stores elements in a hierarchical order: left child < parent < right child. It provides average O(log n) search, insertion, and deletion.
Self‑Balancing Trees
- AVL Tree – guarantees height difference ≤ 1
- Red‑Black Tree – guarantees longest path ≤ 2× shortest path
- B‑Tree – optimized for disk storage
Graph Data Structures
Graphs model relationships between entities. Two common representations are:
- Adjacency List – efficient for sparse graphs (O(V+E) space)
- Adjacency Matrix – constant‑time edge checks, O(V²) space
Example: BFS Traversal (Python)
from collections import deque
def bfs(graph, start):
visited = set()
q = deque([start])
while q:
v = q.popleft()
if v not in visited:
visited.add(v)
q.extend(set(graph[v]) - visited)
return visited
graph = {1:[2,3], 2:[4], 3:[4], 4:[]}
print(bfs(graph,1)) # {1,2,3,4}
Hash‑Based Structures
Hash tables map keys to values using a hash function. They provide average O(1) lookup, insertion, and deletion.
Python Dictionary Example
phone_book = {'Alice': '555‑0101', 'Bob': '555‑0123'}
print(phone_book['Alice']) # 555‑0101
Specialized Structures
Heap (Priority Queue)
A binary heap maintains the heap property (parent ≤ children for min‑heap). It supports O(log n) insert and extract‑min operations.
import heapq
heap = []
heapq.heappush(heap, 5)
heapq.heappush(heap, 2)
print(heapq.heappop(heap)) # 2
Trie (Prefix Tree)
Tries are optimized for prefix searches, such as autocomplete. Each node represents a character, and lookup is O(k) where k is the length of the key.
Comparative Summary of Common Data Structures
| Structure | Search | Insert | Delete | Space |
|---|---|---|---|---|
| Array | O(1) – indexed | O(n) | O(n) | O(n) |
| Linked List | O(n) | O(1) – head | O(1) – head | O(n) |
| Stack | O(n) | O(1) | O(1) | O(n) |
| Queue | O(n) | O(1) | O(1) | O(n) |
| BST (balanced) | O(log n) | O(log n) | O(log n) | O(n) |
| Hash Table | O(1) avg | O(1) avg | O(1) avg | O(n) |
| Binary Heap | O(n) | O(log n) | O(log n) | O(n) |
| Trie | O(k) | O(k) | O(k) | O(Σ·k) |
Best Practices and Common Pitfalls
- Prefer built‑in containers (e.g.,
list,dict,ArrayList) unless you need custom behavior. - Analyze both time and space complexity before committing to a structure.
- When dealing with large datasets, consider cache locality – arrays often outperform linked structures due to contiguous memory.
- Always handle null/empty cases to avoid
NullPointerExceptionor segmentation faults.
Further Reading & References
References
Q: When should I use a linked list instead of an array?
A: Use a linked list when you need frequent insertions/deletions at the beginning or middle of the collection and random access is not a priority.
Q: Are hash tables always faster than binary search trees?
A: Hash tables provide O(1) average lookup, but they lack ordering. If you need ordered traversal or range queries, a balanced BST is preferable despite O(log n) operations.
Q: What is the main advantage of a trie over a hash table for string keys?
A: Tries enable prefix searches and can share common prefixes, which reduces redundancy and provides O(k) lookup where k is the key length, independent of the total number of stored keys.
Q. Which data structure guarantees O(1) access to the middle element?
- Linked List
- Array
- Stack
- Heap
Answer: Array
Arrays store elements contiguously, allowing direct indexing in constant time.
Q. In a red‑black tree, what is the maximum height relative to the number of nodes n?
- log₂ n
- 2·log₂ n
- n/2
- √n
Answer: 2·log₂ n
Red‑black trees maintain a height ≤ 2·log₂ n, ensuring O(log n) operations.