4 Basic Sorting Algorithms in Python
bubble sort, merge sort, heap sort and quick sort
Watch videos of Geeks for Geeks for visualization.
from functools import wraps
from time import time
import numpy as np
size = 100000
print('size = {}\n'.format(size))
def timing(func):
@wraps(func)
def wrapper(*args, **kwargs):
a = np.random.randint(size, size=size)
print('Function {} was called'.format(func.__name__))
start = time()
result = func(a)
end = time()
print('Elapsed time: {:.3f} s\n'.format(end-start))
return result
return wrapper
# bubble sort
@timing
def bubble_sort(arr: 'array') -> 'the sorted array':
n = len(arr)
for i in range(n - 1):
for j in range(n - (i+1)):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
return arr
# merge sort
def merge(left, right):
result = []
i, j = 0, 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
def merge_sort(arr):
n = len(arr)
if n <= 1:
return arr
middle = int(n/2)
left = merge_sort(arr[:middle])
right = merge_sort(arr[middle:])
return merge(left, right)
def in_place_merge(arr, left, middle, right):
i, j = left, middle+1
while i <= middle and j <= right:
if arr[i] <= arr[j]:
i += 1
else:
temp = arr[j]
arr[i+1:j+1] = arr[i:j] # shift part of the array
arr[i] = temp
i += 1
j += 1
middle += 1
def in_place_merge_sort(arr, left, right):
if left < right:
middle = int((left+right) / 2)
in_place_merge_sort(arr, left, middle)
in_place_merge_sort(arr, middle+1, right)
in_place_merge(arr, left, middle, right)
# heap sort
def max_heapify(arr, node: 'in [0, ..., n-1]', heap_size):
left = 2*node + 1
right = left + 1
largest = node
if left <= heap_size-1 and arr[left] > arr[node]:
largest = left
if right <= heap_size-1 and arr[right] > arr[largest]:
largest = right
if largest != node:
arr[node], arr[largest] = arr[largest], arr[node]
max_heapify(arr, largest, heap_size)
def build_max_heap(arr):
n = len(arr)
for node in range(int(n/2)-1, -1, -1):
max_heapify(arr, node, n)
def heap_sort(arr):
build_max_heap(arr)
heap_size = len(arr)
for node in range(len(arr)-1, 0, -1):
arr[0], arr[node] = arr[node], arr[0]
heap_size -= 1
max_heapify(arr, 0, heap_size)
# quick sort
import sys
sys.setrecursionlimit(size)
def partition(arr, left, right):
pivot = arr[right]
i = left - 1
for j in range(left, right):
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i+2:right+1] = arr[i+1:right]
arr[i+1] = pivot
return i + 1
def quick_sort(arr, left, right):
if left < right:
p_index = partition(arr, left, right)
quick_sort(arr, left, p_index-1)
quick_sort(arr, p_index+1, right)
def randomized_partition(arr, left, right):
index = np.random.randint(left, right)
arr[index], arr[right] = arr[right], arr[index]
# the only difference is above two lines
pivot = arr[right]
i = left - 1
for j in range(left, right):
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i+2:right+1] = arr[i+1:right]
arr[i+1] = pivot
return i + 1
def randomized_quick_sort(arr, left, right):
if left < right:
p_index = randomized_partition(arr, left, right)
quick_sort(arr, left, p_index-1)
quick_sort(arr, p_index+1, right)
bubble_sort()
def test(func, *args, **kwargs):
a = np.random.randint(size, size=size)
print('Function {} was called'.format(func.__name__))
start = time()
func(a, *args, **kwargs)
end = time()
print('Elapsed time: {:.3f} s\n'.format(end-start))
test(merge_sort)
test(in_place_merge_sort, left=0, right=size-1)
test(heap_sort)
test(quick_sort, left=0, right=size-1)
test(randomized_quick_sort, left=0, right=size-1)