桶排序
思路:
- 设置一定数量的数组当作空桶;
- 遍历输入数据,并且把数据一个一个放到对应的桶里去;
- 对每个不是空的桶进行排序,内部可使用各种排序方法;
- 从不是空的桶里把排好序的数据拼接起来
代码:
# 桶排序
def bucket_sort(num:list[int], bucket_size:int=5) -> list[int]:
max_val, min_val = max(num), min(num)
# 数据分为 bucketCount 组,这一个是根据每组的数量决定的
bucket_count = (max_val - min_val) // bucket_size + 1
buckets = [[] for _ in range(bucket_count)] # 二维桶
# 利用函数映射将各个数据放入对应的桶中
for i in num:
buckets[(i - min_val) // bucket_size].append(i)
# 清空 num
num.clear()
# 对每一个二维桶中的元素进行排序
for bucket in buckets:
#print(bucket)
insertion_sort(bucket) # 假设使用插入排序
num.extend(bucket) # 将排序好的桶依次放入到 num 中
return num
# 插入排序
def insertion_sort(num: list[int]) -> None:
length = len(num)
for i in range(1, length):
for j in range(i, 0, -1):
if num[j] < num[j-1]:
num[j], num[j-1] = num[j-1], num[j]
else:
break
总结:把待排序的数据划分成几个子序列,然后再根据某种关系映射,再待排序的数据放入子序列中,然后再根据某种排序方法将子序列的数据进行排序,最后将子序列的数据合并就可以得到排序后的序列,而且排序数据尽量服从均匀分布,可提高桶排序的效率
基数排序
思路:
- 取得数组中的最大数,并取得位数;
- 从最低位开始取每个位的数据,组成基数数组;
- 将基数组数据填充到原数组;
- 反复第2,3步, 第2部每轮向前取一位数,反复取到最高位结束
代码:
# 基数排序 未实现排负数
def radis_sort(num: list[int]) -> None:
#获取最多需要被排序几次
times = len(str(max(num)))
for i in range(times):
#分配
bucket=[[] for _ in range(10)]
for j in num:
weishu = j // (10**i) % 10 # 从个位开始取数据
bucket[weishu].append(j)
#收集
num.clear()
for i in range(10):
num += bucket[i]
总结:就是将数据根据相同位数排序好,最后形成一个排序完成的序列,不过这个写法无法排序负数,望有朋友能够提供改进思路
堆排序
思路:
- 建堆(明白堆是什么)
- 找到堆中最大的元素(从小到大排序)
- 移出最大的元素
- 将最后一个元素赋值给顶元素
- 移走完堆顶元素后,再维护堆结构即可
- 反复2到最后过程
代码:
# 堆排序
def down(heap:list[int], index:int, size:int):
'''
维护堆的特性
'''
# 建立一个变量,来存储最大值的索引
max_index = index
# 获取左节点的索引
left = max_index * 2 + 1
# 获取右节点的索引
right = max_index * 2 + 2
# 进行比较获取出最大值索引来
if left < size and heap[max_index] < heap[left]:
max_index = left
if right < size and heap[max_index] < heap[right]:
max_index = right
# 如果max_index 和 index 值不一样,说明需要进行交换
if max_index != index:
heap[max_index], heap[index] = heap[index], heap[max_index]
down(heap, max_index, size)
def heap_sort(heap: list[int]):
# 获取堆有多少数据
size = len(heap)
# 打印原始数据
# print(heap)
# 建堆
for i in range(size//2, -1, -1): # 为了保证一次性取到最大值,所以让索引倒取
down(heap, i, size)
# 打印维护后数据
# print(heap)
# 排序
for i in range(size-1,0,-1):
# 将最大值和未排序的最一个索引进行交换
heap[i],heap[0] = heap[0],heap[i]
# 维护堆的特性
down(heap, 0, i)
# 打印排序好的数据
# print(heap)
总结:就是要明白什么是堆,堆又可分为最小堆和最大堆,最后只要不断的根节点取出,在维护好堆的特性就可得到一个排序好的序列,不明白什么是堆可以参考一分钟带你读懂什么是堆? - 知乎 (zhihu.com)