比较

各类排序算法复杂度

排序算法 平均复杂度 最优复杂度 最大复杂度 额外空间 稳定性
冒泡排序 O(n^2) O(n) O(n^2) O(1) 稳定
选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定
插入排序 O(n^2) O(n) O(n^2) O(1) 稳定
shell排序 O(n^1.3) O(n^2) O(n^2) O(1) 不稳定
快速排序 O(n^2) O(nlogn) O(n^2) O(1) 不稳定
归并排序 O(nlogn) O(nlogn) O(nlogn) O(n) 稳定

排序时间比较表:(单位:秒)

数组规模大小 10 100 1000 10000 1000有序 10000有序
冒泡排序 0 0.002 0.24 14.53 0 0.001
选择排序 0 0.002 0.115 4.949 0.097 7.765
插入排序 0 0.003 0.361 23.202 0.356 24.778
Shell排序 0 0.001 0.011 0.039 0.006 0.045
快速排序 0 0.001 0.116
归并排序 0 0.001 0.006 0.037 0.008 0.036

几点说明:

  • 上表中空的位置,是因为Python快速排序递归超过了递归深度,所以报错没输出了
  • 关于冒泡排序和选择排序

    • 它们的时间复杂度都为 O(n^2),那么为什么排序时间差别这么大呢?因为虽然它们排序的比较次数一致,但它们的交换次数不一样。对于冒泡排序,最优交换次数为0,只需要比较n次;对于选择排序,最优交换次数为n次,需要比较 n^2 次。
    • 在大规模无序数据排序情况下,选择排序比冒泡排序快,选择排序只需交换n次,冒泡排序可能要交换n^2次。
    • 在有序数据排序情况下,冒泡排序比选择排序快,冒泡排序只需比较n次,选择排序需要比较 n^2次。
  • 快速排序和归并排序效率最好。

附Python代码:

import time,random
N = 1000
# ls = [random.randint(1,N) for _ in range(N)]
ls = [i for i in range(N)]

def log_time(ls):
    def wrapper(func):
        start = time.time()
        func(ls)
        end = time.time()
        print('{}排序函数运行了 {} s!'.format(func.__name__,end-start))
    return wrapper

@log_time(ls)
def bubble_sort(ls):
    length = len(ls)
    for i in range(length-1,0,-1):
        count = 0
        for j in range(i):
            if ls[j]>ls[j+1]:
                ls[j],ls[j+1]=ls[j],ls[j+1]
                count += 1
        if count == 0: return ls
    return ls

@log_time(ls)
def select_sort(ls):
    length = len(ls)
    for i in range(length):
        min_index = i
        for j in range(i+1,length):
            if ls[j]<ls[min_index]:
                min_index = j
        ls[i],ls[min_index]=ls[min_index],ls[i]
    return ls

@log_time(ls)
def insert_sort(ls):
    length = len(ls)
    for i in range(1,length):
        for j in range(i,-1,-1):
            if ls[j]>ls[j-1]:
                ls[j],ls[j-1]=ls[j-1],ls[j]
            else:
                break
    return ls

@log_time(ls)
def shell_sort(alist):
    n = len(alist)
    # 初始步长
    gap = n // 2
    while gap > 0:
        # 按步长进行插入排序
        for i in range(gap, n):
            j = i
            # 插入排序
            while j>=gap and alist[j-gap] > alist[j]:
                alist[j-gap], alist[j] = alist[j], alist[j-gap]
                j -= gap
        # 得到新的步长
        gap = gap // 2
    return alist

# @log_time(ls)
def quick_sort(ls):
    def q_sort(ls,left,right):
        if left >= right:
            return
        i,j = left,right
        pivot = ls[left]
        while i<j:
            while ls[j] > pivot and i<j:
                j -= 1
            ls[i] = ls[j]
            while ls[i] <= pivot and i<j:
                i += 1
            ls[j] = ls[i]
        ls[i] = pivot
        q_sort(ls,left,i-1)
        q_sort(ls,i+1,right)
        return ls
    return q_sort(ls,0,len(ls)-1)

@log_time(ls)
def merge_test(ls):
    def merge_sort(ls):
        if len(ls) <= 1:
            return ls
        mid = len(ls)//2
        # 序列左边部分
        left = merge_sort(ls[:mid])
        # 序列右边部分
        right = merge_sort(ls[mid:])
        return merge(left,right)

    def merge(left,right):
        ## left部分的指针 l right部分的指针 r
        l,r = 0,0
        res = []
        while l < len(left) and r < len(right):
            if left[l] < right[r]:
                res.append(left[l])
                l += 1
            else:
                res.append(right[r])
                r += 1
        res += left[l:]
        res += right[r:]
        return res
    return merge_sort(ls)