使用python实现计数排序,计数排序和之前我们说过的插入排序,选择排序等都不一样,它是非比较类的排序。前面我们所讲的排序都是两两比较之后交换位置。
计数排序主要的思想:假设我们有n个整数,范围是 [ x , y ] [x,y] [x,y],现在我们要对其进行排序。首先我们设置 ( y − x + 1 ) (y-x+1) (y−x+1)个位置的列表,其中每一个位置都对应于一个数。在我们遍历了一次待排序的数列之后,我们也就将所有的数都放在了相应的位置里。接下来我们就只要把他们合并到一起就可以了。
算法举例
我们要对【1,3,1,2,6,9,8,0】排序,发现数组的范围是
[
0
,
9
]
[0,9]
[0,9],所以我们设置10个位置。
设计10个位置:【0,0,0,0,0,0,0,0,0,0】
位置所表示数:【0,1,2,3,4,5,6,7,8,9】
遍历一次结果:【1,2,1,1,0,0,1,0,1,1】
之后就是合并的过程,将【0】,【1,1】,【2】,【3】,【6】,【8】,【9】合并,所得即是结果【0,1,1,2,3,6,8,9】。
算法分析
首先想明确的是计数排序是可以操作负整数的。但是没有办法操作小数。
还有一点想说的是,我们在设置位置的时候一定要先获得最大值和最小值。很多教程都是只获得最大值,然后默认从0开始设置。这样的话,第一是不能操作负数,第二也会浪费很多空间,比如我有10000个数排序,但是它的范围就在8,9之间,这样前面的位置就都失去了意义。
计数排序由于不需要比较,其算法的时间复杂度是 O ( n ) O(n) O(n)。但是确实需要很多额外的空间来操作。
方法 | 平均时间复杂度 | 最坏时间复杂度 | 最好时间复杂度 | 空间复杂度 |
---|---|---|---|---|
计数排序 | O ( n + k ) O(n+k) O(n+k) | O ( n + k ) O(n+k) O(n+k) | O ( n + k ) O(n+k) O(n+k) | O ( n + k ) O(n+k) O(n+k) |
最后计数排序是一个稳定的排序方法。
python实现
########################################################
##### 计数排序 #####
########################################################
def jishu(nums, order=1):
max_num = max(nums)
min_num = min(nums)
extra = [0] * (max_num - min_num + 1)
for n in nums:
extra[n - min_num] = extra[n - min_num] + 1
result = []
for i in range(len(extra)):
if extra[i] != 0:
result = result + ([min_num + i] * extra[i])
if order == 1:
return result
else:
return result[::-1]
test = [-2, 4, 6, 9, 0, 76, 21, 87, 65, 43, 32]
print(jishu(test))
print(jishu(test,0))
"""
[-2, 0, 4, 6, 9, 21, 32, 43, 65, 76, 87]
[87, 76, 65, 43, 32, 21, 9, 6, 4, 0, -2]
"""