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)
posted @ 2019-07-03 23:39  resolvent  阅读(154)  评论(0编辑  收藏  举报