ЁЯПл The SchoolтА║ЁЯзо DSAтА║ЁЯУ╢ рдзрдбрд╛ 07 тАФ Sorting: рд╡рд░реНрдЧрд╛рд▓рд╛ рдЙрдВрдЪреАрдиреБрд╕рд╛рд░ рд░рд╛рдВрдЧреЗрдд рд▓рд╛рд╡рдгреЗ
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯУ╢ рдзрдбрд╛ 07 тАФ Sorting: рд╡рд░реНрдЧрд╛рд▓рд╛ рдЙрдВрдЪреАрдиреБрд╕рд╛рд░ рд░рд╛рдВрдЧреЗрдд рд▓рд╛рд╡рдгреЗ

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 07 ┬╖ рдкреБрдвреЗ: lesson-08-binary-search


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рдзрдбреЗ 01тАУ07. comparison counters рдЕрд╕рд▓реЗрд▓реЗ рдЪрд╛рд░ sorts, рддреНрдпрд╛рдЪ 2,000 рдЙрдВрдЪреАрдВрд╡рд░ рд╡реЗрд│ рдореЛрдЬрд▓реЗрд▓реЗ, рдЖрдгрд┐ рддрд░реАрд╣реА рддреБрдореНрд╣реА sorted() рдХрд╛ рдмреЛрд▓рд╛рд╡рддрд╛ рдпрд╛рдЪреЗ рдХрд╛рд░рдг.

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

рд╡рд░реНрдЧрд╛рд▓рд╛ рдЙрдВрдЪреАрдиреБрд╕рд╛рд░ рд░рд╛рдВрдЧреЗрдд рд▓рд╛рд╡рд╛. Bubble: рд░рд╛рдВрдЧреЗрддреВрди рдЪрд╛рд▓рд╛, рдЪреБрдХреАрдЪреНрдпрд╛ рдХреНрд░рдорд╛рддрд▓реНрдпрд╛ рдХреЛрдгрддреНрдпрд╛рд╣реА рджреЛрди рд╢реЗрдЬрд╛рд▒реНрдпрд╛рдВрдЪреА рдЕрджрд▓рд╛рдмрджрд▓ рдХрд░рд╛, рдПрдЦрд╛рджреНрдпрд╛ рдлреЗрд░реАрдд рдХреЛрдгрд╛рдЪреАрдЪ рдЕрджрд▓рд╛рдмрджрд▓ рд╣реЛрдИрдкрд░реНрдпрдВрдд рдкреБрдиреНрд╣рд╛ рдХрд░рд╛ тАФ рд╣рд│реВ, рдкреНрд░рддреНрдпреЗрдХ рдлреЗрд░реА рдореНрд╣рдгрдЬреЗ рдкреВрд░реНрдг рд░рд╛рдВрдЧ. Insertion: рдкреБрдврдЪреЗ рдореВрд▓ рдШреНрдпрд╛ рдЖрдгрд┐ рддреНрдпрд╛рд▓рд╛ рдорд╛рдЧреЗ рддреНрдпрд╛рдЪреНрдпрд╛ рдЬрд╛рдЧреЗрдкрд░реНрдпрдВрдд рдиреНрдпрд╛ тАФ рд░рд╛рдВрдЧ рдЖрдзреАрдЪ рдЬрд╡рд│рдЬрд╡рд│ рдмрд░реЛрдмрд░ рдЕрд╕реЗрд▓ рддрд░ рдЬрд▓рдж. Merge: рд╡рд░реНрдЧрд╛рдЪреЗ рджреЛрди рдЕрд░реНрдзреЗ рдХрд░рд╛, рдкреНрд░рддреНрдпреЗрдХ рдЕрд░реНрдзрд╛ рдХреНрд░рдорд╛рдиреЗ рд▓рд╛рд╡рд╛ (рдкреБрдиреНрд╣рд╛ рдЕрд░реНрдзреЗ рдХрд░реВрдитАж), рдордЧ рджреЛрди рдХреНрд░рдорд╛рдиреЗ рд▓рд╛рд╡рд▓реЗрд▓реНрдпрд╛ рд░рд╛рдВрдЧрд╛ рдПрдХрддреНрд░ рдЧреБрдВрдлрд╛. Quick: рдПрдХ рдореВрд▓ рдирд┐рд╡рдбрд╛, рддреНрдпрд╛рдЪреНрдпрд╛рдкреЗрдХреНрд╖рд╛ рдмреБрдЯрдХреЗ рд╕рдЧрд│реЗ рдбрд╛рд╡реАрдХрдбреЗ, рдЙрдВрдЪ рдЙрдЬрд╡реАрдХрдбреЗ, рдкреНрд░рддреНрдпреЗрдХ рдмрд╛рдЬреВрд▓рд╛ рдкреБрдиреНрд╣рд╛ рдХрд░рд╛. рд╢реЗрд╡рдЯрдЪреЗ рджреЛрди рдЦреВрдкрдЪ рдХрдореА рдХрд╛рдо рдХрд░рддрд╛рдд тАФ рд╣реЗрдЪ n log n рд╡рд┐рд░реБрджреНрдз n┬▓.

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart TD
  A["[5 2 8 1 9 3]"] --> B["[5 2 8]"] & C["[1 9 3]"]
  B --> B1["[2 5 8]"] ; C --> C1["[1 3 9]"]
  B1 & C1 --> M["merge тЖТ [1 2 3 5 8 9]"]

тЭУ рдХрд╛рдп

Sort рд╡реЗрд│ Space Stable рдЯрд┐рдкрд╛
bubble O(n┬▓) O(1) рд╣реЛ рдлрдХреНрдд рдзрдбрд╛, рд╕рд╛рдзрди рдХрдзреАрдЪ рдирд╛рд╣реА
insertion O(n┬▓), рдЬрд╡рд│рдЬрд╡рд│ sorted рдЕрд╕реЗрд▓ рддрд░ O(n) O(1) рд╣реЛ рдЕрдЧрджреА рд▓рд╣рд╛рди рдХрд┐рдВрд╡рд╛ рдЬрд╡рд│рдЬрд╡рд│ sorted рд╕рд╛рдареА рдЙрддреНрддрдо
merge рдиреЗрд╣рдореА O(n log n) O(n) рд╣реЛ linked lists, external sorting
quick рд╕рд░рд╛рд╕рд░реА O(n log n), worst O(n┬▓) O(log n) рдирд╛рд╣реА рдкреНрд░рддреНрдпрдХреНрд╖рд╛рдд рд╕рд░реНрд╡рд╛рдд рдЬрд▓рдж in-place
Timsort (sorted) O(n log n), runs рд╡рд░ O(n) O(n) рд╣реЛ merge + insertion; Python рдЖрдгрд┐ Java рд╣реЗрдЪ рджреЗрддрд╛рдд

ЁЯдФ рдХрд╛

рдХрд╛рдорд╛рд╡рд░ рддреБрдореНрд╣реА рдХрдзреАрдЪ sort рд▓рд┐рд╣рд┐рдгрд╛рд░ рдирд╛рд╣реА, рдЖрдгрд┐ рд░реЛрдЬ рдПрдХ рдмреЛрд▓рд╛рд╡рд╛рд▓. рдЖрдХрд╛рд░ рдорд╛рд╣реАрдд рдЕрд╕рд▓реЗ рдХреА loop рдЪреНрдпрд╛ рдЖрддрд▓рд╛ sorted() рд╣рд╛ рддреБрдореНрд╣рд╛рд▓рд╛ рди рджрд┐рд╕рд▓реЗрд▓рд╛ n┬▓ рдХрдзреА рдЖрд╣реЗ рддреЗ рдХрд│рддреЗ, рдЖрдгрд┐ heap (рдзрдбрд╛ 09) рдХрд┐рдВрд╡рд╛ dict (рдзрдбрд╛ 05) sorting рдкреВрд░реНрдгрдЪ рдХрдзреА рдЯрд╛рд│рддреЛ рддреЗрд╣реА.

ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)

рдкреНрд░рддреНрдпреЗрдХ sort рдПрдХ list рдШреЗрддреЛ рдЖрдгрд┐ рдирд╡реА list рд╡ рддрд┐рдЪрд╛ comparison count рдкрд░рдд рдХрд░рддреЛ; demo.py sort рдЪрд╛рд░рд╣реА sorts рддреНрдпрд╛рдЪ random 2,000 рдЙрдВрдЪреАрдВрд╡рд░ рдЪрд╛рд▓рд╡рддреЛ, рддреЗ sorted рд╢реА рдЬреБрд│рддрд╛рдд рд╣реЗ assert рдХрд░рддреЛ, рдордЧ рдЬрд╡рд│рдЬрд╡рд│ sorted рд░рд╛рдВрдЧреЗрд╡рд░ insertion рд╡рд┐рд░реБрджреНрдз bubble рджрд╛рдЦрд╡рддреЛ, рдЖрдгрд┐ Timsort рдЪрд╛ рд╡реЗрд│.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛

python3 dsa/demo.py sort
python3 - <<'EOF'
import sys, random; sys.path.insert(0, "dsa"); from algorithms import quick_sort, merge_sort
worst = list(range(2000))                      # already sorted: our quick_sort picks the middle pivot, so it is fine тАФ try the first element as pivot and watch n┬▓
print("quick on sorted input:", quick_sort(worst)[1], "comparisons")
rows = [("Katrina", "3A", 150), ("Aishwarya", "3A", 150), ("Dipika", "3B", 140)]
print(sorted(sorted(rows, key=lambda r: r[0]), key=lambda r: r[2]))   # stable: ties keep the name order
EOF

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ

Bubble ~2,000,000 comparisons, insertion ~1,000,000, merge ~19,000, quick ~13,000 тАФ рдЖрдгрд┐ milliseconds рдпрд╛ counts рдкреНрд░рдорд╛рдгреЗрдЪ рдпреЗрддрд╛рдд; рдЬрд╡рд│рдЬрд╡рд│ sorted рд░рд╛рдВрдЧреЗрд╡рд░ bubble рдЖрдгрд┐ insertion рджреЛрдШрд╛рдВрдирд╛рд╣реА ~2,000 рд▓рд╛рдЧрддрд╛рдд. sorted() рд╕рдЧрд│реНрдпрд╛рдд рдЬрд▓рдж рдЖрд╣реЗ. sorted input рд╡рд░ quick: ~19,000 comparisons (рдордзрд▓рд╛ pivot рддреНрдпрд╛рд▓рд╛ рд╡рд╛рдЪрд╡рддреЛ). stable рджреБрд╣реЗрд░реА sort 150 рдЙрдВрдЪреАрд╡рд░ Aishwarya рд▓рд╛ Katrina рдЪреНрдпрд╛ рдЖрдзреА рдареЗрд╡рддреЛ.

ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ

n = 2,000 рд▓рд╛ n log n рд╡рд┐рд░реБрджреНрдз n┬▓ рд╣рд╛ рд╢рдВрднрд░ рдкрдЯреАрдЪрд╛ рдлрд░рдХ рдЖрд╣реЗ тАФ рддреБрдореНрд╣реА рддреЛ рдореЛрдЬрд▓рд╛рдд тАФ рдЖрдгрд┐ рдХреЛрдгрддреЗ sorts stable рдЖрд╣реЗрдд рдЖрдгрд┐ рддреЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ рдЖрд╣реЗ рд╣реЗ рддреБрдореНрд╣рд╛рд▓рд╛ рдорд╛рд╣реАрдд рдЖрд╣реЗ.

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: database рдордзрд▓рд╛ ORDER BY, log pipelines, leaderboards, рдЖрдгрд┐ request handler рдордзрд▓рд╛ рдкреНрд░рддреНрдпреЗрдХ sorted(...) тАФ рддреБрдореНрд╣реА рдЖрдХрд╛рд░ рдЖрдгрд┐ stability рдЪреНрдпрд╛ рд╣рдореАрд╡рд░рдЪ рдЕрд╡рд▓рдВрдмреВрди рдЕрд╕рддрд╛.

тПня╕П рдкреБрдвреЗ

рдзрдбрд╛ 08 тАФ binary search: рдХреНрд░рдорд╛рдиреЗ рд▓рд╛рд╡рд▓реЗрд▓реА рдиреЛрдВрджрд╡рд╣реА, рдЖрдгрд┐ рдЙрддреНрддрд░рд╛рд╡рд░ search.

ЁЯУ╢ Lesson 07 тАФ Sorting: lining up the class by height

ЁЯУН You are here: Lesson 07 of 12 ┬╖ Next: lesson-08-binary-search


ЁЯУж What's in this branch

Lessons 01тАУ07. Four sorts with comparison counters, timed on the same 2,000 heights, and the reason you call sorted() anyway.

ЁЯзТ Explain like I'm 5

Line the class up by height. Bubble: walk the line, swap any two neighbours in the wrong order, repeat until a walk swaps nobody тАФ slow, every walk is the whole line. Insertion: take the next child and walk them back to their place тАФ quick if the line was nearly right already. Merge: split the class in half, sort each half (by splitting againтАж), then zip two sorted lines together. Quick: pick one child, everyone shorter to the left, taller to the right, repeat on each side. The last two do far less work тАФ that is n log n against n┬▓.

ЁЯЧ║я╕П Diagram

flowchart TD
  A["[5 2 8 1 9 3]"] --> B["[5 2 8]"] & C["[1 9 3]"]
  B --> B1["[2 5 8]"] ; C --> C1["[1 3 9]"]
  B1 & C1 --> M["merge тЖТ [1 2 3 5 8 9]"]

тЭУ What

Sort Time Space Stable Notes
bubble O(n┬▓) O(1) yes a lesson, never a tool
insertion O(n┬▓), O(n) nearly sorted O(1) yes great for tiny or nearly sorted
merge O(n log n) always O(n) yes linked lists, external sorting
quick O(n log n) avg, O(n┬▓) worst O(log n) no fastest in-place in practice
Timsort (sorted) O(n log n), O(n) on runs O(n) yes merge + insertion; what Python and Java ship

ЁЯдФ Why

You will never write a sort at work, and you will call one every day. Knowing the shapes tells you when sorted() inside a loop is the n┬▓ you did not see, and when a heap (lesson 09) or a dict (lesson 05) avoids sorting at all.

ЁЯФз How (in this repo)

Each sort takes a list and returns a new one plus its comparison count; demo.py sort runs all four on the same random 2,000 heights, asserts they agree with sorted, then shows insertion versus bubble on a nearly sorted line, and Timsort's time.

ЁЯзк Try it

python3 dsa/demo.py sort
python3 - <<'EOF'
import sys, random; sys.path.insert(0, "dsa"); from algorithms import quick_sort, merge_sort
worst = list(range(2000))                      # already sorted: our quick_sort picks the middle pivot, so it is fine тАФ try the first element as pivot and watch n┬▓
print("quick on sorted input:", quick_sort(worst)[1], "comparisons")
rows = [("Katrina", "3A", 150), ("Aishwarya", "3A", 150), ("Dipika", "3B", 140)]
print(sorted(sorted(rows, key=lambda r: r[0]), key=lambda r: r[2]))   # stable: ties keep the name order
EOF

тЬЕ Verify тАФ what you should see

Bubble ~2,000,000 comparisons, insertion ~1,000,000, merge ~19,000, quick ~13,000 тАФ and the milliseconds follow the counts; on the nearly sorted line both bubble and insertion need ~2,000. sorted() is the fastest of all. Quick on sorted input: ~19,000 comparisons (the middle pivot saves it). The stable double sort keeps Aishwarya before Katrina at 150.

ЁЯПБ What you just proved

n log n versus n┬▓ is a factor of a hundred at n = 2,000 тАФ you measured it тАФ and you know which sorts are stable and why that matters.

тЪая╕П Common mistakes

ЁЯПн Why this matters in production: ORDER BY in a database, log pipelines, leaderboards, and every sorted(...) in a request handler тАФ the shape and the stability guarantee are what you are relying on.

тПня╕П Next

Lesson 08 тАФ binary search: the sorted register, and searching on the answer.

тЖР PreviousrecursionNext тЖТbinary search

This page is the lesson's README from the lesson-07-sorting branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.