bubble sort

swap adjacent elements to bubble up largest element in arr[0:n-i]

def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        for j in range(0, n - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr

n passes, (n-1)/2 comparisons per pass, so we have

selection sort

swap current item and min of arr[i:n]

def selection_sort(arr):
    n = len(arr)
    for i in range(n):
        min_idx = i
        for j in range(i + 1, n):
            if arr[j] < arr[min_idx]:
                min_idx = j
        arr[i], arr[min_idx] = arr[min_idx], arr[i]
    return arr

n passes, (n-1)/2 comparisons per pass, so we have

insertion sort

compare current with items to its left, insert into its correct position from 1 to n

def insertion_sort(arr):
    for i in range(1, len(arr)):
        key = arr[i]  # num to be inserted
        j = i - 1 
 
		# loop through arr[0:i]
        while j >= 0 and arr[j] > key:
            arr[j + 1] = arr[j]  # shift right
            j -= 1
        
        arr[j + 1] = key # insert
 
    return arr 

again

merge sort

divide and conquer - recursively sort halves before merging them

def merge_sort(arr):
    if len(arr) > 1:
        mid = len(arr) // 2
        L = arr[:mid]
        R = arr[mid:]
 
        merge_sort(L)
        merge_sort(R)
 
        # merge sorted subarrays
        i = 0 # to traverse L
        j = 0 # to traverse R
        k = 0 # to traverse arr
        while i < len(L) and j < len(R):
            if L[i] < R[j]:
                arr[k] = L[i]
                i += 1
            else:
                arr[k] = R[j]
                j += 1
            k += 1
 
        # add the leftovers    
        while i < len(L):
            arr[k] = L[i]
            i += 1
            k += 1
        while j < len(R):
            arr[k] = R[j]
            j += 1
            k += 1
    return arr

O(n log n):

  • O(log n) to divide into log n levels
  • O(n) to merge each level

quick sort

divide and conquer - choose a pivot as partition and recursively sort the subarrays

A simplified implementation:

def quick_sort(arr):
    if len(arr) <= 1:
        return arr
    pivot = arr[len(arr) // 2]
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    return quick_sort(left) + middle + quick_sort(right)

cyclic sort