Drills

Drills

Five tasks.


1. Where stability goes

Change the Merge condition from a[i].Title <= b[j].Title to <.

Run dcsort_test.go. Which test fails? And did the algo dc numbers change? Explain why one character changes neither the complexity nor the comparison count, but does change the result.


2. Why median-of-three is not enough for reverse order

Step 7 showed median-of-three staying quadratic on reverse-sorted input.

Find the reason. Log the p returned by every Partition and look at how the slice divides over the first ten levels. Is the first split good? What about the second?

(Hint: the first split is perfect. The problem is in what Partition leaves behind.)


3. Hoare partitioning

Implement PartitionHoare — the two-pointer scheme, walking from both ends towards each other.

Run median-of-three with it on reverse-sorted input. Did the quadratic behaviour go away? If so, your answer to task 2 is confirmed.


4. Three-way partitioning

Generate a library with -dup-rate 0.9: ten percent distinct titles, the rest repeats.

Run all four algorithms. Which suffers most, and why?

Then implement a three-way split (less / equal / greater) and measure again.


5. Recursion depth

QuickSortNaive on sorted input recurses n levels deep.

In lesson 5 you measured Go's stack as holding about 8 million frames. How large would a sorted slice have to be to break QuickSortNaive?

Work it out, then check. And consider why sort.Slice never does this — the answer is limit := bits.Len(uint(length)) in its code.