Sorting Algorithms

Back

Loading concept...

🎯 Sorting Algorithms: The Magic of Putting Things in Order

Imagine you have a messy toy box. All your toys are jumbled up—cars mixed with dolls, blocks scattered everywhere. How would you organize them? That’s exactly what sorting algorithms do with numbers and data!

Think of sorting like organizing a line of kids by height for a class photo. There are many ways to do it, and each way has its own tricks!


📚 What We’ll Learn

We’ll discover 8 amazing sorting superpowers:

  1. Insertion Sort - The Card Player’s Method
  2. Merge Sort - The Divide & Team Up Strategy
  3. Quick Sort - The Pivot Party
  4. Counting Sort - The Bucket Counter
  5. Sorting Stability - Keeping Friends Together
  6. Custom Comparators - Your Own Rules
  7. Quick Select - Finding the Special One
  8. Divide and Conquer - The Master Strategy

🃏 Insertion Sort: The Card Player’s Method

The Story

Imagine you’re playing cards. When you get a new card, you slide it into the right spot in your hand. That’s Insertion Sort!

How It Works

  1. Start with the second item
  2. Compare it with items before it
  3. Slide it into the correct position
  4. Repeat for all items!
def insertion_sort(arr):
    for i in range(1, len(arr)):
        key = arr[i]
        j = i - 1
        while j >= 0 and arr[j] > key:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = key
    return arr

Example: Sorting Cards

Hand: [5, 2, 8, 1]

Step 1: Take 2, slide before 5 → [2, 5, 8, 1]
Step 2: Take 8, stays in place → [2, 5, 8, 1]
Step 3: Take 1, slide to start → [1, 2, 5, 8]

Done! 🎉

When to Use It?

✅ Small lists (under 50 items) ✅ Almost sorted data ✅ Simple to understand and code


🏰 Merge Sort: The Divide & Team Up Strategy

The Story

Imagine you need to sort 1000 books. That’s too hard alone! So you:

  1. Split the pile in half
  2. Ask two friends to each sort their half
  3. Combine the sorted halves together

This is Merge Sort - teamwork makes the dream work!

How It Works

graph TD A["8, 3, 7, 1"] --> B["8, 3"] A --> C["7, 1"] B --> D["8"] B --> E["3"] C --> F["7"] C --> G["1"] D --> H["3, 8"] E --> H F --> I["1, 7"] G --> I H --> J["1, 3, 7, 8"] I --> J

The Code

def merge_sort(arr):
    if len(arr) <= 1:
        return arr

    mid = len(arr) // 2
    left = merge_sort(arr[:mid])
    right = merge_sort(arr[mid:])

    return merge(left, right)

def merge(left, right):
    result = []
    i = j = 0
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    result.extend(left[i:])
    result.extend(right[j:])
    return result

Example

Start: [8, 3, 7, 1]
Split: [8, 3] and [7, 1]
Split more: [8] [3] [7] [1]
Merge pairs: [3, 8] [1, 7]
Final merge: [1, 3, 7, 8] ✨

Why Is It Great?

⚡ Always fast: O(n log n) ✅ Works great for huge lists ✅ Stable (keeps equal items in order)


🎯 Quick Sort: The Pivot Party

The Story

Imagine you’re at a party and someone shouts: “Everyone shorter than me, go LEFT! Everyone taller, go RIGHT!”

That person is the pivot. Now each group does the same thing until everyone’s sorted!

How It Works

  1. Pick a pivot (usually the last element)
  2. Put smaller items on left, bigger on right
  3. Repeat for each side
def quick_sort(arr):
    if len(arr) <= 1:
        return arr

    pivot = arr[-1]
    left = [x for x in arr[:-1] if x <= pivot]
    right = [x for x in arr[:-1] if x > pivot]

    return quick_sort(left) + [pivot] + quick_sort(right)

Example: The Pivot Party

Array: [7, 2, 9, 1, 5]
Pivot: 5

Left (≤5):  [2, 1]
Right (>5): [7, 9]

Now sort each side the same way!
Result: [1, 2, 5, 7, 9] 🎉

Quick Sort vs Merge Sort

Feature Quick Sort Merge Sort
Speed Usually faster Always consistent
Space Uses less memory Needs extra space
Stable? No Yes

🪣 Counting Sort: The Bucket Counter

The Story

Imagine you have marbles of 5 colors. Instead of comparing them, just COUNT how many of each color you have!

If you have 3 red, 2 blue, 4 green… just output: red, red, red, blue, blue, green, green, green, green!

How It Works

This works when numbers are in a small range (like 0-100).

def counting_sort(arr):
    if not arr:
        return arr

    max_val = max(arr)
    count = [0] * (max_val + 1)

    # Count each number
    for num in arr:
        count[num] += 1

    # Build sorted array
    result = []
    for i, c in enumerate(count):
        result.extend([i] * c)

    return result

Example

Array: [4, 2, 2, 8, 3, 3, 1]

Counts:
1 appears 1 time
2 appears 2 times
3 appears 2 times
4 appears 1 time
8 appears 1 time

Output: [1, 2, 2, 3, 3, 4, 8] ✨

Super Power

🚀 O(n + k) - Can be faster than comparison sorts! 📦 Best for: ages, grades, small numbers


🤝 Sorting Stability: Keeping Friends Together

The Story

Imagine two students, both named “Sam”, score 90 points. If Sam A came before Sam B originally, a stable sort keeps them in that order!

Stable vs Unstable

Original: [(Sam A, 90), (Bob, 85), (Sam B, 90)]

Stable Sort by score:
[(Bob, 85), (Sam A, 90), (Sam B, 90)]
✅ Sam A still before Sam B!

Unstable Sort might give:
[(Bob, 85), (Sam B, 90), (Sam A, 90)]
❌ Order of Sams changed!

Which Sorts Are Stable?

Algorithm Stable?
Insertion Sort ✅ Yes
Merge Sort ✅ Yes
Counting Sort ✅ Yes
Quick Sort ❌ No

Why Does It Matter?

When sorting by multiple things! Sort by name first, then by score - stable sort keeps names in order within same scores.


🎨 Custom Comparators: Your Own Rules

The Story

What if you want to sort words by length? Or people by age? You need your own sorting rules!

Python’s Key Function

# Sort by length
words = ["cat", "elephant", "dog", "ant"]
sorted(words, key=len)
# Result: ["cat", "dog", "ant", "elephant"]

# Sort by last letter
sorted(words, key=lambda x: x[-1])
# Result: ["dog", "cat", "ant", "elephant"]

Sorting Objects

students = [
    {"name": "Alice", "age": 12},
    {"name": "Bob", "age": 10},
    {"name": "Charlie", "age": 11}
]

# Sort by age
sorted(students, key=lambda s: s["age"])
# Bob (10), Charlie (11), Alice (12)

# Sort by name
sorted(students, key=lambda s: s["name"])
# Alice, Bob, Charlie

Reverse Order

numbers = [3, 1, 4, 1, 5]
sorted(numbers, reverse=True)
# Result: [5, 4, 3, 1, 1]

🔍 Quick Select: Finding the Special One

The Story

What if you don’t need to sort everything? You just want the 3rd smallest number?

Quick Select finds the kth smallest without sorting everything!

How It Works

Like Quick Sort, but only look at ONE side!

def quick_select(arr, k):
    if len(arr) == 1:
        return arr[0]

    pivot = arr[-1]
    left = [x for x in arr[:-1] if x <= pivot]
    right = [x for x in arr[:-1] if x > pivot]

    if k <= len(left):
        return quick_select(left, k)
    elif k == len(left) + 1:
        return pivot
    else:
        return quick_select(right, k - len(left) - 1)

Example: Find 3rd Smallest

Array: [7, 2, 9, 1, 5]
Find: 3rd smallest (k=3)

Pivot: 5
Left (≤5): [2, 1]  → 2 items
Right (>5): [7, 9]

k=3 > len(left)=2, so answer is pivot!
3rd smallest = 5 ✨

When to Use?

✅ Find median ✅ Find top 10 scores ✅ Faster than sorting everything!


⚔️ Divide and Conquer: The Master Strategy

The Story

A wise king couldn’t defeat a large army. So he split it into small groups, defeated each one, then combined his victories!

This is Divide and Conquer - the secret behind Merge Sort and Quick Sort!

The Three Steps

graph TD A["Big Problem"] --> B["Divide into smaller parts"] B --> C["Solve each part"] C --> D["Combine solutions"] D --> E["Final Answer!"]

The Pattern

  1. DIVIDE: Split the problem
  2. CONQUER: Solve smaller pieces
  3. COMBINE: Put answers together

Examples in Sorting

Algorithm Divide Conquer Combine
Merge Sort Split in half Sort each half Merge sorted halves
Quick Sort Partition by pivot Sort each side Already combined!

Why Is It Powerful?

🧮 Complexity: Often O(n log n) 🧩 Simple: Big problems become tiny ones ♻️ Recursive: Same logic repeats at each level


🏆 The Sorting Showdown

Speed Comparison

Algorithm Best Average Worst
Insertion O(n) O(n²) O(n²)
Merge O(n log n) O(n log n) O(n log n)
Quick O(n log n) O(n log n) O(n²)
Counting O(n+k) O(n+k) O(n+k)

When to Use What?

Small list (< 50)? → Insertion Sort
Need stability? → Merge Sort
General purpose? → Quick Sort
Small number range? → Counting Sort
Find kth element? → Quick Select

🎉 You Did It!

Now you know:

Insertion Sort - Like sorting cards in your hand ✅ Merge Sort - Divide, sort, and merge back ✅ Quick Sort - Pick a pivot and partition ✅ Counting Sort - Just count them up! ✅ Stability - Keep equal items in order ✅ Custom Comparators - Sort by your own rules ✅ Quick Select - Find kth without full sort ✅ Divide & Conquer - The master strategy

You’re now a Sorting Wizard! 🧙‍♂️✨

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.