Merge Sort

Context: FIT1008_MOC · a Divide and Conquer sort · solves the Sorting Problem · uses an Auxiliary Function (Recursion) · contrast with Quick Sort · the merge generalises from to lists in K-way Merge FIT2004 use: the merge is also an instrumentation point — threading a counter through it solves an apparently unrelated problem in ➔ Counting Inversions

Quick Revision

  • 🎯 Objective: cut in half, sort each, merge two sorted halves ➔ trivial-split / heavy-combine D&C sort.
  • 📦 Core Components: Split ➔ | Recurse ➔ two calls on | Merge ➔ , ties left-first ⇒ stable.
  • ⚡ Key Constraint: guaranteed every case + stable ➔ but needs scratch.

📝 Core

1. The Algorithm (Split → Merge)

  • Trivial split ➔ cut the array in half; non-trivial combine ➔ merge two already-sorted halves.
  • Apparatus ➔ one reused temp array of size + start/end markers; base case = 1-element slice.

2. Why Every Case

  • Level count × per-level work ➔ halving gives levels, the merge does per level ➔ .
  • Order-independent ➔ the count depends only on , never element order ⟹ best = average = worst; no case unlike Quick Sort.

3. Stability & Variants

  • Stable tie-break ➔ take from left half (<=) ➔ earlier-input keys emitted first.
  • Linked variant ➔ LinkList merges by relinking ➔ stack, no scratch.
  • External sort ➔ sequential access pattern ➔ basis of multiway sorts for data RAM.

4. The Hybrid Cut-off (applied W4)

  • The engineering trick ➔ stop recursing at subproblem size and finish with insertion sort, fast on small nearly-sorted ranges with tiny constants (Sorting Problem).
  • Merging part ➔ recursion stops when ⟹ levels × ⟹ .
  • The tail ➔ subproblems of size , each worst case ⟹ .
  • Total ➔ raising buys fewer merge levels and pays quadratically in the tail, so it is asymptotically worse for growing ; is held at a small constant (libraries use –), where the bound collapses back to with a smaller constant factor. A constant-factor optimisation, never a class change.

⚙️ Core Implementation

🔹 merge_sort + auxiliary recursion + the merge

⚖️ Core Decision Matrix

AlgorithmBestAverageWorstSpaceStableTrait
Merge SortYesguaranteed + stable, scratch array
Quick SortNoin-place, smaller constant
HeapsortNoin-place + guaranteed

When It Flips: merge sort's space/stability trade is the inverse of quicksort's — pick merge for worst-case guarantees, stability, linked lists, or external data; quicksort when in-place + smaller constant outweigh the risk.

📊 Exam Execution Trace

Manual Execution Trace

Merge of two sorted halves [2, 5] + [1, 4]:

Step / StateTrigger Opa[ia]a[ib]Taketmp Payload
0 (Init)init21[]
1compare21right (1<2)[1]
2compare24left (2≤4)[1,2]
3compare54right (4<5)[1,2,4]
4drain5left[1,2,4,5]

Applied Exercise

Problem: Derive merge sort’s complexity and show why it has no bad case.

Final Extracted Output: the level count and per-level work are both independent of input order ⟹ best = average = worst = ; no input degrades it.

🧠 Active Recall