希尔排序
- 希尔排序思路
- 希尔排序是一种分组插入排序算法。
- 首先取一个整数d1=n/2,将元素分为d1个组,每组相邻量元素之间距离为d1,在各组内进行直接插入排序;
- 取第二个整数d2=d1/2,重复上述分组排序过程,直到di=1,即所有元素在同一组内进行直接插入排序。
- 希尔排序每趟并不使某些元素有序,而是使整体数据越来越接近有序;最后一趟排序使得所有数据有序。
# 需要将 插入排序的所有的 1 改成 d
# 用到的插入排序
def insert_sort(li, d):
for i in range(d,len(li)):
tmp = li[i]
j = i-d
while j>=0 and li[j]>tmp:
li[j+d] = li[j]
j-=d
li[j+d] = tmp
def shell_sort(li):
d = len(li) // 2
while d > 0:
insert_sort(li,d)
d = d // 2
li = list(range(100000))
random.shuffle(li)
shell_sort(li)
print(li)
计数排序
- 现在有一个列表,已知列表中的数范围都在0到100之间。设计算法在O(n)时间复杂度内将列表进行排序。
- o创建一个列表,用来统计每个数出现的次数。
import random
from cal_time import cal_time
@cal_time
def count_sort(li, max_num=100):
# 生成从 0 到 最大值的列表
count = [0 for _ in range(max_num+1)]
for val in li:
count[val] += 1
li.clear()
for a, b in enumerate(count):
# li.extend([a]*b)
for j in range(b):
li.append(a)
@cal_time
def sys_sort(li):
li.sort()
li = [random.randint(0,100) for _ in range(100000)]
count_sort(li)
桶排序
- 在计数排序中,如果元素的范围比较大(比如在1到1亿之间),如何改造算法?
- 桶排序(Bucket Sort):首先将元素分在不同的桶中,在对每个桶中的元素排序。
- 桶排序的表现取决于数据的分布。也就是需要对不同数据排序时采取不同的分桶策略。
- 平均情况时间复杂度:O(n+k)
- 最坏情况时间复杂度:O(n 2 k)
- 空间复杂度:O(n k)
基数排序
- 多关键字排序:加入现在有一个员工表,要求按照薪资排序,年龄相同的员工按照年龄排序。
- 先按照年龄进行排序,再按照薪资进行稳定的排序。
- 对32,13,94,52,17,54,93排序,是否可以看做多关键字排序?
- 就是按照 位数进行排序 i=0 个位 i=1 十位
- 1,10,100,1000,10000.....
- 时间复杂度: O(kn)
- 空间复杂度: O(k+n) (k 表示数字位数)
import random
from cal_time import cal_time
# 多关键字排序 第一关键字、第二关键字、...
# 排序是稳定的
# li = [
# {'sal':2000, 'age':18},
# {'sal':5000, 'age':30},
# {'sal':6000, 'age':30},
# {'sal':5000, 'age':18},
# {'sal':2000, 'age':30},
# ]
# li.sort(key=lambda x: (x['sal'], x['age']))
# li.sort(key=lambda x:x['age'])
# li.sort(key=lambda x:x['sal'])
# num = 56
# i = 2
# digit = num // 10**i % 10
@cal_time
def radix_sort(li):
max_val = max(li) # 先找出最大值
i = 0 # 每次循环选取的 位数 第一次 个位
while 10 ** i <= max_val: # 循 环条件 位数的 不能大于最大的 值 1000 不能大于 999 没有千位
count = [[] for _ in range(10)] # 创建存储 的列表
for val in li:
dig = val // 10 ** i % 10 # 首次 选出 列表中所有 的个位基数
count[dig].append(val) # 按基数的位置 放入 存储列表中
li.clear() # 清空之前的 列表
# 重新 赋值列表
for l in count:
for val in l:
li.append(val)
i += 1 # 增加基数
#li = list(range(100000))
li = [random.randint(0,999) for _ in range(100000)]
random.shuffle(li)
radix_sort(li)