线性时间排序算法:计数排序

一、基本原理

计数排序的思想类似于哈希表中的直接定址法,在给定的一组序列中,先找出该序列中的最大值和最小值,从而确定需要开辟多大的辅助空间,每一个数在对应的辅助空间中都有唯一的下标。

  1. 找出序列中最大值和最小值,开辟Max-Min+1的辅助空间
  2. 最小的数对应下标为0的位置,遇到一个数就给对应下标处的值+1,。
  3. 遍历一遍辅助空间,就可以得到有序的一组序列

限制:计数排序假设n个输入元素中的每一个元素都是在0到k区间内的一个整数,只可处理非负数;计数排序的基本思想:对每一个元素x,确定小于x的元素个数,利用这一信息,就可以直接把x放到输出排序数组的正确位置上了。

二、图解排序过程

三、实现代码

import random

def count_sort(li,max_num = 100):
    count = [0 for i in range(max_num+1)]
    for num in li:
        count[num] += 1
    li.clear()
    for i,val in enumerate(count):
        for _ in range(val):
            li.append(i)

li = [random.randint(0, 100) for i in range(100000)]
count_sort(li)
print(len(li))

打印结果

"C:\Program Files\Python35\python.exe" E:/count.py
100000

Process finished with exit code 0

四、性能分析

1、和系统自带的速度比较

import random
import time
import copy
import sys
from collections import deque

def cal_time(func):
    def wrapper(*args, **kwargs):
        t1 = time.time()
        result = func(*args, **kwargs)
        t2 = time.time()
        print("%s running time: %s secs." % (func.__name__, t2 - t1))
        return result

    return wrapper
@cal_time
def count_sort(li,max_num = 100):
    count = [0 for i in range(max_num+1)]
    for num in li:
        count[num] += 1
    li.clear()
    for i, val in enumerate(count):
        for _ in range(val):
            li.append(i)


@cal_time
def sys_sort(li):
    li.sort()


li = [random.randint(0, 100) for i in range(100000)]
li1 = copy.deepcopy(li)
count_sort(li)
sys_sort(len(li))

输出结果

"C:\Program Files\Python35\python.exe" E:/python/test/count.py

count_sort running time: 0.018001079559326172 secs.

Traceback (most recent call last):
  File "E:/工作目录/python/test/count.py", line 35, in <module>
    sys_sort(len(li1))
  File "E:/工作目录/python/test/count.py", line 10, in wrapper
    result = func(*args, **kwargs)
  File "E:/工作目录/python/test/count.py", line 29, in sys_sort
    li.sort()
AttributeError: 'int' object has no attribute 'sort'

Process finished with exit code 1

2、算法分析: 

计数排序是一种以空间换时间的排序算法,并且只适用于待排序列中所有的数较为集中时,比如一组序列中的数据为0 1 2 3 4 999;就得开辟1000个辅助空间。 

3、时间复杂度 

  • 时间复杂度:O(n)O(n)
  • 空间复杂度:O(n)+O(N)O(n)+O(N)
  • 是否稳定:是
  • 优化措施:为了保障稳定性,算法中进行了多余的操作,如果不需要稳定性,可以优化时间。

4、应用场景

计数排序虽然时间复杂度较低,但需要满足的条件较多,如果能满足限制条件与空间需求,计数排序自然很快

1、计数排序的时间度理论为O(n+k),其中k为序列中数的范围。 

2、不过当O(k)>O(n*log(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(n*log(n)), 如归并排序,堆排序)

posted @ 2018-09-25 17:10  活的潇洒80  阅读(354)  评论(0编辑  收藏  举报