Advanced Sorting & Searching
dsa.fetehadin.com8.1 Shell Sort
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.
8.2 Quick Sort
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).
8.3 Merge Sort
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.
8.4 Heap Sort
Build a max-heap in the array, then repeatedly swap the root (the largest item) to the end and sift down. O(n log n) in every case, in-place.
| Build heap | O(n) |
| Each extract-max (swap + heapify) | O(log n) |
| Best / average / worst | O(n log n) |
| Space | O(1) iterative, O(log n) with recursive heapify |
| Stable · in-place | no · yes |
- ✗Using 1-based formulas (2i, 2i+1) with a 0-based array. With 0-based it is 2i+1 and 2i+2.
- ✗Starting the build loop at i = 0 instead of n/2 − 1, going down to 0.
- ✗Calling heapify on the whole array instead of the shrinking heap size
end.
8.5 Hashing Basics
A hash function turns a key into an array index, so search is O(1) on average. Collisions, separate chaining, linear probing and the load factor.
| search / insert / delete, average | O(1) |
| search / insert / delete, worst (all keys collide) | O(n) |
| Space | O(M + n) |
- ✗With linear probing, stopping a search at a slot holding a different key. Only an empty slot means "not found".
- ✗Forgetting to wrap around with
% Mwhen probing. - ✗Claiming hashing is always O(1). The worst case is O(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.
- Max-heap:
- A complete binary tree where every parent is ≥ its children; stored in an array.
- Heapify:
- Sift a node down until the heap property holds below it. O(log n).
- Gap (shell sort):
- The distance between compared items in a shell sort pass; shrinks to 1.
- Hash function:
- Maps a key to an index of the hash table, e.g. h(k) = k mod M.
- Collision:
- Two different keys hashing to the same index.
- Separate chaining:
- Each table slot holds a list of all keys that hash there.
- Linear probing:
- On a collision, try the next slot (h + i) % M until an empty one.
- Load factor:
- α = n / M, how full a hash table is.