python数据结构与算法基础 第五课
tags:
- python
- 路飞学院
categories:
- python
- 排序算法
- 希尔排序
- 计数排序
- 桶排序
- 基数排序
文章目录
第一节 希尔排序
1. 希尔排序介绍
- 希尔排序是之前插入排序的变形。
- 希尔排序(Shell Sort)是-种分组插入排序算法。
- 首先取一个整数d-=n/2, 将元素分为d个组,每组相邻量元素之间距离为d,在各组内进行直接插入排序;
- 取第二个整数d2=d/2,重复上述分组排序过程,直到d=1,即所有元素在同- -组内进行直接插入排序。
- 希尔排序每趟并不使某些元素有序,而是使整体数据越来越接近有序;最后一趟排序使得所有数据有序。
# 希尔排序,只需要把插入排序拿过来。把出现的1 变为gap即可
def insert_sort_gap(li, gap):
for i in range(gap, len(li)): # i表示摸到的牌
temp = li[i]
j = i - gap # j表示有序区的最后一张牌(手里的牌)
while j >= 0 and li[j] > temp:
li[j + gap] = li[j]
j -= gap
li[j + gap] = temp
def shell_sort(li):
d = len(li) // 2
while d >= 1:
insert_sort_gap(li, d)
d //= 2
import random
list = random.sample([i for i in range(1000)], 20)
print(list)
shell_sort(list)
print(list)
2. 希尔排序总结
- 希尔排序比插入排序表现好很多(实验证明)
- 希尔排序表现比堆排序稍微慢一些(实验证明)
- 希尔排序的时间复杂度讨论比较复杂,并且和选取的gap序列有关。
- 自己查一下 维基百科。时间复杂度太多了
- 希尔排序平均情况下小于nn.现在得出最快的nlogn*logn
第二节 计数排序
1. 计数排序
- 对列表进行排序,已知列表中的数范围都在0到100之间。设计一个时间复杂度为O(n)的算法。
2. 系统自带的排序算法:比我们之前学过的都快。因为底层是C语言写的
# 计数排序 已知需要排序的列表元素范围在0-100之间
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 ind, val in enumerate(count):
for i in range(val):
li.append(ind)
import random
list = [random.randint(0,100) for i in range(1000)]
print(list)
count_sort(list)
print(list)
第三节 桶排序
1. 桶排序
- 在计数排序中,如果元素的范围比较大(比如在1倒亿之间),如何改造算法?
- 桶排序(Bucket Sort):首先将元素分在不同的桶中,在对每个桶中的元素排序。
- 然后在出数

# 桶排序
def bucket_sort(li, n=100, max_num=10000):
# 创建桶列表, 桶也是一个列表。所以应该是一个二维列表
buckets = [[] for _ in range(n)]
for val in li:
# 0-99 ->0, 100-199->1
# 10000->100 我们这只有0-99号桶。所以把10000放到99号桶
i = min(val // (max_num // n), n-1) # 放到i号桶中
buckets[i].append(val)
# 插入后先桶内排序
for j in range(len(buckets[i])-1, 0, -1):
# 桶内冒泡排序
if buckets[i][j] < buckets[i][j-1]:
buckets[i][j], buckets[i][j-1] = buckets[i][j-1], buckets[i][j]
else:
break
# 输出所有桶内元素
sorted_li = []
for buc in buckets:
sorted_li.extend(buc)
return sorted_li
import random
list = [random.randint(0, 10000) for i in range(100)]
print(list)
li = bucket_sort(list)
print(li)
2. 桶排序的总结
- 桶排序的表现取决于数据的分布。也就是需要对不同数据排序时采取不同的分桶策略。
- 平均情况时间复杂度: O(n+k)
- 最坏情况时间复杂度: O(n^2*k)
- 空间复杂度: O(nk)
第四节 基数排序
1. 基数排序
- 多关键字排序:加入现在有一个员工表,要求按照薪资排序,年龄相同的员工按照年龄排序。
- 先按照年龄进行排序,再按照薪资进行稳定的排序。
- 对32,13,94,52,17,54,93排序, 是否可以看做多关键字排序? 先对个位排序,在对十位排序
- 装多次桶,然后出数。桶排序是装一次桶后,排序输出。
# 基数排序算法
def radix_sort(li):
# 循环次数即位数由最大值确定。
max_num = max(li)
it = 0
while 10 ** it <= max_num:
# 桶数确定的10个
buckets = [[] for _ in range(10)]
# 根据位数。个位十位百位..放入桶中
for val in li:
# 987 it=1 987//10->98 98%10->8; it=2 987//100->9 9%10=9
digit = (val // (10 ** it)) % 10
buckets[digit].append(val)
# 分桶完成
li.clear()
for buc in buckets:
# 重新写回li
li.extend(buc)
it += 1
import random
list = [random.randint(0, 1000) for i in range(20)]
print(list)
radix_sort(list)
print(li)
2. 基数排序的总结
- 时间复杂度: O(kn)
- 空间复杂度: 0(k+n)
- k表示数字位数
- 有可能快排要快的(和数的范围有关)
14万+

被折叠的 条评论
为什么被折叠?



