1. 希尔排序
- 希尔排序是一种分组插入排序算法
- 首先取一个整数d1=n/2,将元素分为d1个组,每组相邻两元素之间的距离为d1,在各组内进行直接插入排序;
- 取第二个整数d2=d1/2,重复上述分组排序过程,直到di=1,即所有元素在同一组内进行直接插入排序。
- 希尔排序每趟并不使某些元素有序,而是使整体数据越来越接近有序;最后一趟排序使得所有数据有序。
重点代码:
# 修改插入排序间隙
def insert_sort_gap(li, d): # d=1为正常插入排序
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_gap(li, d)
d = d // 2
希尔排序的时间复杂度讨论比较复杂,并且和选取的gap序列有关。
2. 计数排序
现在有一个列表,已知列表中数的范围都在0到100之间。 设计算法在o(n)时间复杂度内将列表进行排序。
def count_sort(li,max_num=100):
count=[0]*(max_num+1)
for v in li:
count[v]+=1
li.clear()
for i,v in enumerate(count): # 表示i这个数出现了v次
for j in range(v):
li.append(i)
时间复杂度o(n)。不适合包含数过大的情况
3. 桶排序
- 在计数排序中,如果元素的范围比较大(比如1到1亿之间),如何改造算法?
- 桶排序(Bucket Sort):首先将元素分在不同的桶之中,再对每个桶中的元素排序。
- 桶排序的表现取决于数据的分布(适合平均分布)。也就是需要对不同数据排序时采取不同发分桶策略。
- 平均情况时间复杂度:o(n+k)
- 最坏情况时间复杂度:o(n2k)
- 空间复杂度:o(nk)
代码略
4. 基数排序
- 多关键字排序:假如现在有一个员工表,要求按照薪资排序,薪资相同的员工按照年龄排序
- 先按照年龄进行排序,再按照薪资进行稳定的排序
- 对32,13,94,52,17,54,93排序,是否可以看做多关键字排序?
- 正常应该是按照先十位数进行排序,十位数相等再按照个位数进行稳定的排序
- 若基数排序,则先比较个位数,再比较十位数
重点代码:
# i=0 个位;1 十位;2 百位...
def get_digit(num, i):
return num // (10 ** i) % 10
def radix_sort(li):
max_num = max(li)
i = 0
while 10 ** i <= max_num:
buckets = [[] for v in range(10)]
for val in li:
digit = get_digit(val, i)
buckets[digit].append(val)
li.clear()
for bucket in buckets:
for val in bucket:
li.append(val)
i += 1
时间复杂度:o(kn)、空间复杂度:o(k+n),其中k表示数字位数。