python开发之算法&数据结构(三)
一、基于桶排序思想
1. 计数排序
计数排序是一个非基于比较的排序算法,他的思想是用下标记录每个元素出现的次数,而下标涵盖了所有元素的范围,最后按照下标顺序,次数是多少就输出多少次下标,输出的即为排序后的结果。
1.1 排序过程
# 计数排序:
def count_sort(li,max_count=100):
count = [0 for _ in range(max_count+1)]
for i in li:
count[i] += 1
li.clear()
for index,val in enumerate(count):
for i in range(val):
li.append(index)
注: 该方法存在一个问:无法保证相同元素之间的相对位置。比如上图数字代表年级,同为3年级的有两个班:3年级文科班和3年级理科班,假如排序前文科班排在理科班前面,按上述方法排序完成后无法保证文科班还在理科班前面,因为两个3都无法表示自己是哪个班的。
1.2 排序优化
在上述方法的基础上,计数器 每个下标对应的数都是前面所有数的和 (计数器下标从1开始),如果计数器下标从0开始,就把下标对应的每个数都减1。接着从要排序的数列的 最后 一个元素开始,在计数器中找对应的下标,例如元素3就找计数器下标3,发现其对应的值为5,则该元素3在排好序的新序列中的位置是下标5的位置,并且计数器下标3对应的数减1;以此类推直到所有元素都放入新列表中,期间一直要保持计数器的更新。
- 采用该方法排序后的结果可以保证相同元素的相对位置不变,也就是说优化计数排序算法是 稳定 的。
- 对于把计数器每个下标对应的数都加上前面所有数,可以理解为小于等于2的元素占据着新列表下标从0到3的位置(如下图);小于等于4的元素占据着新列表下标从0到7的位置。
- 原列表最后一个3,排序完就在新列表下标为5的位置,然后计数器5位置的值-1变为4,原列表倒数第二个3,排序完就在新列表下标为4的位置。
- 还有一种情况是元素范围从 非0或非1 开始,比如20-26,那就把新列表建为(26-20+1)的长度。
1.3 代码实现
计数排序代码关键点:计数器、计数器与新列表的对应关系
代码思路:首先得到原列表最大最小值,确定计数器范围;然后遍历原列表,在计数器中记录每个元素出现的次数;再循环将计数器中每个下标对应的数都加上前面所有数,如果计数器下标从0开始,则还需要把计数器中的每个值都 -1;最后对原列表倒序取值,放到新列表的对应位置。
# 计数排序优化:
def CountingSort(li):
maxNum=max(li) # 获取li中的最大值和最小值
minNum=min(li)
# 以最大值和最小值的差作为计数器的长度,并构建计数器,初始化为0
length=maxNum-minNum+1
countLi=[0 for _ in range(length)]
resultLi