Common Algorithms
Bubble Sort
Organizing data in order is fundamental to computing, from displaying search results to preparing data for efficient lookup. Bubble sort is one of the simplest sorting algorithms to understand and implement, making it an excellent starting point for learning how sorting works, even though faster algorithms exist for production use.
Bubble sort repeatedly steps through the list, compares adjacent elements, and swaps them if they are in the wrong order. Larger elements "bubble up" to the end.
Algorithm
- Repeat for each element:
- Compare adjacent pairs
- If out of order, swap them
- After each pass, the largest unsorted element is in its final position
- Repeat until no swaps are made
adjacent_swap
Compare neighboring elements and swap if out of order
Basic Implementation
basic.py
Replay: real traced execution (multi-file project)
# Basic bubble sort
def bubble_sort(arr):
"""Bubble sort implementation"""
n = len(arr)
# Bubble sort implementation
for i in range(n - 1):
for j in range(n - i - 1):
if arr[j] > arr[j + 1]:
# Swap
arr[j], arr[j + 1] = arr[j + 1], arr[j]
# Test bubble sort
numbers = [64, 34, 25, 12, 22, 11, 90]
print("Before:", numbers)
bubble_sort(numbers)
print("After: ", numbers)
# Basic bubble sort
def bubble_sort(arr):
"""Bubble sort implementation"""
n = len(arr)
# Bubble sort implementation
for i in range(n - 1):
for j in range(n - i - 1):
if arr[j] > arr[j + 1]:
# Swap
arr[j], arr[j + 1] = arr[j + 1], arr[j]
# Test bubble sort
numbers = [5, 1, 4, 2, 8]
print("Before:", numbers)
bubble_sort(numbers)
print("After: ", numbers)
# Basic bubble sort
def bubble_sort(arr):
"""Bubble sort implementation"""
n = len(arr)
# Bubble sort implementation
for i in range(n - 1):
for j in range(n - i - 1):
if arr[j] > arr[j + 1]:
# Swap
arr[j], arr[j + 1] = arr[j + 1], arr[j]
# Test bubble sort
numbers = [3, 2, 1]
print("Before:", numbers)
bubble_sort(numbers)
print("After: ", numbers)
numbers ← [64, 34, 25, 12, 22, 11, 90]
16# Test bubble sort17numbers→ [64, 34, 25, 12, 22, 11, 90] = [64, 34, 25, 12, 22, 11, 90]18#@numbers=[5, 1, 4, 2, 8], [3, 2, 1]1920print("Before:", numbers[64, 34, 25, 12, 22, 11, 90])21bubble_sort(numbers[64, 34, 25, 12, 22, 11, 90])22print("After: ", numbers)outputBefore: [64, 34, 25, 12, 22, 11, 90]n ← 7
4def bubble_sort(arr[64, 34, 25, 12, 22, 11, 90]):5 """Bubble sort implementation"""6 n→ 7 = len(arr[64, 34, 25, 12, 22, 11, 90])for i in range(n - 1):
pass 1 of 68# Bubble sort implementation9for i0 in range(n7 - 1):10 for j in range(n - i - 1):11 if arr[j] > arr[j + 1]:All 6 passes — pass 1 is the card above pass i1 0 2 1 3 2 4 3 5 4 6 5 for j in range(n - i - 1):
pass 1 of 219for i in range(n - 1):10 for j0 in range(n7 - i0 - 1):11 if arr[j] > arr[j + 1]:12 # Swap21 passes — pass 1 is the card above pass ji1 0 0 2 1 0 3 2 0 4 3 0 5 4 0 6 5 0 7 0 1 8 1 1 9 2 1 ⋯ 10 more passes ⋯ 20 1 4 21 0 5 arr[j] ← 34, arr[j + 1] ← 64
pass 1 of 1410for j in range(n - i - 1):11 if arr[j]64 > arr[j + 1]34:12 # Swap13 arr[j]→ 34, arr[j + 1]→ 64 = arr[j + 1], arr[j]14 passes — pass 1 is the card above pass arr[j]arr[j + 1]1 64 → 34 34 → 64 2 64 → 25 25 → 64 3 64 → 12 12 → 64 4 64 → 22 22 → 64 5 64 → 11 11 → 64 6 34 → 25 25 → 34 7 34 → 12 12 → 34 8 34 → 22 22 → 34 9 34 → 11 11 → 34 ⋯ 3 more passes ⋯ 13 22 → 11 11 → 22 14 12 → 11 11 → 12 numbers ← [11, 12, 22, 25, 34, 64, 90]
20print("Before:", numbers)21bubble_sort(numbers→ [11, 12, 22, 25, 34, 64, 90])22print("After: ", numbers[11, 12, 22, 25, 34, 64, 90])outputAfter: [11, 12, 22, 25, 34, 64, 90]
numbers ← [5, 1, 4, 2, 8]
16# Test bubble sort17numbers→ [5, 1, 4, 2, 8] = [5, 1, 4, 2, 8]1819print("Before:", numbers[5, 1, 4, 2, 8])20bubble_sort(numbers[5, 1, 4, 2, 8])21print("After: ", numbers)outputBefore: [5, 1, 4, 2, 8]n ← 5
4def bubble_sort(arr[5, 1, 4, 2, 8]):5 """Bubble sort implementation"""6 n→ 5 = len(arr[5, 1, 4, 2, 8])for i in range(n - 1):
pass 1 of 48# Bubble sort implementation9for i0 in range(n5 - 1):10 for j in range(n - i - 1):11 if arr[j] > arr[j + 1]:All 4 passes — pass 1 is the card above pass i1 0 2 1 3 2 4 3 for j in range(n - i - 1):
pass 1 of 109for i in range(n - 1):10 for j0 in range(n5 - i0 - 1):11 if arr[j] > arr[j + 1]:12 # SwapAll 10 passes — pass 1 is the card above pass ji1 0 0 2 1 0 3 2 0 4 3 0 5 0 1 6 1 1 7 2 1 8 0 2 9 1 2 10 0 3 arr[j] ← 1, arr[j + 1] ← 5
pass 1 of 410for j in range(n - i - 1):11 if arr[j]5 > arr[j + 1]1:12 # Swap13 arr[j]→ 1, arr[j + 1]→ 5 = arr[j + 1], arr[j]All 4 passes — pass 1 is the card above pass arr[j]arr[j + 1]1 5 → 1 1 → 5 2 5 → 4 4 → 5 3 5 → 2 2 → 5 4 4 → 2 2 → 4 numbers ← [1, 2, 4, 5, 8]
19print("Before:", numbers)20bubble_sort(numbers→ [1, 2, 4, 5, 8])21print("After: ", numbers[1, 2, 4, 5, 8])outputAfter: [1, 2, 4, 5, 8]
numbers ← [3, 2, 1]
16# Test bubble sort17numbers→ [3, 2, 1] = [3, 2, 1]1819print("Before:", numbers[3, 2, 1])20bubble_sort(numbers[3, 2, 1])21print("After: ", numbers)outputBefore: [3, 2, 1]n ← 3
4def bubble_sort(arr[3, 2, 1]):5 """Bubble sort implementation"""6 n→ 3 = len(arr[3, 2, 1])for i in range(n - 1):
pass 1 of 28# Bubble sort implementation9for i0 in range(n3 - 1):10 for j in range(n - i - 1):11 if arr[j] > arr[j + 1]:for j in range(n - i - 1):
pass 1 of 39for i in range(n - 1):10 for j0 in range(n3 - i0 - 1):11 if arr[j] > arr[j + 1]:12 # SwapAll 3 passes — pass 1 is the card above pass ji1 0 0 2 1 0 3 0 1 arr[j] ← 2, arr[j + 1] ← 3
pass 1 of 310for j in range(n - i - 1):11 if arr[j]3 > arr[j + 1]2:12 # Swap13 arr[j]→ 2, arr[j + 1]→ 3 = arr[j + 1], arr[j]All 3 passes — pass 1 is the card above pass inarr[j]arr[j + 1]1 — — 3 → 2 2 → 3 2 1 3 3 → 1 1 → 3 3 — — 2 → 1 1 → 2 for i in range(n - 1):
pass 2 of 28# Bubble sort implementation9for i1 in range(n3 - 1):10 for j in range(n - i - 1):11 if arr[j] > arr[j + 1]:numbers ← [1, 2, 3]
19print("Before:", numbers)20bubble_sort(numbers→ [1, 2, 3])21print("After: ", numbers[1, 2, 3])outputAfter: [1, 2, 3]
Trace Example
trace.py
Replay: real traced execution (multi-file project)
# Bubble sort with trace
def bubble_sort_trace(arr):
"""Bubble sort with step-by-step trace"""
n = len(arr)
# Trace each pass
for i in range(n - 1):
print(f"Pass {i + 1}:")
swapped = False
for j in range(n - i - 1):
if arr[j] > arr[j + 1]:
print(f" Swap {arr[j]} and {arr[j + 1]}")
arr[j], arr[j + 1] = arr[j + 1], arr[j]
swapped = True
print(f" Result: {arr}")
if not swapped:
print(" No swaps - array is sorted!")
break
# Test with trace
numbers = [5, 2, 8, 1, 9]
print("Initial:", numbers)
print()
bubble_sort_trace(numbers)
numbers ← [5, 2, 8, 1, 9]
26# Test with trace27numbers→ [5, 2, 8, 1, 9] = [5, 2, 8, 1, 9]2829print("Initial:", numbers[5, 2, 8, 1, 9])30print()31bubble_sort_trace(numbers[5, 2, 8, 1, 9])outputInitial: [5, 2, 8, 1, 9]n ← 5
4def bubble_sort_trace(arr[5, 2, 8, 1, 9]):5 """Bubble sort with step-by-step trace"""6 n→ 5 = len(arr[5, 2, 8, 1, 9])swapped ← False
pass 1 of 48# Trace each pass9for i0 in range(n5 - 1):10 print(f"Pass {i0 + 1}:")11 swapped→ False = FalseoutputPass 1:All 4 passes — pass 1 is the card above pass iswapped1 0 False 2 1 False 3 2 False 4 3 False for j in range(n - i - 1):
pass 1 of 1013for j0 in range(n5 - i0 - 1):14 if arr[j] > arr[j + 1]:15 print(f" Swap {arr[j]} and {arr[j + 1]}")All 10 passes — pass 1 is the card above pass ji1 0 0 2 1 0 3 2 0 4 3 0 5 0 1 6 1 1 7 2 1 8 0 2 9 1 2 10 0 3 arr[j] ← 2, arr[j + 1] ← 5, swapped ← True
pass 1 of 413for j in range(n - i - 1):14 if arr[j]5 > arr[j + 1]2:15 print(f" Swap {arr[j]5} and {arr[j + 1]2}")16 arr[j]→ 2, arr[j + 1]→ 5 = arr[j + 1], arr[j]17 swapped→ True = Trueoutput Swap 5 and 2All 4 passes — pass 1 is the card above pass arr[j]arr[j + 1]swapped1 5 → 2 2 → 5 True 2 8 → 1 1 → 8 True 3 5 → 1 1 → 5 True 4 2 → 1 1 → 2 True print(f" Result: {arr}")
19print(f" Result: {arr[2, 5, 1, 8, 9]}")output Result: [2, 5, 1, 8, 9]print(f" Result: {arr}")
19print(f" Result: {arr[2, 1, 5, 8, 9]}")output Result: [2, 1, 5, 8, 9]print(f" Result: {arr}")
19print(f" Result: {arr[1, 2, 5, 8, 9]}")output Result: [1, 2, 5, 8, 9]print(f" Result: {arr}")
19print(f" Result: {arr[1, 2, 5, 8, 9]}")output Result: [1, 2, 5, 8, 9]if not swapped:
21if not swappedFalse:22 print(" No swaps - array is sorted!")23 breakoutput No swaps - array is sorted!numbers ← [1, 2, 5, 8, 9]
30print()31bubble_sort_trace(numbers→ [1, 2, 5, 8, 9])
Optimized Version
optimized.py
Replay: real traced execution (multi-file project)
# Optimized bubble sort
def bubble_sort_optimized(arr):
"""Optimized bubble sort with early termination"""
n = len(arr)
passes = 0
# Optimized with early termination
for i in range(n - 1):
passes += 1
swapped = False
for j in range(n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
swapped = True
# If no swaps, array is sorted
if not swapped:
break
return passes
# Test on different inputs
almost_sorted = [1, 2, 3, 5, 4, 6, 7, 8]
reversed_list = [8, 7, 6, 5, 4, 3, 2, 1]
print("Almost sorted:")
print("Before:", almost_sorted)
passes1 = bubble_sort_optimized(almost_sorted)
print("After: ", almost_sorted)
print("Passes:", passes1)
print("\nReverse sorted:")
print("Before:", reversed_list)
passes2 = bubble_sort_optimized(reversed_list)
print("After: ", reversed_list)
print("Passes:", passes2)
almost_sorted ← [1, 2, 3, 5, 4, 6, 7, 8], reversed_list ← [8, 7, 6, 5, 4, 3, 2, 1]
26# Test on different inputs27almost_sorted→ [1, 2, 3, 5, 4, 6, 7, 8] = [1, 2, 3, 5, 4, 6, 7, 8]28reversed_list→ [8, 7, 6, 5, 4, 3, 2, 1] = [8, 7, 6, 5, 4, 3, 2, 1]2930print("Almost sorted:")31print("Before:", almost_sorted[1, 2, 3, 5, 4, 6, 7, 8])32passes1 = bubble_sort_optimized(almost_sorted[1, 2, 3, 5, 4, 6, 7, 8])33print("After: ", almost_sorted)outputAlmost sorted: Before: [1, 2, 3, 5, 4, 6, 7, 8]n ← 8, passes ← 0
pass 1 of 24def bubble_sort_optimized(arr[1, 2, 3, 5, 4, 6, 7, 8]):5 """Optimized bubble sort with early termination"""6 n→ 8 = len(arr[1, 2, 3, 5, 4, 6, 7, 8])7 passes→ 0 = 0passes ← 1, swapped ← False
pass 1 of 99# Optimized with early termination10for i0 in range(n8 - 1):11 passes→ 1 += 112 swapped→ False = FalseAll 9 passes — pass 1 is the card above pass ipassesswapped1 0 0 → 1 False 2 1 1 → 2 False 3 0 0 → 1 False 4 1 1 → 2 False 5 2 2 → 3 False 6 3 3 → 4 False 7 4 4 → 5 False 8 5 5 → 6 False 9 6 6 → 7 False for j in range(n - i - 1):
pass 1 of 4114for j0 in range(n8 - i0 - 1):15 if arr[j] > arr[j + 1]:16 arr[j], arr[j + 1] = arr[j + 1], arr[j]41 passes — pass 1 is the card above pass jiswapped1 0 0 — 2 1 0 — 3 2 0 — 4 3 0 — 5 4 0 — 6 5 0 — 7 6 0 — 8 0 1 — 9 1 1 — ⋯ 30 more passes ⋯ 40 1 5 — 41 0 6 — arr[j] ← 4, arr[j + 1] ← 5, swapped ← True
pass 1 of 2914for j in range(n - i - 1):15 if arr[j]5 > arr[j + 1]4:16 arr[j]→ 4, arr[j + 1]→ 5 = arr[j + 1], arr[j]17 swapped→ True = True29 passes — pass 1 is the card above pass arr[j]arr[j + 1]swapped1 5 → 4 4 → 5 True 2 8 → 7 7 → 8 True 3 8 → 6 6 → 8 True 4 8 → 5 5 → 8 True 5 8 → 4 4 → 8 True 6 8 → 3 3 → 8 True 7 8 → 2 2 → 8 True 8 8 → 1 1 → 8 True 9 7 → 6 6 → 7 True ⋯ 18 more passes ⋯ 28 3 → 1 1 → 3 True 29 2 → 1 1 → 2 True if not swapped:
19# If no swaps, array is sorted20if not swappedFalse:21 breakreturn passes
23return passes2almost_sorted ← [1, 2, 3, 4, 5, 6, 7, 8], passes1 ← 2
31print("Before:", almost_sorted)32passes1→ 2 = bubble_sort_optimized(almost_sorted→ [1, 2, 3, 4, 5, 6, 7, 8])33print("After: ", almost_sorted[1, 2, 3, 4, 5, 6, 7, 8])34print("Passes:", passes12)3536print("\nReverse sorted:")37print("Before:", reversed_list[8, 7, 6, 5, 4, 3, 2, 1])38passes2 = bubble_sort_optimized(reversed_list[8, 7, 6, 5, 4, 3, 2, 1])39print("After: ", reversed_list)outputAfter: [1, 2, 3, 4, 5, 6, 7, 8] Passes: 2 Reverse sorted: Before: [8, 7, 6, 5, 4, 3, 2, 1]n ← 8, passes ← 0
pass 2 of 24def bubble_sort_optimized(arr[8, 7, 6, 5, 4, 3, 2, 1]):5 """Optimized bubble sort with early termination"""6 n→ 8 = len(arr[8, 7, 6, 5, 4, 3, 2, 1])7 passes→ 0 = 0return passes
23return passes7reversed_list ← [1, 2, 3, 4, 5, 6, 7, 8], passes2 ← 7
37print("Before:", reversed_list)38passes2→ 7 = bubble_sort_optimized(reversed_list→ [1, 2, 3, 4, 5, 6, 7, 8])39print("After: ", reversed_list[1, 2, 3, 4, 5, 6, 7, 8])40print("Passes:", passes27)outputAfter: [1, 2, 3, 4, 5, 6, 7, 8] Passes: 7
early_termination
Stop early if no swaps occur in a pass, meaning list is sorted
Descending Order
descending.py
Replay: real traced execution (multi-file project)
# Sort descending
def bubble_sort_ascending(arr):
"""Sort in ascending order"""
n = len(arr)
for i in range(n - 1):
for j in range(n - i - 1):
# Ascending: swap if left > right
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
def bubble_sort_descending(arr):
"""Sort in descending order"""
n = len(arr)
for i in range(n - 1):
for j in range(n - i - 1):
# Descending: swap if left < right
if arr[j] < arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
# Test both directions
numbers1 = [64, 34, 25, 12, 22]
numbers2 = [64, 34, 25, 12, 22]
bubble_sort_ascending(numbers1)
print("Ascending: ", numbers1)
bubble_sort_descending(numbers2)
print("Descending:", numbers2)
numbers1 ← [64, 34, 25, 12, 22], numbers2 ← [64, 34, 25, 12, 22]
24# Test both directions25numbers1→ [64, 34, 25, 12, 22] = [64, 34, 25, 12, 22]26numbers2→ [64, 34, 25, 12, 22] = [64, 34, 25, 12, 22]2728bubble_sort_ascending(numbers1[64, 34, 25, 12, 22])29print("Ascending: ", numbers1)n ← 5
4def bubble_sort_ascending(arr[64, 34, 25, 12, 22]):5 """Sort in ascending order"""6 n→ 5 = len(arr[64, 34, 25, 12, 22])7 for i in range(n - 1):for i in range(n - 1):
pass 1 of 46n = len(arr)7for i0 in range(n5 - 1):8 for j in range(n - i - 1):9 # Ascending: swap if left > rightAll 4 passes — pass 1 is the card above pass i1 0 2 1 3 2 4 3 for j in range(n - i - 1): # Ascending: swap if left > rig…
pass 1 of 107for i in range(n - 1):8 for j0 in range(n5 - i0 - 1):9 # Ascending: swap if left > right10 if arr[j] > arr[j + 1]:11 arr[j], arr[j + 1] = arr[j + 1], arr[j]All 10 passes — pass 1 is the card above pass ji1 0 0 2 1 0 3 2 0 4 3 0 5 0 1 6 1 1 7 2 1 8 0 2 9 1 2 10 0 3 arr[j] ← 34, arr[j + 1] ← 64
pass 1 of 99# Ascending: swap if left > right10if arr[j]64 > arr[j + 1]34:11 arr[j]→ 34, arr[j + 1]→ 64 = arr[j + 1], arr[j]All 9 passes — pass 1 is the card above pass arr[j]arr[j + 1]1 64 → 34 34 → 64 2 64 → 25 25 → 64 3 64 → 12 12 → 64 4 64 → 22 22 → 64 5 34 → 25 25 → 34 6 34 → 12 12 → 34 7 34 → 22 22 → 34 8 25 → 12 12 → 25 9 25 → 22 22 → 25 numbers1 ← [12, 22, 25, 34, 64]
28bubble_sort_ascending(numbers1→ [12, 22, 25, 34, 64])29print("Ascending: ", numbers1[12, 22, 25, 34, 64])3031bubble_sort_descending(numbers2[64, 34, 25, 12, 22])32print("Descending:", numbers2)outputAscending: [12, 22, 25, 34, 64]n ← 5
14def bubble_sort_descending(arr[64, 34, 25, 12, 22]):15 """Sort in descending order"""16 n→ 5 = len(arr[64, 34, 25, 12, 22])17 for i in range(n - 1):for i in range(n - 1):
pass 1 of 416n = len(arr)17for i0 in range(n5 - 1):18 for j in range(n - i - 1):19 # Descending: swap if left < rightAll 4 passes — pass 1 is the card above pass iarr[j]arr[j + 1]1 0 12 → 22 22 → 12 2 1 — — 3 2 — — 4 3 — — for j in range(n - i - 1): # Descending: swap if left < ri…
pass 1 of 1017for i in range(n - 1):18 for j0 in range(n5 - i0 - 1):19 # Descending: swap if left < right20 if arr[j] < arr[j + 1]:21 arr[j], arr[j + 1] = arr[j + 1], arr[j]All 10 passes — pass 1 is the card above pass jiarr[j]arr[j + 1]1 0 0 — — 2 1 0 — — 3 2 0 — — 4 3 0 12 → 22 22 → 12 5 0 1 — — 6 1 1 — — 7 2 1 — — 8 0 2 — — 9 1 2 — — 10 0 3 — — arr[j] ← 22, arr[j + 1] ← 12
19# Descending: swap if left < right20if arr[j]12 < arr[j + 1]22:21 arr[j]→ 22, arr[j + 1]→ 12 = arr[j + 1], arr[j]numbers2 ← [64, 34, 25, 22, 12]
31bubble_sort_descending(numbers2→ [64, 34, 25, 22, 12])32print("Descending:", numbers2[64, 34, 25, 22, 12])outputDescending: [64, 34, 25, 22, 12]
Counting Comparisons
comparison_count.py
Replay: real traced execution (multi-file project)
# Count comparisons and swaps
def bubble_sort_counted(arr):
"""Bubble sort that counts operations"""
n = len(arr)
comparisons = 0
swaps = 0
# Count operations
for i in range(n - 1):
for j in range(n - i - 1):
comparisons += 1
if arr[j] > arr[j + 1]:
swaps += 1
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return comparisons, swaps
# Test on different inputs
sorted_list = [1, 2, 3, 4, 5]
reversed_list = [5, 4, 3, 2, 1]
random_list = [3, 1, 4, 2, 5]
comp1, swap1 = bubble_sort_counted(sorted_list.copy())
print(f"Already sorted: {comp1} comparisons, {swap1} swaps")
comp2, swap2 = bubble_sort_counted(reversed_list.copy())
print(f"Reverse sorted: {comp2} comparisons, {swap2} swaps")
comp3, swap3 = bubble_sort_counted(random_list.copy())
print(f"Random order: {comp3} comparisons, {swap3} swaps")
sorted_list ← [1, 2, 3, 4, 5], reversed_list ← [5, 4, 3, 2, 1]
21# Test on different inputs22sorted_list→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5]23reversed_list→ [5, 4, 3, 2, 1] = [5, 4, 3, 2, 1]24random_list→ [3, 1, 4, 2, 5] = [3, 1, 4, 2, 5]2526comp1, swap1 = bubble_sort_counted(sorted_list[1, 2, 3, 4, 5].copy())27print(f"Already sorted: {comp1} comparisons, {swap1} swaps")n ← 5, comparisons ← 0, swaps ← 0
pass 1 of 34def bubble_sort_counted(arr[1, 2, 3, 4, 5]):5 """Bubble sort that counts operations"""6 n→ 5 = len(arr[1, 2, 3, 4, 5])7 comparisons→ 0 = 08 swaps→ 0 = 0All 3 passes — pass 1 is the card above pass arrncomparisonsswaps1 [1, 2, 3, 4, 5] 5 0 0 2 [5, 4, 3, 2, 1] 5 0 0 3 [3, 1, 4, 2, 5] 5 0 0 for i in range(n - 1):
pass 1 of 1210# Count operations11for i0 in range(n5 - 1):12 for j in range(n - i - 1):13 comparisons += 1All 12 passes — pass 1 is the card above pass i1 0 2 1 3 2 4 3 5 0 6 1 7 2 8 3 9 0 10 1 11 2 12 3 comparisons ← 1
pass 1 of 3011for i in range(n - 1):12 for j0 in range(n5 - i0 - 1):13 comparisons→ 1 += 114 if arr[j] > arr[j + 1]:30 passes — pass 1 is the card above pass jicomparisons1 0 0 0 → 1 2 1 0 1 → 2 3 2 0 2 → 3 4 3 0 3 → 4 5 0 1 4 → 5 6 1 1 5 → 6 7 2 1 6 → 7 8 0 2 7 → 8 9 1 2 8 → 9 ⋯ 19 more passes ⋯ 29 1 2 8 → 9 30 0 3 9 → 10 return comparisons, swaps
18return comparisons10, swaps0comp1 ← 10, swap1 ← 0
26comp1→ 10, swap1→ 0 = bubble_sort_counted(sorted_list[1, 2, 3, 4, 5].copy())27print(f"Already sorted: {comp110} comparisons, {swap10} swaps")2829comp2, swap2 = bubble_sort_counted(reversed_list[5, 4, 3, 2, 1].copy())30print(f"Reverse sorted: {comp2} comparisons, {swap2} swaps")outputAlready sorted: 10 comparisons, 0 swapsswaps ← 1, arr[j] ← 4, arr[j + 1] ← 5
pass 1 of 1313comparisons += 114if arr[j]5 > arr[j + 1]4:15 swaps→ 1 += 116 arr[j]→ 4, arr[j + 1]→ 5 = arr[j + 1], arr[j]13 passes — pass 1 is the card above pass swapsarr[j]arr[j + 1]1 0 → 1 5 → 4 4 → 5 2 1 → 2 5 → 3 3 → 5 3 2 → 3 5 → 2 2 → 5 4 3 → 4 5 → 1 1 → 5 5 4 → 5 4 → 3 3 → 4 6 5 → 6 4 → 2 2 → 4 7 6 → 7 4 → 1 1 → 4 8 7 → 8 3 → 2 2 → 3 9 8 → 9 3 → 1 1 → 3 ⋯ 2 more passes ⋯ 12 1 → 2 4 → 2 2 → 4 13 2 → 3 3 → 2 2 → 3 return comparisons, swaps
18return comparisons10, swaps10comp2 ← 10, swap2 ← 10
29comp2→ 10, swap2→ 10 = bubble_sort_counted(reversed_list[5, 4, 3, 2, 1].copy())30print(f"Reverse sorted: {comp210} comparisons, {swap210} swaps")3132comp3, swap3 = bubble_sort_counted(random_list[3, 1, 4, 2, 5].copy())33print(f"Random order: {comp3} comparisons, {swap3} swaps")outputReverse sorted: 10 comparisons, 10 swapsreturn comparisons, swaps
18return comparisons10, swaps3comp3 ← 10, swap3 ← 3
32comp3→ 10, swap3→ 3 = bubble_sort_counted(random_list[3, 1, 4, 2, 5].copy())33print(f"Random order: {comp310} comparisons, {swap33} swaps")outputRandom order: 10 comparisons, 3 swaps
Characteristics
- Time complexity: O(n^2) - two nested loops
- Space complexity: O(1) - sorts in place
- Stable: equal elements maintain relative order
- Best case: O(n) - already sorted with optimization
- Worst case: O(n^2) - reverse sorted
quadratic_time
O(n^2) means doubling the data quadruples the time
When to Use
- Teaching sorting concepts
- Small datasets
- Nearly sorted data with optimization
- When simplicity is more important than speed
Exercise: practical.py
Implement bubble sort to sort a list of student records by grade, preserving the original order for students with the same grade