python排序算法-计数排序简单实现以及相应的优化

一、什么是计数排序

字面意思理解就是将序列当中的元素出现的个数进行记录,然后再进行排序。

比如说有一组数列,里面有10个数字,这十个数字的范围是在0~8之间,那么如何才能在最短时间内将这个数组排列完成呢?

由于这个数字的取值范围是在0~8,所以先建立一个长度为元素取值最大值+1的一个数组-count_list,下标从0-8,元素的初始值先设置为0


000000000
012345678

这里有这样的一个数组-array_list

   [ 0, 8, 3, 1, 5, 7, 3, 6, 4, 4]

1、首先先遍历整个数列,到第一个元素的时候,遍历到的内容是数字0,那么count_list下标为零的位置所对应的元素值加1

   [ 0, 8, 3, 1, 5, 7, 3, 6, 4, 4]

100000000
012345678

2、那么同理,第二个遍历到的数字是8,那么就在count_list列表当中下标为8的位置元素加1

   [ 0, 8, 3, 1, 5, 7, 3, 6, 4, 4]

100000001
012345678

3、接着往下走,遍历到了3,那么在count_list下标为3的位置元素加1

   [ 0, 8, 3, 1, 5, 7, 3, 6, 4, 4]

100100001
012345678

之后的操作同理即可,元素出现一次,就在对应位置下标的元素值上加1,最后遍历完成的count_list就变成了这个样子

110221111
012345678

那么每个数字出现了多少次包括具体的数字是几,就一目了然了,之后我们所需要做的就是遍历count_list列表,输出下标,下标对应的元素是几就打印这个下标几次,

   [ 0, 1, 3, 3, 4, 4, 5, 6, 7, 8]


二、 原理清楚之后上代码

在这里插入图片描述

# 创建随机列表函数
import random

array_list = []

def input_num():
	'''
	控制产生随机数列表
	:return: array_list
	'''
	global num, start, end
	num = int(input('请输入产生数组的个数:'))
	if num <= 0:raise Exception('请输入大于零的数字')
	start = int(input('请输入起始数字:'))
	end = int(input('请输入结束数字:'))
	if start > end :raise Exception('起始数字一定要小于结束数字')

	for i in range(num):
		n = random.randint(start, end)
		array_list.append(n)

	return array_list

随机的列表创建好之后,开始计数排序

array_list = input_num()
print("生成的随机数组:\n%s"% array_list)

res = []
def count_sort(array_list):
	# 先得到最大元素确定count_list的范围
	max_value = array_list[0]
	for i in range(len(array_list)):
		if array_list[i] > max_value:
			max_value = array_list[i]
	# 创建0-最大元素之间的空列表
	count_list = [0] * (max_value + 1)

	# 遍历生成的随机列表,把出现的元素,作为count_list列表的下标,
	# 其中,对应下标的元素值+1
	for i in array_list:
		count_list[i] += 1
	
	# 做好标记之后按照顺序输出
	# 在count_list当中下标是几就输出几,下标就是在原来列表中的数字
	# count_list当中的元素个数是代表下标重复输出的次数
	for index in range(len(count_list)):  # 获取count_list下标
		for j in range(count_list[index]):  # 利用count_list对应下标里面的值实现多次添加
			res.append(index)  # count_list的index是array_list里面的值
	# 完成时候,将排好的元素打印输出
	return res

count_list_res = count_sort(array_list)
print(count_list_res)

在这里插入图片描述


三、优化思路

以上的内容是最简单的一种处理方法,当我们的数列当中,数字范围不是特别大的时候,我们可以采取上面的方法。
但是会有极端情况,比如这个列表里面的元素值都比较大


[94, 95, 92, 95, 94, 99, 98, 96]
在这里插入图片描述
虽然说是可以完成排序的,但是由于我们创建列表的个数是按照最大值+1来去创建的那么在创建完成之后,我们会发现,在整个列表的前90个空间都是没有被利用而浪费了的,这样的处理方式是不合理的

那么根据这样的一个问题我们可以这么去优化:
我们再创建列表的时候,长度可以参考最大值-最小值+1这样的方式去处理,这样的话我们就不会有那么多的空间被浪费了

那么代码可以做一个简单的修改:

res = []
def count_sort(array_list):

	# 找出最大最小值,确定count_list的列表范围
	max_value = array_list[0]
	min_value = array_list[0]
	
	for i in range(len(array_list)):
		if array_list[i] > max_value:
			max_value = array_list[i]
		if array_list[i] < min_value:
			min_value = array_list[i]

	# 创建实际所用范围的列表空间
	count_list = [0] * (max_value - min_value + 1)
	print("创建实际所用规模的列表:{}".format(count_list))

	# 接下来的思路就是
	# 每一个array_list当中的元素,在count_list当中的下标
	# 是具体元素减去最小值,得出一个差值作为偏移量
	for i in range(len(array_list)):
		count_list[array_list[i] - min_value] +=1
	print("确定count_list:{}".format(count_list))

	# 偏移量解决完之后,按照之前的思路逐一进行打印即可
	for index in range(len(count_list)):  # 遍历count_list
		for i in range(count_list[index]):  # 根据count_list中的值控制添加次数
			res.append(index + min_value)  # 下标就是偏移量,偏移量+最小值还原最终数据

	return res

array_list = [94, 95, 92, 95, 94, 99, 98, 96]
print("原始列表:{}".format(array_list))
count_list_res = count_sort(array_list)
print("计数排序之后的结果:{}".format(count_list_res))

结果如下:
在这里插入图片描述
这样,将根据最大最小值的差值去构造列表的话,就避免了因为元素太大而导致存储空间的大量浪费

但是即便这样处理之后好像已经没什么问题了,但是还是有局限性

一方面,如果在一组数列当中,最大值和最小值的差值很大,那计数排序是不适合的
另一方面,如果数列当中不完全是整数,这应该怎么办,甚至全部都是浮点数这又该怎么办,那我们使用计数排序实际上是用不了的

这种问题,我们应该如何处理,那就需要考虑使用另外一种算法了,下一篇文章详细说明

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值