By the end of this chapter you'll be able to…

  • 1State the exact worst-case comparison count for binary search
  • 2Decide when sorting to enable binary search actually pays
  • 3Derive the comparison lower bound from a decision tree
  • 4Explain what the lower-bound proof permits an algorithm to do instead
  • 5Compare the three quadratic sorts on stability, swaps and adaptivity
  • 6Explain why selection sort has a fixed comparison count and minimal swaps
  • 7Explain why insertion sort is linear on sorted input
  • 8State merge sort's guarantees and its space cost
  • 9Explain what makes merge sort stable
  • 10Write the quicksort recurrence and identify the worst-case split
  • 11Explain why sorted input triggers quicksort's worst case
  • 12Compare merge, quick and heap sort across all six properties
  • 13State the conditions under which counting sort is useful
  • 14Explain why radix sort requires a stable inner sort
  • 15State bucket sort's assumption and how it degrades
  • 16Define the load factor and explain why it determines everything
  • 17Choose a good table size for the division method
  • 18Explain what universal hashing guarantees that fixed hashing cannot
  • 19Compare separate chaining and open addressing on load factor and degradation
  • 20Distinguish primary from secondary clustering
  • 21Compute the expected probe count for linear probing
  • 22Explain why deletion under open addressing needs tombstones
💡
Why this chapter matters in GATE
Three topics that share one theme: each is a study of how much work is genuinely necessary and how to avoid doing more than that. For sorting, the answer comes from information theory — a comparison has two outcomes, so distinguishing n factorial orderings needs at least log of n factorial comparisons, which gives the n log n lower bound and explains why every comparison sort is stuck at it. For hashing, the answer comes from the load factor: everything about a table's performance, from probe counts to when to resize, is a function of how full it is, and the collision strategy only changes the constants. The third organising fact is that a faster-than-comparison sort must not compare. Counting, radix and bucket sort all beat n log n by exploiting structure in the keys rather than by being cleverer about comparisons, which is precisely the loophole the lower-bound proof leaves open.

Before you start — revise these

🔗
Asymptotic Complexity & Recurrences
The merge sort and quicksort recurrences, and the amortised reasoning behind table resizing, are solved with the machinery from that chapter.
🔗
Binary Heaps & Graphs as Data Structures
Heapsort's guarantees and its poor locality come from the heap's array representation and sifting behaviour.
🔗
Probability and Statistics
Expected probe counts, the uniform hashing assumption and bucket sort's average case all rest on expectation arguments.

Searching, Sorting & Hashing

Three topics that share one theme: each is a study of how much work is genuinely necessary, and how to avoid doing more than that.

For sorting, the answer comes from information theory. A comparison has two outcomes, so it distinguishes at most a factor of two, and distinguishing possible orderings therefore needs at least comparisons. That single argument gives the lower bound and explains why every comparison sort is stuck at it.

For hashing, the answer comes from the load factor. Everything about a hash table's performance — probe counts, clustering, when to resize — is a function of how full it is, and the collision strategy only changes the constants.

The third organising fact is that a faster-than-comparison sort must not compare. Counting sort, radix sort and bucket sort all beat , and they do it by exploiting structure in the keys rather than by being cleverer about comparisons.

So the question to ask about any sorting algorithm is what it assumes about the data, and the question to ask about any hash table is how full it is.

1. Searching

Linear search examines elements one at a time and costs in the worst case, in the best. It requires nothing of the data, which is its only advantage.

Binary search repeatedly halves a sorted array and costs .

The precondition is absolute: the array must be sorted, and applying binary search to unsorted data does not merely perform badly, it returns wrong answers.

The exact worst-case comparison count is , because each comparison halves the remaining range and the search ends when one element remains.

Sorting to enable binary search only pays if the array is searched many times, since the sort costs and each linear search costs only . One search is not worth it; a thousand are.

Interpolation search guesses the position by proportion rather than always taking the midpoint, achieving on uniformly distributed data and degrading to when the distribution is skewed.

2. The Comparison Lower Bound

Any comparison-based sort can be drawn as a decision tree: internal nodes are comparisons, branches are outcomes, leaves are the possible orderings.

There must be at least leaves, since every permutation of the input must be distinguishable, and a binary tree with leaves has height at least .

By Stirling's approximation, .

So no comparison-based sort can beat in the worst case. Merge sort and heapsort achieve it, so the bound is tight and the problem is settled.

The proof also tells you exactly how to escape it: stop comparing. An algorithm that uses key values directly — as an array index, or digit by digit — is not a decision tree over comparisons and the bound does not apply.

3. The Quadratic Sorts

Three sorts differ in ways that are examined precisely.

SortBestWorstStableSwapsAdaptive
Bubble with flagYesYes
SelectionNoNo
InsertionYesYes

Selection sort always performs exactly comparisons, regardless of the input, because it scans the whole unsorted region on every pass. Its compensating virtue is that it performs only swaps, the minimum possible, which matters when a swap is far more expensive than a comparison.

Insertion sort is on already-sorted input and runs in time proportional to the number of inversions, which makes it genuinely fast on nearly-sorted data. This is why library sorts switch to it for small or almost-ordered subarrays.

Bubble sort with an early-exit flag also detects sorted input in one pass, but without the flag it is even on sorted data — a distinction questions exploit.

Selection sort is the only one of the three that is not stable, because swapping a minimum into place can jump it past an equal element.

4. Merge Sort

Merge sort splits the array in half, sorts each half recursively, and merges.

The bound holds in every case — best, average and worst — because the split is always even regardless of the data.

It is stable, provided the merge takes from the left half when elements are equal, and that single implementation detail is what stability depends on.

It requires extra space for the merge, which is its main cost and the reason it is not used where memory is tight. In-place merging is possible but complicated and slower in practice.

Merge sort is the natural choice for linked lists, where the extra space vanishes because merging relinks nodes rather than copying them, and where quicksort's random access is unavailable.

It is also the basis of external sorting, where the data exceeds memory: sorted runs are written to disk and merged in passes.

5. Quicksort

Quicksort partitions around a pivot so that smaller elements precede it and larger follow, then recurses on each side.

The partition is the whole algorithm; there is no combine step at all, which is the mirror image of merge sort.

where is the number of elements below the pivot.

A balanced split gives ; a maximally unbalanced split gives .

The worst case occurs on already-sorted input when the pivot is the first or last element, which is exactly the input a naive implementation is most likely to meet. Choosing a random pivot, or the median of three, makes the worst case vanishingly unlikely without eliminating it.

Quicksort is not stable and uses stack space for the recursion, which is why it is usually described as in-place despite not being strictly so.

Despite the worse worst case, quicksort is usually the fastest comparison sort in practice, because its inner loop is a simple scan with excellent cache behaviour, while merge sort copies and heapsort jumps.

6. Comparing the Three

SortBestAverageWorstSpaceStable
MergeYes
QuickNo
HeapNo

Each buys its guarantee with a different currency. Merge sort pays memory, heapsort pays cache locality, and quicksort pays worst-case certainty.

The practical resolution used by real libraries is a hybrid: quicksort by default, insertion sort below a size threshold, and a switch to heapsort if the recursion depth suggests the worst case is developing.

7. Non-Comparison Sorts

Counting sort tallies occurrences of each key value and reconstructs the array. It costs where is the range of key values, and it is stable if the output is built by scanning the input backwards.

It is only useful when is . Sorting a thousand values from a range of a billion would allocate a billion counters, so the range condition is not a technicality.

Radix sort sorts digit by digit, least significant first, using a stable sort at each digit. It costs for digits.

The inner sort must be stable, or the algorithm is simply wrong — earlier digits' ordering would be destroyed by later passes. This is the single most examined fact about radix sort.

Bucket sort distributes keys into buckets by value, sorts each bucket, and concatenates. It achieves average time when the keys are uniformly distributed, and degrades to the inner sort's worst case when they are not.

All three escape the comparison bound by using key values as addresses rather than comparing them, which is precisely the loophole the lower-bound proof leaves open.

8. Hashing and the Load Factor

A hash table maps a key to a slot through a hash function, giving expected access.

The load factor — elements divided by slots — determines everything. Both the expected probe count and the resizing policy are functions of it alone.

A good hash function distributes keys uniformly and computes quickly. The division method uses , and should be prime and far from a power of two, because a power of two makes the hash depend only on the low-order bits.

The multiplication method multiplies by an irrational-like constant and extracts middle bits, which is less sensitive to the choice of .

Universal hashing selects a hash function at random from a family, guaranteeing good expected behaviour against any input including an adversarial one — which fixed functions cannot do.

9. Collision Resolution

Two families exist, and they behave differently as the table fills.

Separate chaining stores colliding elements in a list at the slot. The load factor may exceed 1, and the expected search cost is — constant work plus a walk down a chain of average length .

Open addressing stores everything in the table itself, probing a sequence of slots until an empty one is found. The load factor cannot exceed 1, and performance degrades sharply as it approaches it.

Three probe sequences appear.

Linear probing checks the next slot, wrapping around. It has the best cache behaviour and the worst clustering: occupied runs merge into longer runs, and a longer run is more likely to grow, which is called primary clustering.

Quadratic probing steps by increasing squares, breaking up primary clusters but creating secondary clustering, since keys hashing to the same slot follow identical sequences.

Double hashing uses a second hash function for the step size, so keys colliding at the first slot diverge immediately. It has the best theoretical behaviour and the worst locality.

For linear probing, the expected probes for an unsuccessful search is approximately

The squared term is what makes linear probing collapse near full. At it predicts about 50 probes; at , about 2.5.

Deletion under open addressing cannot simply blank a slot, because that would break probe sequences passing through it. A deleted marker, or tombstone, is written instead, and tombstones accumulate until the table is rebuilt.

10. Worked Examples

Example 1. How many comparisons does binary search make in the worst case on 1000 elements, and how does that compare with linear search?

Each comparison halves the remaining range, so the worst case is .

Since and , the answer is 10 comparisons.

Linear search needs up to 1000.

The ratio is 100 to 1, and it widens: for a million elements binary search needs 20 against a million, a ratio of 50,000.

The catch is the precondition. Sorting 1000 elements costs about comparisons, so a single search does not justify sorting. Break-even is at roughly 10 searches, and beyond that the sort pays for itself many times over.

Example 2. Prove that no comparison sort can do better than .

Model any comparison sort as a decision tree. Each internal node is a comparison between two elements, each has two children for the two outcomes, and each leaf is a permutation the algorithm can output.

For the algorithm to be correct, every one of the possible input orderings must lead to a distinct leaf, since each requires a different rearrangement. So the tree has at least leaves.

A binary tree of height has at most leaves, so , giving .

By Stirling's approximation, , so

The height of the tree is the worst-case number of comparisons, so every comparison sort needs comparisons on some input.

The bound is tight, since merge sort and heapsort achieve it, so nothing better exists within the comparison model. The only escape is to leave the model, which is what counting and radix sort do.

Example 3. Sort the array [170, 45, 75, 90, 802, 24, 2, 66] using radix sort, showing each pass.

Three digits are needed, since the largest value has three.

Pass 1, on the units digit: the keys sort by last digit into 170, 90, 802, 2, 24, 45, 75, 66.

Reading the units digits: 0, 0, 2, 2, 4, 5, 5, 6 — correctly ordered, with ties preserving their earlier relative order.

Pass 2, on the tens digit: starting from the pass-1 output, sort by the middle digit to get 802, 2, 24, 45, 66, 170, 75, 90.

Tens digits: 0, 0, 2, 4, 6, 7, 7, 9. Note that 170 precedes 75 because both have tens digit 7 and 170 came first in the pass-1 output — this is stability doing its work.

Pass 3, on the hundreds digit: sort by the leading digit to get 2, 24, 45, 66, 75, 90, 170, 802.

Hundreds digits: 0, 0, 0, 0, 0, 0, 1, 8. The six values with no hundreds digit keep their pass-2 order, which is already correct on the lower two digits.

The array is sorted.

The whole algorithm depends on stability. If pass 3 reordered the six zero-hundreds values arbitrarily, the work of passes 1 and 2 would be destroyed and the result would be wrong. This is why counting sort, which is stable, is the standard inner sort for radix.

Example 4. A hash table has 11 slots and uses with linear probing. Insert 22, 31, 4, 15, 28, 17, 88, 59. Where does each land?

Compute each initial slot and probe forward on collision.

22 mod 11 = 0. Slot 0 is free. Placed at 0.

31 mod 11 = 9. Free. Placed at 9.

4 mod 11 = 4. Free. Placed at 4.

15 mod 11 = 4. Occupied by 15's collision with 4, so probe slot 5. Free. Placed at 5.

28 mod 11 = 6. Free. Placed at 6.

17 mod 11 = 6. Occupied, probe 7. Free. Placed at 7.

88 mod 11 = 0. Occupied by 22, probe 1. Free. Placed at 1.

59 mod 11 = 4. Occupied, probe 5 (occupied), 6 (occupied), 7 (occupied), 8. Free. Placed at 8.

The final table holds 22 at 0, 88 at 1, 4 at 4, 15 at 5, 28 at 6, 17 at 7, 59 at 8, and 31 at 9.

Notice the cluster. Slots 4 through 8 form a run of five, and 59 needed four probes to get past it. That run formed because two separate hash values, 4 and 6, produced adjacent occupied regions that merged — exactly the primary clustering that linear probing suffers from.

The load factor is 8/11, about 0.73. The linear-probing formula predicts about probes for an unsuccessful search, which is consistent with what the last insertion experienced.

Example 5. Why is quicksort's worst case triggered by sorted input, and why is it still preferred in practice?

With a first-element pivot on a sorted array, every element is larger than the pivot, so the partition puts zero elements on the left and on the right.

The recurrence becomes , which unrolls to .

The recursion depth also becomes rather than , so the stack usage becomes linear and can overflow.

The irony is that sorted or nearly-sorted input is extremely common in practice, which makes this the worst possible worst case to have.

Two fixes address it. Choosing a random pivot makes any particular input equally likely to split well, so no adversary can construct a bad case without knowing the random seed. Choosing the median of the first, middle and last elements guarantees a reasonable split on sorted input specifically, at almost no cost.

Despite all this, quicksort remains the practical default because its partition loop is a pair of sequential scans with near-perfect cache behaviour, it needs no auxiliary array, and its constant factor is markedly smaller than merge sort's. Real libraries hedge by switching to heapsort if the recursion depth exceeds about , which caps the worst case at while keeping quicksort's speed in the common case.

Example 6. A hash table with separate chaining has 1000 slots and 1500 elements. What is the expected number of comparisons for an unsuccessful search, and what changes with open addressing?

The load factor is .

For separate chaining, an unsuccessful search hashes to a slot and walks its entire chain, whose expected length is .

Expected comparisons: , so about 2.5 comparisons — hashing plus walking an average chain of 1.5.

A successful search walks on average half the chain, giving roughly .

With open addressing, this table cannot exist. Open addressing stores every element in the table itself, so the load factor cannot exceed 1, and 1500 elements will not fit in 1000 slots at all.

This is the structural difference between the two families. Chaining degrades gracefully and linearly past full, while open addressing has a hard capacity limit and degrades sharply before reaching it — at linear probing already needs about 50 probes for an unsuccessful search.

The practical consequence is that open-addressed tables are resized at a load factor around 0.7, while chained tables tolerate values above 1 without difficulty.

Summary

Every sorting bound comes from information: a comparison distinguishes two cases, so separating orderings needs comparisons, and merge sort and heapsort make that tight.

Binary search needs comparisons and an absolutely sorted array; sorting first pays only when the array is searched many times.

Selection sort always makes comparisons but only swaps, and is the one quadratic sort that is not stable. Insertion sort is adaptive and linear on sorted input.

Merge sort is always and stable, paying space. Quicksort is on average and quadratic on sorted input with a naive pivot, unstable, and usually fastest in practice. Heapsort is always and in place, and unstable with poor locality.

Counting sort costs and is useful only when is . Radix sort costs and requires a stable inner sort or it is simply wrong. Bucket sort is linear on uniform data.

Everything about a hash table follows from the load factor. Chaining gives and tolerates ; open addressing cannot exceed and collapses well before it.

Linear probing has the best locality and suffers primary clustering; quadratic probing breaks that up but leaves secondary clustering; double hashing separates colliding keys immediately at the cost of locality.

Deletion under open addressing requires tombstones, because blanking a slot would break every probe sequence running through it.

Key formulas & results

Everything to memorise for the exam hall, in one card. Screenshot this for revision.

The organising tool
SORTING BOUNDS COME FROM HOW MUCH INFORMATION ONE COMPARISON GIVES. HASHING PERFORMANCE COMES FROM THE LOAD FACTOR ALONE.
ASK WHAT A SORTING ALGORITHM ASSUMES ABOUT THE DATA, AND ASK HOW FULL A HASH TABLE IS. EVERYTHING ELSE FOLLOWS FROM THOSE TWO QUESTIONS.
Binary search
THE WORST-CASE COMPARISON COUNT IS THE CEILING OF log2(n PLUS 1), AND THE ARRAY MUST BE SORTED.
APPLYING BINARY SEARCH TO UNSORTED DATA DOES NOT MERELY PERFORM BADLY, IT RETURNS WRONG ANSWERS. THE PRECONDITION IS ABSOLUTE.
When sorting pays
SORTING COSTS n log n AND EACH LINEAR SEARCH COSTS n, SO SORTING TO ENABLE BINARY SEARCH PAYS ONLY AFTER ROUGHLY log n SEARCHES.
ONE SEARCH NEVER JUSTIFIES A SORT; A THOUSAND SEARCHES REPAY IT MANY TIMES OVER.
The comparison lower bound
A DECISION TREE MUST HAVE AT LEAST n FACTORIAL LEAVES, SO ITS HEIGHT IS AT LEAST log2 OF n FACTORIAL, WHICH BY STIRLING IS THETA(n log n).
MERGE SORT AND HEAPSORT ACHIEVE IT, SO THE BOUND IS TIGHT AND THE PROBLEM IS SETTLED WITHIN THE COMPARISON MODEL.
Escaping the bound
AN ALGORITHM THAT USES KEY VALUES DIRECTLY, AS AN ARRAY INDEX OR DIGIT BY DIGIT, IS NOT A DECISION TREE OVER COMPARISONS.
COUNTING, RADIX AND BUCKET SORT ALL EXPLOIT THIS LOOPHOLE, WHICH IS WHY THEY BEAT n log n WITHOUT CONTRADICTING THE PROOF.
The quadratic sorts
BUBBLE AND INSERTION ARE STABLE AND ADAPTIVE, LINEAR ON SORTED INPUT. SELECTION IS NEITHER STABLE NOR ADAPTIVE.
SELECTION SORT ALWAYS MAKES EXACTLY n(n-1)/2 COMPARISONS BUT ONLY n MINUS 1 SWAPS, THE MINIMUM POSSIBLE, WHICH MATTERS WHEN SWAPS ARE EXPENSIVE.
Insertion sort's adaptivity
INSERTION SORT RUNS IN TIME PROPORTIONAL TO THE NUMBER OF INVERSIONS, SO IT IS O(n) ON SORTED INPUT.
THIS IS WHY LIBRARY SORTS SWITCH TO IT FOR SMALL OR ALMOST-ORDERED SUBARRAYS, WHERE ITS TINY CONSTANT BEATS ANY n log n ALGORITHM.
Merge sort
T(n) = 2T(n/2) PLUS THETA(n), GIVING THETA(n log n) IN EVERY CASE BECAUSE THE SPLIT IS ALWAYS EVEN REGARDLESS OF THE DATA.
IT IS STABLE PROVIDED THE MERGE TAKES FROM THE LEFT HALF ON TIES, AND THAT SINGLE IMPLEMENTATION DETAIL IS WHAT STABILITY DEPENDS ON.
Merge sort's space cost
IT REQUIRES THETA(n) EXTRA SPACE FOR THE MERGE, WHICH IS ITS MAIN COST.
IT IS THE NATURAL CHOICE FOR LINKED LISTS, WHERE MERGING RELINKS RATHER THAN COPIES, AND FOR EXTERNAL SORTING OF DATA EXCEEDING MEMORY.
Quicksort
T(n) = T(k) PLUS T(n-k-1) PLUS THETA(n), WHERE k IS THE NUMBER OF ELEMENTS BELOW THE PIVOT.
THE PARTITION IS THE WHOLE ALGORITHM AND THERE IS NO COMBINE STEP, WHICH IS THE MIRROR IMAGE OF MERGE SORT.
Quicksort's worst case
A MAXIMALLY UNBALANCED SPLIT GIVES THETA(n SQUARED), AND IT OCCURS ON ALREADY-SORTED INPUT WHEN THE PIVOT IS THE FIRST OR LAST ELEMENT.
SORTED INPUT IS EXTREMELY COMMON IN PRACTICE, WHICH MAKES THIS THE WORST POSSIBLE WORST CASE TO HAVE. RANDOM OR MEDIAN-OF-THREE PIVOTS FIX IT.
Comparing the three n log n sorts
MERGE IS n log n ALWAYS, STABLE, O(n) SPACE. QUICK IS n log n AVERAGE, n SQUARED WORST, UNSTABLE, O(log n) STACK. HEAP IS n log n ALWAYS, UNSTABLE, O(1) SPACE.
EACH BUYS ITS GUARANTEE WITH A DIFFERENT CURRENCY: MERGE PAYS MEMORY, HEAPSORT PAYS CACHE LOCALITY, AND QUICKSORT PAYS WORST-CASE CERTAINTY.
Counting sort
IT COSTS THETA(n PLUS k) WHERE k IS THE RANGE OF KEY VALUES, AND IT IS STABLE IF THE OUTPUT IS BUILT BY SCANNING THE INPUT BACKWARDS.
IT IS ONLY USEFUL WHEN k IS O(n). SORTING A THOUSAND VALUES FROM A RANGE OF A BILLION WOULD ALLOCATE A BILLION COUNTERS.
Radix sort
IT SORTS DIGIT BY DIGIT, LEAST SIGNIFICANT FIRST, COSTING THETA(d(n PLUS k)) FOR d DIGITS.
THE INNER SORT MUST BE STABLE OR THE ALGORITHM IS SIMPLY WRONG, SINCE LATER PASSES WOULD DESTROY THE ORDERING ESTABLISHED BY EARLIER DIGITS.
Bucket sort
DISTRIBUTE KEYS INTO BUCKETS BY VALUE, SORT EACH BUCKET, AND CONCATENATE. IT IS THETA(n) ON AVERAGE FOR UNIFORMLY DISTRIBUTED KEYS.
IT DEGRADES TO THE INNER SORT'S WORST CASE WHEN THE DISTRIBUTION IS SKEWED AND EVERYTHING LANDS IN ONE BUCKET.
The load factor
ALPHA EQUALS n OVER m, ELEMENTS DIVIDED BY SLOTS, AND IT DETERMINES BOTH THE EXPECTED PROBE COUNT AND THE RESIZING POLICY.
THE COLLISION STRATEGY ONLY CHANGES THE CONSTANTS. EVERYTHING QUALITATIVE ABOUT A HASH TABLE FOLLOWS FROM HOW FULL IT IS.
Choosing the table size
FOR THE DIVISION METHOD h(k) = k MOD m, THE SIZE m SHOULD BE PRIME AND FAR FROM A POWER OF TWO.
A POWER OF TWO MAKES THE HASH DEPEND ONLY ON THE LOW-ORDER BITS, DISCARDING MOST OF THE KEY. THE MULTIPLICATION METHOD IS LESS SENSITIVE TO m.
Universal hashing
SELECT A HASH FUNCTION AT RANDOM FROM A FAMILY, GUARANTEEING GOOD EXPECTED BEHAVIOUR AGAINST ANY INPUT INCLUDING AN ADVERSARIAL ONE.
NO FIXED FUNCTION CAN OFFER THIS, BECAUSE AN ADVERSARY WHO KNOWS THE FUNCTION CAN ALWAYS CONSTRUCT KEYS THAT ALL COLLIDE.
Separate chaining
COLLIDING ELEMENTS GO IN A LIST AT THE SLOT. THE LOAD FACTOR MAY EXCEED 1, AND EXPECTED SEARCH COST IS THETA(1 PLUS ALPHA).
A SUCCESSFUL SEARCH WALKS ON AVERAGE HALF A CHAIN, GIVING ROUGHLY 1 PLUS ALPHA OVER 2. CHAINING DEGRADES GRACEFULLY AND LINEARLY.
Open addressing
EVERYTHING IS STORED IN THE TABLE ITSELF, PROBING UNTIL AN EMPTY SLOT IS FOUND. THE LOAD FACTOR CANNOT EXCEED 1.
PERFORMANCE DEGRADES SHARPLY AS ALPHA APPROACHES 1, WHICH IS WHY OPEN-ADDRESSED TABLES ARE RESIZED AT AROUND 0.7.
The three probe sequences
LINEAR PROBING CHECKS THE NEXT SLOT. QUADRATIC PROBING STEPS BY INCREASING SQUARES. DOUBLE HASHING USES A SECOND HASH FUNCTION FOR THE STEP SIZE.
LINEAR HAS THE BEST LOCALITY AND PRIMARY CLUSTERING. QUADRATIC BREAKS THAT UP BUT HAS SECONDARY CLUSTERING. DOUBLE HASHING IS BEST THEORETICALLY AND WORST FOR LOCALITY.
Clustering
PRIMARY CLUSTERING IS OCCUPIED RUNS MERGING INTO LONGER RUNS, WHICH ARE THEN MORE LIKELY TO GROW. SECONDARY CLUSTERING IS KEYS HASHING TO THE SAME SLOT FOLLOWING IDENTICAL SEQUENCES.
LINEAR PROBING SUFFERS BOTH; QUADRATIC PROBING ELIMINATES THE FIRST BUT NOT THE SECOND; DOUBLE HASHING ELIMINATES BOTH.
Linear probing cost
P_unsucc IS APPROXIMATELY ONE HALF TIMES (1 PLUS 1 OVER (1 MINUS ALPHA) SQUARED).
THE SQUARED TERM IS WHAT MAKES LINEAR PROBING COLLAPSE NEAR FULL: ABOUT 2.5 PROBES AT ALPHA 0.5, BUT ABOUT 50 AT ALPHA 0.9.
Deletion under open addressing
A DELETED SLOT CANNOT SIMPLY BE BLANKED, BECAUSE THAT WOULD BREAK EVERY PROBE SEQUENCE PASSING THROUGH IT. A TOMBSTONE MARKER IS WRITTEN INSTEAD.
TOMBSTONES ACCUMULATE AND LENGTHEN PROBE SEQUENCES UNTIL THE TABLE IS REBUILT, WHICH IS AN OPERATIONAL COST CHAINING DOES NOT HAVE.
⚠️

Traps GATE sets — and how to dodge them

These are the exact option-traps and misreads that cost marks under negative marking.

WATCH OUT
Applying binary search to unsorted data
The precondition is not a performance hint but a correctness requirement. On unsorted data the algorithm discards the half containing the target and returns a wrong answer, silently.
WATCH OUT
Sorting an array to enable a single binary search
The sort costs n log n and one linear search costs n. Break-even is at roughly log n searches, so sorting pays only when the array will be queried many times.
WATCH OUT
Claiming a sort beats the n log n lower bound by being cleverer about comparisons
The decision-tree argument rules that out entirely within the comparison model. The only escape is to stop comparing and use key values directly, as counting and radix sort do.
WATCH OUT
Assuming selection sort's comparison count depends on the input
It always performs exactly n(n-1)/2 comparisons, because it scans the entire unsorted region on every pass regardless of what it finds. Only insertion and flagged bubble sort are adaptive.
WATCH OUT
Calling selection sort stable
Swapping a minimum into position can jump it past an equal element, destroying relative order. It is the one quadratic sort of the three that is not stable.
WATCH OUT
Assuming bubble sort detects sorted input automatically
Only the flagged variant does. Without an early-exit flag it performs all n passes even on sorted input, remaining quadratic where the flagged version is linear.
WATCH OUT
Assuming merge sort is stable regardless of implementation
Stability depends entirely on the merge taking from the left half when elements compare equal. Taking from the right instead produces a correct but unstable sort.
WATCH OUT
Describing quicksort as strictly in place
It uses O(log n) stack space for the recursion, and O(n) in the worst case if the recursion is not tail-optimised on the larger side. It is usually called in place because it needs no auxiliary array.
WATCH OUT
Believing a random pivot eliminates quicksort's worst case
It makes the worst case vanishingly unlikely rather than impossible. Real libraries additionally switch to heapsort when the recursion depth suggests degeneration, which caps the true worst case.
WATCH OUT
Using counting sort on a large key range
It allocates one counter per possible key value, so it costs Theta(n plus k). With k far larger than n the space and time are dominated by the range, not the data.
WATCH OUT
Using an unstable inner sort inside radix sort
Later passes would reorder keys that earlier passes had correctly arranged, destroying the result. The stability requirement is what makes counting sort the standard inner sort.
WATCH OUT
Sorting radix digits most significant first without care
The standard least-significant-first formulation relies on stability to build up the order. A most-significant-first variant requires recursive bucketing instead and is a different algorithm.
WATCH OUT
Choosing a power of two for the hash table size with the division method
Taking a key modulo a power of two keeps only the low-order bits and discards the rest of the key, so any structure in the high bits is lost. A prime far from a power of two is the standard choice.
WATCH OUT
Expecting an open-addressed table to hold more elements than slots
Every element occupies a slot, so the load factor cannot exceed 1 and the table simply fills. Only chaining permits a load factor above 1, and it degrades gracefully when it does.
WATCH OUT
Blanking a slot when deleting from an open-addressed table
Any probe sequence that passed through that slot to reach a later element would now terminate early and report the element missing. A tombstone marker preserves the sequence.
WATCH OUT
Confusing primary with secondary clustering
Primary clustering is adjacent occupied runs merging, which linear probing suffers. Secondary clustering is keys with the same initial hash following identical probe sequences, which quadratic probing still suffers.

Exam-pattern practice

PYQ-style questions with full solutions. Work through them as a readiness check — mark yourself honestly and get your gap report at the end.

Readiness check

Are you exam-ready for Searching, Sorting & Hashing?

9 problems from this chapter. Try each one, reveal the worked solution, mark yourself honestly — get your gap report at the end.

9 questions~6 min

5-minute revision

The whole chapter, distilled. Read this the night before the exam.

  • Binary search needs ceil(log2(n+1)) comparisons.
  • Binary search on unsorted data is wrong, not slow.
  • Sorting to search pays only after about log n searches.
  • A decision tree needs n! leaves.
  • Height at least log2 n! gives the n log n bound.
  • The bound is tight; merge and heapsort achieve it.
  • Escaping it means not comparing at all.
  • Selection sort always makes n(n-1)/2 comparisons.
  • Selection sort makes only n-1 swaps.
  • Selection sort is not stable.
  • Insertion sort is linear on sorted input.
  • Insertion sort runs in time proportional to inversions.
  • Bubble sort needs a flag to detect sorted input.
  • Merge sort is n log n in every case.
  • Merge sort is stable if the merge favours the left.
  • Merge sort needs Theta(n) extra space.
  • Merge sort suits linked lists and external sorting.
  • Quicksort has no combine step.
  • Sorted input plus an end pivot gives the quadratic worst case.
  • Quicksort is unstable and uses O(log n) stack.
  • Quicksort is usually fastest in practice.
  • Heapsort is n log n always and in place.
  • Heapsort is unstable with poor locality.
  • Counting sort costs Theta(n + k).
  • Counting sort needs k to be O(n).
  • Radix sort costs Theta(d(n + k)).
  • Radix sort requires a stable inner sort.
  • Bucket sort is linear on uniform data only.
  • The load factor is n over m.
  • The load factor determines everything.
  • Table size should be prime, not a power of two.
  • Universal hashing defends against adversarial keys.
  • Chaining allows alpha above 1.
  • Chaining costs Theta(1 + alpha).
  • Open addressing caps alpha at 1.
  • Linear probing suffers primary clustering.
  • Quadratic probing suffers secondary clustering.
  • Double hashing eliminates both, at locality cost.
  • Linear probing cost has a squared denominator.
  • Deletion needs tombstones under open addressing.
  • Resize chained tables near alpha 1, open ones near 0.7.

GATE question blueprint

How this topic is asked, tier by tier — so you can prep to the pattern.

Typical weightage: Algorithms contributes roughly 8-10 of the 72 core-CS marks; searching, sorting and hashing supply 2-3 of those across 2-3 questions

Question styleMarks eachTypical countWhat it tests
Sorting properties1~1Stability, adaptivity, comparison counts and swap counts
Comparison lower bound2~1The decision-tree argument and computing the bound for a small n
Quicksort2~1Worst-case triggers, comparison counts and pivot strategies
Sort selection2~1Choosing an algorithm from stated memory, timing and key-range constraints
Non-comparison sorts1~1Counting and radix sort costs and the stability requirement
Stability2~1Which algorithms are stable and what makes each so
Hashing2~1Load factor, table sizing and probe-sequence tracing
Collision resolution2~1Chaining versus open addressing, clustering types and probe-count formulas

Exam-hall strategy

Battle-tested tips from mentors and toppers for this topic under the sectional clock.

  1. Read the constraints first; sorting questions are built so the constraints select one algorithm.
  2. Check for a stated key range, which signals counting or radix sort.
  3. Check for stability requirements, which eliminate quicksort and heapsort.
  4. For quicksort questions, check whether the input is sorted and which pivot is used.
  5. For hashing, compute the load factor before anything else.
  6. For probe traces, write the initial slot for every key before starting to probe.
  7. Probe counts and comparison counts are commonly set as NAT, which carries no negative marking, so never leave one blank.
  8. For 1-mark and 2-mark MCQs, negative marking is -1/3 and -2/3, so guess only after eliminating an option.
  9. GATE gives a single freely-navigable 180-minute window, so flag a long probe trace and return to it.

Beyond the exam

Where this skill shows up in the job you're competing for — and in life.

The sort in a standard library

Introsort runs quicksort, falls back to heapsort on deep recursion, and finishes with insertion sort on small subarrays, combining all three chapters' trade-offs.

Sorting records on two fields

Sorting by secondary key then primary key gives the right result only if both sorts are stable, which is why database sort operators guarantee it.

Sizing a hash table

The resize threshold in every hash map implementation is a direct consequence of the probe-count formulas, which is why open-addressed maps grow at around 0.7 load.

External sorting of a large file

Merge sort's ability to work in sequential passes over sorted runs is what makes sorting data larger than memory possible at all.

Where else this topic is tested

Prepare once, score in every exam that asks it.

GATE DAHigh overlap — sorting complexity and hashing appear, with more emphasis on their use in data pipelines
UGC NET Computer ScienceHigh overlap — sort properties, the comparison lower bound and collision resolution are examined as direct recall
ISRO / BARC / DRDO computer science papersVery high overlap — probe sequences, comparison counting and sort stability are recurring MCQ topics

Questions aspirants ask

Pulled from the Q&A community and mentor sessions.

Because the lower bound applies only to comparison sorts, and counting sort never compares two keys. The proof models an algorithm as a decision tree whose internal nodes are comparisons, each with two outcomes. Distinguishing n factorial orderings then requires a tree of height at least log of n factorial, which is n log n. Counting sort is not such a tree. It uses each key directly as an index into a counter array, so a single operation places a key exactly where it belongs among all possible values, extracting far more than one bit of information. The loophole is real but conditional. Counting sort costs Theta(n plus k) where k is the range of key values, so it is linear only when k is O(n). Sorting a thousand 32-bit integers spread across the full range would require four billion counters, which is not merely slow but impossible. Radix sort mitigates this by processing d digits of a bounded range each, costing Theta(d(n plus k)) with a small k, and bucket sort mitigates it by assuming a known distribution. All three trade generality for speed: they need to know something about the keys that a comparison sort does not. That is the honest statement of the trade, and it is why comparison sorts remain the default for arbitrary data with only an ordering defined on it.

Because the worst case almost never happens with a decent pivot rule, while the constant factor matters on every single run. Quicksort's inner loop is two pointers scanning toward each other, comparing and occasionally swapping. That is sequential memory access, so every cache line fetched is fully used and hardware prefetching works perfectly. Heapsort's inner loop sifts a value down a root-to-leaf path, and in the array representation those positions are at indices roughly doubling each step, so successive accesses jump increasingly far apart and miss the cache repeatedly. A cache miss costs on the order of a hundred cycles against a few for a comparison, so heapsort loses badly on constants even though both are n log n. Quicksort also needs no auxiliary array, unlike merge sort, and its recursion uses only O(log n) stack when the smaller side is recursed into first. The worst case is handled by engineering rather than by switching algorithms. A random or median-of-three pivot makes a bad split vanishingly unlikely on real data, and the introsort strategy used by real libraries monitors recursion depth and switches to heapsort if it exceeds about twice log n. That caps the true worst case at n log n while retaining quicksort's speed in the overwhelming majority of runs, which is why the hybrid rather than any pure algorithm is what actually ships.

Because each pass is supposed to refine the ordering established by all previous passes, and only stability preserves that earlier work. Consider sorting three-digit numbers least significant digit first. After the units pass, keys are correctly ordered by their last digit. The tens pass now sorts by the middle digit, and among keys sharing a middle digit the correct relative order is exactly the order they arrived in, since that order already reflects their units digits. A stable sort preserves it; an unstable one scrambles it, and the units-digit information is lost permanently. Concretely, take 170 and 75 after a units pass has placed 170 before 75. Both have tens digit 7. A stable tens pass keeps 170 first, which is correct because 170 has units 0 and 75 has units 5. An unstable pass might place 75 first, and the final hundreds pass would then leave 75 before 170 among values sharing a hundreds digit — but 75 is smaller than 170, so that particular pair happens to end correctly. Change the example to 175 and 170 and the error becomes visible: an unstable tens pass can leave 175 before 170, and no later pass corrects it. The requirement is why counting sort is the near-universal inner sort for radix. It is stable when the output is built by scanning the input backwards, it is linear in the digit range, and its range k is small since a digit has at most ten or 256 values.

Primary clustering is runs of occupied slots merging into longer runs; secondary clustering is distinct keys following identical probe sequences. They have different causes and different remedies. Linear probing produces primary clustering because its probe sequence is simply the next slot. When a run of occupied slots exists, any key hashing to any position within that run ends up appended at the run's end, extending it by one. A longer run presents a larger target for the next insertion, so it grows faster, and adjacent runs eventually merge into a single very long one. The effect is self-reinforcing, which is why the probe count grows with the square of one over the free fraction rather than linearly. Quadratic probing eliminates this by stepping in increasing squares, so keys hashing to nearby but different slots diverge quickly and runs do not merge. What remains is secondary clustering: two keys hashing to the same initial slot follow exactly the same sequence of offsets forever, so they collide at every step and the second must probe past all the first's positions. It is far milder than primary clustering because it affects only keys sharing an initial hash rather than keys landing anywhere in a region. Double hashing removes secondary clustering too, by making the step size itself a function of the key, so two keys colliding initially diverge on the very next probe. The cost is locality: successive probes jump unpredictably across the table, defeating the cache in a way linear probing never does.

Read the constraints in the stem and eliminate, because such questions are always constructed so that the constraints select exactly one answer. Start with worst-case requirements. If the question mentions a real-time deadline, a guarantee, or an adversarial input, quicksort is eliminated, since no pivot rule makes its quadratic case impossible. Next consider memory. If auxiliary space is limited or the phrase in place appears, merge sort is eliminated, since it needs Theta(n) extra. Those two eliminations usually leave heapsort as the comparison-sort answer, which is precisely its niche: the only one guaranteeing n log n without extra space. Then check whether the keys have exploitable structure. If they are integers in a range comparable to n, counting sort beats every comparison sort at Theta(n plus k), deterministically. If they are fixed-width integers or strings, radix sort applies at Theta(d(n plus k)). If they are uniformly distributed reals, bucket sort is linear on average. A stem that specifies a key range is almost always steering toward one of these. Finally check stability. If the data is being sorted on a second key, or the phrase preserve order appears, quicksort and heapsort are out and merge sort or a stable counting sort is required. And if the input is described as nearly sorted or the size as small, insertion sort's adaptivity makes it the intended answer despite being quadratic in general.
Header Logo