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.
Counting Comparisons
basic.py
# 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 =
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 =
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 =
print("Before:", numbers)
bubble_sort(numbers)
print("After: ", numbers)
trace.py
# 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)
optimized.py
# 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)
descending.py
# 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)
comparison_count.py
# 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")
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
When to Use
- Teaching sorting concepts
- Small datasets
- Nearly sorted data with optimization
- When simplicity is more important than speed
adjacent_swap
Compare neighboring elements and swap if out of order
early_termination
Stop early if no swaps occur in a pass, meaning list is sorted
quadratic_time
O(n^2) means doubling the data quadruples the time
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