解决思路
注:LowB三人组指的是:冒泡、插入、选择
例如:找前五大的数,先取出列表前五个数,建成小根堆,堆顶即堆中最小值。0与1比较,比1小,跳过,下一个7比1大,7把1换掉,做一次向下调整…遍历整个列表之后,堆中的数即前五大的数。
但其实用内置函数heapq即可实现,直接heapq.nlargest(n,li),将li列表中要的前n大参数传入即可返回前n大数的列表。前n小即heapq.nsmallest(n,li),内置函数不了解与向下调整不明白的同学,见算法之堆排序
向下调整
代码实现
def sift(li, low, high): # 向下调整函数
i = low
j = i * 2 + 1
tmp = li[i]
while j <= high:
if j+1 <= high and li[j+1] < li[j]: # 确保有右孩子,左右孩子比较
j = j+1 # 右孩子小于左孩子,指向右孩子
if li[j] < tmp: # 右孩子与堆顶值比较
li[i] = li[j] # 若小于堆顶值,则右子树向上移动
i = j
j = 2 * i + 1
else:
break
li[i] = tmp
def topk(li, k):
heap = li[0:k] # 先切片出列表前k个数
for i in range((k-2)//2,-1,-1): # 建堆
sift(heap,i,k-1)
for i in range(k,len(li)): # 遍历原列表
if li[i] > heap[0]: # 大于小根堆的堆顶则覆盖堆顶
heap[0] = li[i]
sift(heap,0,k-1) # 重新向下调整,使其保持是一个(小根)堆
for i in range(k-1, -1, -1): # 排序输出,小根堆输出从大到小,大根堆输出从小到大
heap[0], heap[i] = heap[i], heap[0]
sift(heap,0,i-1)
return heap
li = [7,2,1,5,6,3,8,9,10]
print(li)
print(topk(li,5))