Sorting Problem

Context: FIT1008_MOC, FIT2004_MOC · a Computational Problem · backbone clustering the three elementary sorts (Bubble/Selection/Insertion) + sort properties Stability & Incrementality · recursive sorts (Merge Sort, Quick Sort, Heapsort) referenced FIT2004 emphasis: every sort is now graded on four axes — correctness (Invariant), time, auxiliary space, stability — and the suite splits into comparison-based (floored at ) vs non-comparison (Counting Sort, Radix Sort, which break the floor). W3 adds the engineering layer: how to force stability onto an unstable sort, and what sorting is actually for (§9).

Quick Revision

  • 🎯 Objective: rearrange orderable elements → non-decreasing ➔ correctness = permutation + ordering.
  • 📦 Core Components: Bubble ➔ adaptive, swaps | Selection swaps, never adaptive | Insertion ➔ adaptive + online | non-comparison / .
  • ⚡ Key Constraint: all three elementary sorts are worst (arithmetic series ) ➔ discriminators are stability, swap count, adaptivity; the floor binds only algorithms that compare.

📝 Core

1. The Sorting Problem (Spec)

  • Specification ➔ input orderable elements ➔ output permutation .
  • Correctnesspermutation AND ordering (ordered-only misses drop/duplicate bugs).

2. Comparison-Based vs Non-Comparison

  • Comparison-based ➔ the algorithm’s only access to keys is the test “is ?” — bubble, insertion, selection, Merge Sort, Quick Sort, Heapsort.
  • The floor ➔ every comparison-based sort is sorts are provably optimal within that class, and no cleverness gets below it.
  • Non-comparisonCounting Sort and Radix Sort use the key as an array index, never comparing two items ⟹ the floor does not apply, at the cost of demanding bounded integer keys.
  • Selection rule ➔ keys are bounded integers with range Counting Sort; decomposable into narrow columns ⟹ Radix Sort; anything else ⟹ a comparison sort.

3. Bubble Sort

  • Mechanism ➔ walk L→R, swap each ➔ largest bubbles to the final tail.
  • Adaptivity ➔ BubbleSort II swapped flag ➔ best on sorted input.
  • Cost profile ➔ strict >stable; up to swaps (one per inversion).

4. Selection Sort

  • Mechanism ➔ scan suffix for min ➔ exactly one swap/pass to leftmost unsorted.
  • Swap-thrift swaps (wins when writes costly: flash, big records).
  • No best case ➔ the minimum must be located in full every pass, so there is no early exit ⟹ best avg worst ; unstable, because the long-distance swap can throw an equal key backwards ([4a,2,3,4b,1][1,2,3,4b,4a]).
  • Correctness ➔ two-clause prefix invariant + both counters increment ➔ Invariant.

5. Insertion Sort

  • Mechanism ➔ sorted prefix; shift larger elements right, drop temp into the gap.
  • Adaptive + online ➔ best (sorted input ⟹ the inner while never fires) ➔ absorbs a new last element in one pass.
  • Stability from shifting ➔ strict > means equal keys are never swapped past each other; shifting rather than swapping is what preserves order ➔ basis of [[Sorted List (ADT)|sorted-list add]].

6. Stability (Property)

  • Definition ➔ equal keys keep input order; observable only sorting by key.
  • When it matters ➔ multi-pass sorting on several keys (sort by name, then by department, and the names stay ordered within each department) and any Radix Sort subsort; with distinct keys it is unobservable and free.
  • Mechanism heuristicshifting is stable, long-distance swapping is not. Bubble/insertion/merge move items past adjacent or ordered positions and preserve ties; selection/heap/quicksort throw an item across the array and can hurdle an equal key.
  • Bug vector> vs >= is a one-character stability break.
  • Engineering fix A — tuple the index in ➔ compare on so ties break by original position; blocked when the container cannot hold tuples.
  • Engineering fix B — a parallel index list ➔ keep index_list alongside the data, consult it only when list[a] == list[b], and apply every swap to both lists.
  • Time is UNCHANGED by either fix ➔ when the index list is never read; when they are equal the tie-break compares two integers in ⟹ no factor is added to any bound.
  • Space grows by one class at most ➔ selection sort goes from auxiliary to ; but total space was already for the input, and ⟹ the total bound does not move, only the in-place claim is lost.

7. Incrementality (Property)

  • Definition ➔ small input change ➔ rework (sorting’s online analogue) ➔ Online Algorithm.
  • Insertion yes / Selection no ➔ append-to-back ➔ one pass; “final” prefix blocks latecomers.
  • Graduate ➔ frequent updates ➔ balanced Binary Tree/Heap (/update).

8. The Cost Terms Everyone Drops

  • Comparisons are not ➔ if comparing two items costs (words compared letter-by-letter, tuples field-by-field), every bound gains a factor: elementary sorts become , Merge Sort becomes · state or declare it constant.
  • Why an integer comparison IS ➔ a fixed-width machine word is compared by one hardware instruction regardless of its value; a -character string has no such instruction and must be walked symbol by symbol. The asymmetry is architectural, not algorithmic — which is why the item type, not the algorithm, decides whether can be dropped.
  • Input space follows the same rule integers occupy ; strings of length up to occupy .
  • Comparisons swaps, always ➔ no algorithm swaps a pair it never compared ⟹ a swap-count bound can never exceed the comparison-count bound; use it as a self-check on a derived answer.
  • The recursion stack is auxiliary space levels of frames cost , and if each frame stores words ⟹ recursive sorts are not in-place even when they never allocate a scratch array.
  • Three auxiliary-space classes, three causes ⟸ iterative, swaps only (the three elementary sorts, Heapsort) · ⟸ a balanced recursion’s frame chain (Merge Sort’s stack, Quick Sort recursing smaller-first) · ⟸ a scratch array (Merge Sort’s merge buffer) or a degenerate recursion (Quick Sort’s worst-case stack). Naming the cause is what earns the mark.
  • Consequence ➔ an iterative rewrite is the standard route to auxiliary; this is why “in-place?” and “recursive?” are almost the same question in the summary table.
  • Best worst is a diagnostic, not a coincidence ➔ the cases collapse exactly when (1) the algorithm has no early termination path and (2) the item values cannot change the control flow. Selection sort and Merge Sort satisfy both ⟹ one covers every case; bubble (the swapped flag) and insertion (the inner while) violate (1), and Quick Sort violates (2)Big-O Notation.

9. What Sorting Is FOR

  • Sorting is rarely the goal ➔ it is the preprocessing step that makes a later pass linear; if the follow-up pass is not cheaper, the sort was not worth it.
  • Grouping ➔ equal keys become contiguous, so counting occurrences, finding the mode, or aggregating by key collapses to one sequential scan instead of a nested search.
  • Deduplication ➔ duplicates are adjacent after sorting, so a two-pointer compaction removes them in ; the naive alternative — deleting in place by shifting the tail left — costs per removal and overall.
  • An “in-place” requirement PICKS THE SORT ➔ the compaction is already auxiliary, so the sort is the only term that can break the budget: Merge Sort spends on scratch and Quick Sort on stack ⟹ Heapsort is the only valid choice, being the sole sort with auxiliary. Naming the sort is the marked step, not the two-pointer loop.
  • Why not a hash set or BST ➔ both dedup in expected / and preserve input order, but cost auxiliary ⟹ disqualified the moment “in-place” appears in the spec. Reach for them when order preservation matters more than space.
  • Enabling access ➔ sortedness is the precondition of Binary Search and of range reporting in Output-Sensitive Complexity.
  • Order statistics ➔ sorting answers every rank at once; when only one rank is wanted, Quickselect does it in and sorting is over-solving.
  • The amortisation rule ➔ sort once at and every subsequent query is cheap; sort per query and the preprocessing cost is paid again each time — the standard “is preprocessing worth it?” exam judgement.

⚙️ Core Implementation

🔹 Bubble Sort (II, adaptive)

🔹 Selection Sort (min swaps)

🔹 Insertion Sort (adaptive, online)

🔹 Two-pointer deduplication (the payoff of sorting)

⚖️ Core Decision Matrix

(Best / Average / Worst time, auxiliary space, stability, in-place. comparison cost applies to every comparison-based row.)

AlgorithmBestAverageWorstAuxiliary spaceStableIn-placeDistinctive trait
Bubble Sort (II)YesYesadaptive; swaps
Selection SortNoYesonly swaps
Insertion SortYesYesadaptive and online
HeapsortNoYesin-place and guaranteed
Merge Sort scratch stackYesNoguaranteed, stable
Quick Sort — fixable to stackDependsNofast in practice; pivot-sensitive
Counting Sort · stableengineeredNono comparisons; key range
Radix SortrequiredNo stable counting passes, LSD first

When It Flips: choose an sort when is small (low overhead), nearly-sorted (insertion → ), or writes dominate (selection's swaps). Choose a non-comparison sort only when the keys are bounded integers: Counting Sort while , Radix Sort while . Otherwise the floor makes Merge Sort/Heapsort optimal — merge for stability, heap for auxiliary.

📊 Exam Execution Trace

Manual Execution Trace

Insertion Sort on [5, 2, 4, 1]:

Step / StateTrigger OpmarktempShiftsArray Payload
0 (Init)init[5, 2, 4, 1]
1insert125→[2, 5, 4, 1]
2insert245→[2, 4, 5, 1]
3insert315,4,2→[1, 2, 4, 5]

Applied Exercise

Problem: Derive the worst-case bound of the elementary sorts on reverse-sorted input, then re-quote it when each comparison costs . Derivation Proof / Hand-Calculation Walkthrough:

Final Extracted Output: worst case for bubble/selection/insertion, or with non-constant comparison cost; bubble & insertion reach best.

🧠 Active Recall