计数排序

实际工作中,如果 k=O(n),那么选择计数排序,线性时间。

比如排序数组[1, 102, 103, .... 10*100],n = 100, k=10n=O(n), 那么可以用计数排序,计数排序是稳定的:原数组中相同元素在输出数组中的次序是一样的

#!/usr/bin/env python
# -*- encoding: utf-8 -*-

def countSort(A, k, offset=0):
    """
    A: 待排序数组
    k: 数组A区间-offset后的最大值
    offset: 有时候A在一个区间内[a,b],这时候,可以设置offset为a
    """
    if offset > 0:
        A[:] = [p - offset for p in A]
    B = [0] * len(A)  # 最终输出的排序数组
    C = [0] * k  # 临时存储数组
    for i in range(0, len(A)):
        C[A[i]] += 1  # C[i]现在代表数组A中元素等于i的个数
    for i in range(1, k):
        C[i] += C[i - 1]  # C[i]现在代表数组A中元素小于等于i的个数
    for j in range(len(A) - 1, -1, -1):
        B[C[A[j]] - 1] = A[j]
        C[A[j]] -= 1  # 防止数组 A 有重复的数,在 B 中占据了相同的位置
    A[:] = B[:]
    if offset > 0:
        A[:] = [p + offset for p in A]

if __name__ == '__main__':
    A = [9, 7, 8, 10, 16, 3, 14, 2, 1, 4]
    countSort(A, 20)
    print(A)

    A = [9, 7, 8, 10, 16, 3, 14, 2, 1, 4]
    B = [100 + p for p in A]
    countSort(B, 30, 96)
    print(B)