Searching & Sorting
dsa.fetehadin.comCheck every item from left to right until you find the key or run out. Works on any array, sorted or not, but costs O(n).
| Best case | O(1): key at index 0 |
| Average case (found) | (n + 1)/2 comparisons → O(n) |
| Worst case | O(n): last item or not present |
| Needs sorted data? | No |
| Space | O(1) |
- ✗Returning
-1inside the loop (in anelse), which stops after checking only the first item. - ✗Looping with
i <= n, one past the end. - ✗Forgetting that an unsorted array cannot use binary search.
On a sorted array, check the middle, then throw away the half that cannot contain the key. Each step halves the problem, so it takes O(log n).
| Best case | O(1): key is at the first mid |
| Average / worst case | O(log n): about ⌊log₂ n⌋ + 1 comparisons |
| 1,000,000 items | at most 20 comparisons |
| Needs sorted data? | Yes, and random access (an array, not a linked list) |
| Space | O(1) iterative · O(log n) recursive (call stack) |
- ✗Using
while (low < high)instead oflow <= high. That misses a key when one item is left. - ✗Setting
low = midorhigh = midinstead ofmid ± 1, which can loop forever. - ✗Running it on unsorted data. The result is meaningless.
Find the smallest remaining item and swap it to the front. Repeat. Simple, at most n − 1 swaps, but always O(n²) comparisons.
| Best case | O(n²): it still scans for the minimum every pass |
| Average case | O(n²) |
| Worst case | O(n²): n(n−1)/2 comparisons |
| Swaps | at most n − 1 (the fewest of the simple sorts) |
| Space | O(1) |
| Stable · in-place | no · yes |
- ✗Swapping inside the inner loop every time a smaller item is found. Swap once, after the inner loop.
- ✗Starting the inner loop at
j = iinstead ofj = i + 1(compares an item with itself). - ✗Claiming selection sort has an O(n) best case. It has none; it always scans.
Compare neighbours and swap them if they are out of order. After each pass the biggest remaining item has "bubbled" to the end.
| Best case (already sorted) | O(n): one pass, no swaps, stop |
| Average case | O(n²) |
| Worst case (reversed) | O(n²): n(n−1)/2 comparisons and swaps |
| Space | O(1) |
| Stable · in-place | yes · yes |
- ✗Looping
jup ton - 1in every pass instead ofn - 1 - i. It still works, but does useless comparisons. - ✗Writing
a[j] >= a[j+1]. Swapping equal items breaks stability. - ✗Reading past the array with
j < nand then accessinga[j + 1].
Grow a sorted part on the left by inserting each new item into its correct place, like sorting cards in your hand. Fast on nearly sorted data.
| Best case (already sorted) | O(n): n − 1 comparisons, 0 shifts |
| Average case | O(n²) |
| Worst case (reversed) | O(n²): n(n−1)/2 comparisons and shifts |
| Space | O(1) |
| Stable · in-place | yes · yes |
- ✗Writing
a[j] >= keyin the while loop. That breaks stability. - ✗Forgetting
j >= 0in the loop condition, which readsa[-1]. - ✗Putting
a[j + 1] = keyinside the while loop. It goes after the loop.
When records are big, don't move them. Sort an array of pointers (or indices) to the records instead, and only small addresses get swapped.
| Comparisons | same as the underlying sort (here selection: n(n−1)/2) |
| Data moved per swap | one pointer (8 bytes) instead of one whole record |
| Time | O(n²) with selection sort; O(n log n) with a fast sort |
| Space | O(n) for the pointer array |
| Stable · in-place | no · no |
- ✗Swapping the records (
swap(*p[i], *p[min])) instead of the pointers (swap(p[i], p[min])). That defeats the purpose. - ✗Comparing the pointers themselves (
p[j] < p[min]) instead of what they point to (p[j]->score). - ✗Forgetting to initialise
p[i] = &s[i]before sorting.
Insertion sort on items a gap apart, with the gap shrinking to 1. Far-away items move in big jumps, so the final insertion sort has little work left.
| Best case (sorted) | O(n log n) |
| Average case | depends on the gaps; about O(n^1.5) for n/2, n/4, … |
| Worst case (gaps n/2, n/4, …) | O(n²) |
| Space | O(1) |
| Stable · in-place | no · yes |
- ✗Comparing neighbours (gap 1) in every pass, which is just insertion sort.
- ✗Forgetting that the last pass must use gap = 1, or the array may not be sorted.
- ✗Claiming it is stable. Jumps over a gap can reorder equal keys.
Split the array in half, sort each half recursively, then merge the two sorted halves. Always O(n log n), stable, but needs O(n) extra space.
| Best case | O(n log n) |
| Average case | O(n log n) |
| Worst case | O(n log n) |
| Space | O(n) for the temporary array |
| Stable · in-place | yes · no |
- ✗Forgetting to copy the leftover items after one half runs out.
- ✗Using
<instead of<=in merge, which breaks stability. - ✗Base case
lo > hionly. A single item (lo == hi) must also stop the recursion.
Pick a pivot, partition so smaller items go left and bigger items go right, then sort each side recursively. Average O(n log n), worst O(n²).
| Best case (pivot splits in half) | O(n log n) |
| Average case | O(n log n) |
| Worst case (sorted input, last-item pivot) | O(n²) |
| Space | O(log n) recursion on average, O(n) worst |
| Stable · in-place | no · yes |
- ✗Recursing on
(lo, p)instead of(lo, p − 1). The pivot is already in place. - ✗Forgetting the final
swap(a[i + 1], a[hi])that puts the pivot in place. - ✗Saying quick sort is always O(n log n).
- Stable sort:
- A sort that keeps equal keys in their original relative order.
- In-place:
- Uses only O(1) extra memory besides the input (recursion stack aside).
- Pass:
- One full sweep of the outer loop of a sort.
- Pointer sort:
- Sorting an array of pointers (or indices) to records instead of moving the records themselves.
- Linear search:
- Check each item in turn. O(n). Works on unsorted data.
- Binary search:
- Repeatedly halve a sorted range by comparing with the middle item. O(log n).
- Divide and conquer:
- Split a problem into smaller parts, solve them recursively, combine the results.
- Pivot:
- The item quick sort partitions around.
- Partition:
- Rearranging a range so items smaller than the pivot come before it and bigger ones after.
- Gap (shell sort):
- The distance between compared items in a shell sort pass; shrinks to 1.