计数排序
计数排序不是一个比较排序算法,通过计数将时间复杂度降到了O(n)。
算法步骤
第一步:找出原数组中元素值最大的,记为max。
第二步:创建一个新数组count,其长度是max加1,其元素默认值都为0。
第三步:遍历原数组中的元素,以原数组中的元素作为count数组的索引,以原数组中的元素出现次数作为count数组的元素值。
第四步:创建结果数组result,起始索引index。
第五步:遍历count数组,找出其中元素值大于0的元素,将其对应的索引作为元素值填充到result数组中去,每处理一次,count中的该元素值减1,直到该元素值不大于0,依次处理count中剩下的元素。
第六步:返回结果数组result。
算法代码
def count_sort(li, max_count = 100):
count = [0 for _ in range(max_count + 1)]
for val in li:
count[val] += 1
li.clear()
for index, val in enumerate(count):
for i in range(val):
li.append(index)
算法分析
基础版能够解决一般的情况,但是它有一个缺陷,那就是存在空间浪费的问题。
比如一组数据{101,109,108,102,110,107,103},其中最大值为110,按照基础版的思路,我们需要创建一个长度为111的计数数组,但是我们可以发现,它前面的[0,100]的空间完全浪费了,那怎样优化呢?
将数组长度定为max-min+1,即不仅要找出最大值,还要找出最小值,根据两者的差来确定计数数组的长度。
进阶版步骤
以数组A = {101,109,107,103,108,102,103,110,107,103}为例。
第一步:找出数组中的最大值max、最小值min。
第二步:创建一个新数组count,其长度是max-min加1,其元素默认值都为0。
第三步:遍历原数组中的元素,以原数组中的元素作为count数组的索引,以原数组中的元素出现次数作为count数组的元素值。
改进算法代码
def count_sort_min_max(li):
min_num = min(li)
max_num = max(li)
count = [0 for _ in range(max_num - min_num + 1)]
for val in li:
count[val - min_num] += 1
li.clear()
for index, val in enumerate(count):
for i in range(val):
li.append(index + min_num)
以上就是计数排序算法的全部内容了,虽然它可以将排序算法的时间复杂度降低到O(N),但是有两个前提需要满足:一是需要排序的元素必须是整数,二是排序元素的取值要在一定范围内,并且比较集中。只有这两个条件都满足,才能最大程度发挥计数排序的优势。