Introduction
No structure is best at everything. To choose, list the operations your program does most often, then pick the structure that makes those cheap.
You now have a toolbox. The skill that matters most is knowing which tool to pick up, and that choice is what many interview and design questions are really testing.
How it works
The cost table
| Structure | Search | Insert | Delete | Smallest | In order? |
|---|---|---|---|---|---|
| Unsorted array | O(n) | O(1) at end | O(n) | O(n) | no |
| Sorted array | O(log n) | O(n) | O(n) | O(1) | yes |
| Linked list | O(n) | O(1) at front | O(1) once found | O(n) | no |
| Balanced BST | O(log n) | O(log n) | O(log n) | O(log n) | yes (inorder) |
| Binary heap | O(n) | O(log n) | pop min: O(log n) | O(1) | no |
| Hash table | O(1) average | O(1) average | O(1) average | O(n) | no |
Matching problems to structures
| The program needs to... | Use |
|---|---|
| undo the last action, match brackets, backtrack | a stack |
| serve in arrival order, BFS | a queue |
| always take the smallest or most urgent item | a heap |
| look up by a key (a name, an ID) | a hash table |
| look up by key and list in order, or find ranges | a balanced BST |
| jump to the i-th item, little inserting | an array |
| insert and remove in the middle often | a (doubly) linked list |
| model connections: roads, friends, networks | a graph |
Small data is different. For 20 items, a plain array is often fastest of all: simple loops over memory that sits side by side are very quick on real computers. Big-O matters when n gets large.
Syntax
No new syntax is needed. A useful way to think is to write the job as a list of operations, with an estimate of how often each happens:
Lookup by student ID very often
Add a student sometimes
List students in order rarely
Example
#include <stdio.h>
int linear(int a[], int n, int key, int *steps) {
for (int i = 0; i < n; i++) {
(*steps)++;
if (a[i] == key) return i;
}
return -1;
}
int binary(int a[], int n, int key, int *steps) {
int lo = 0, hi = n - 1;
while (lo <= hi) {
(*steps)++;
int mid = (lo + hi) / 2;
if (a[mid] == key) return mid;
if (a[mid] < key) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}
int main(void) {
int a[16];
for (int i = 0; i < 16; i++) a[i] = 3 * i; // 0, 3, 6, ..., 45
int s1 = 0, s2 = 0;
linear(a, 16, 42, &s1);
binary(a, 16, 42, &s2);
printf("linear: %d comparisons, binary: %d comparisons\n", s1, s2);
return 0;
}Both functions find 42 in the same 16 sorted numbers. Linear search compares from the start; binary search halves the range each time. 15 comparisons against 4. With a million numbers it would be up to a million against 20. Keeping data sorted (or in a BST) buys fast search, at the price of slower inserts.
Line by line
linearcompareskeywith each item from the start, and(*steps)++adds one to the caller's counter.binarykeeps a range fromlotohi, and each pass adds one step.- It compares the middle item. Equal means found, and otherwise half of the range is thrown away.
mainfills 16 cells with multiples of 3, so the array is sorted.- Both searches look for 42, and each receives its own counter by address.
printfshows both counts on one line.
Expected result
linear: 15 comparisons, binary: 4 comparisons
In the real world
A database engineer picks between a B-tree index and a hash index by asking this same question: will people ask for exact matches, or ranges? Caches, routers and search engines are all designed around the operations they do most.
Common mistakes
- Picking a structure because it is familiar, without listing the operations first.
- Optimising a part of the program that runs only a few times.
- Forgetting the cost of keeping a structure sorted or balanced when it changes often.
Best practices
- Write down the operations and how often each happens.
- Prefer the simplest structure that is fast enough.
- Measure with realistic data when two choices look close.
Summary
No structure is best at everything. List the operations your program needs, compare the costs, then pick the simplest structure that makes the most common operations cheap.
Quick check
Key takeaways
- Start from the operations, not from a favourite structure.
- Keeping data ordered makes search cheap and insertion dearer.
- For small inputs, the simplest structure is often fastest.
Practice problems for this lesson
My notes
Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.