7个经典排序算法

介绍

作为算法入门,排序算法是最最基础的部分,今天整理一下7个经典的排序算法,包括insertionSort,ShellSort,BubbleSort,QuickSort,SelectionSort,HeapSort,MergeSort,并对他们的复杂度做一个对比总结。顺便推荐一个网站Comparison Sorting Algorithms,可以演示算法具体步骤。注意本文代码部分都使用的是python3。

Insertion Sort

主要思想是decrease-and-conquer,遍历整个数组,把小的值往前放,直接上代码:

# input: an array A
# output: a sorted array A
def insertionSort(A):
    n = len(A)
    if n <= 1:
        return A
    for i in range(1,n):
        v = A[i]
        j = i - 1
        while j >= 0 and v <= A[j]:
            A[j+1] = A[j]
            j = j - 1
        A[j+1] = v
        #print(A)

p1

ShellSort

希尔排序是插入排序的另一个(高阶)版本,可以把一个无序数组变成一个大致有序的数组,然后再通过插入排序就可以高效完成排序了。

p2

def shellSort(A):
    n = len(A)
    gap = n//2
    while gap>0:
        for i in range(gap,n):
            key = A[i]
            while i>gap and A[i-gap]>key:
                A[i] = A[i-gap]
                i -= gap
            A[i] = key
        gap //= 2
    #A = insertionSort(A)

BubbleSort

冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。

p3

def bubbleSort(A):
    n = len(A)
    if n <= 1:
        return A
    for i in range(n):
        # Last i elements are already in place
        for j in range(0, n-i-1):
            if A[j] > A[j+1] :
                A[j], A[j+1] = A[j+1], A[j]

QuickSort

快排的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

p4

def quick_sort(A,l,r):
    if l < r:
        s = partition(A,l,r)
        quick_sort(A,l,s-1)
        quick_sort(A,s+1,r)

def partition(A,l,r):
     p = A[l] # pivot
     i = l
     j = r
     while i < j:
        while i < r and A[i] <= p:
             i += 1
        while j >= l and A[j] > p:
             j -= 1
        A[i],A[j] = A[j],A[i]
     A[i],A[j] = A[j],A[i] # undo the last swap
     A[l],A[j] = A[j],A[l] # bring the pivot to the correct position
     return j

SelectionSort

选择排序是一种简单直观的排序算法。原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

p5

def selectionSort(A):
    for i in range(len(A)):
        min_idx = i
        for j in range(i+1, len(A)):
            if A[min_idx] > A[j]:
                min_idx = j
        A[i], A[min_idx] = A[min_idx], A[i]

HeapSort

堆排序是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序每次利用max heap找到最大的元素,将它放在最末并从堆中删除它,然后继续对剩下的堆进行max heap找最大元素,依次重复这个过程完成排序。

p6

def heapify(arr, n, i):
    largest = i
    l = 2 * i + 1     # left = 2*i + 1
    r = 2 * i + 2     # right = 2*i + 2
    if l < n and arr[i] < arr[l]:
        largest = l
    if r < n and arr[largest] < arr[r]:
        largest = r
    if largest != i:
        arr[i],arr[largest] = arr[largest],arr[i]  # 交换
        heapify(arr, n, largest)

def heapSort(arr):
    n = len(arr)
    # Build a maxheap.
    for i in range(n, -1, -1):
        heapify(arr, n, i)
    # 一个个交换元素
    for i in range(n-1, 0, -1):
        arr[i], arr[0] = arr[0], arr[i]   # 交换
        heapify(arr, i, 0)

如果你看不懂这个算法,可以试试这个视频

MergeSort

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。

p7

def merge(arr, l, m, r):
    n1 = m - l + 1
    n2 = r- m
    # 创建临时数组
    L = [0] * (n1)
    R = [0] * (n2)
    # 拷贝数据到临时数组 arrays L[] 和 R[]
    for i in range(0 , n1):
        L[i] = arr[l + i]
    for j in range(0 , n2):
        R[j] = arr[m + 1 + j]
    # 归并临时数组到 arr[l..r]
    i = 0     # 初始化第一个子数组的索引
    j = 0     # 初始化第二个子数组的索引
    k = l     # 初始归并子数组的索引
    while i < n1 and j < n2 :
        if L[i] <= R[j]:
            arr[k] = L[i]
            i += 1
        else:
            arr[k] = R[j]
            j += 1
        k += 1
    # 拷贝 L[] 的保留元素
    while i < n1:
        arr[k] = L[i]
        i += 1
        k += 1

    # 拷贝 R[] 的保留元素
    while j < n2:
        arr[k] = R[j]
        j += 1
        k += 1

def mergeSort(arr,l,r):
    if l < r:
        m = int((l+(r-1))/2)
        mergeSort(arr, l, m)
        mergeSort(arr, m+1, r)
        merge(arr, l, m, r)

复杂度对比

p8

posted @ 2020-07-08 02:16  MrDoghead  阅读(282)  评论(0编辑  收藏  举报