#topk问题的解决思路
#先构造小根堆调整函数
def sift(li,low,high): #li是指列表,low是指根节点位置,high是指最后一个元素位置
i=low #最开始跟节点的位置
j=2*i+1 #左边下一层孩子节点
tmp=li[low] #把堆顶元素存下来
while j<=high: #只要j位置有节点,有数字便可以一直循环
if j+1<high and li[j+1]<li[j]: #右边孩子有并且右边更大
j=j+1 #把j指向j+1,右边孩子大于左边,指向右边
if li[j]<tmp:
li[i]=li[j]
i=j #往下看一层
j=2*j+1
else: #tmp更大的情况,把tmp放上来
li[i]=tmp #把tmp放到某一级领导的位置上
break
else:
li[i]=tmp #把tmp放在叶子节点上去
def topk(li,k):
#1首先取前k个元素构造k长度的列表,并且构造k长度的小根堆
heap=li[0:k]
for i in range((k-2)//2,-1,-1):
sift(heap,i,k-1)
#2遍历列表中其他的元素,形成最终的k数目的小根堆
for i in range(k,len(li)-1):
if li[i]>heap[0]:
heap[0]=li[i]
sift(heap,0,k-1)
#3对于前k的小根堆进行吐数的操作
for i in range(k-1,-1,-1): #i是指当前堆的最后一个元素
heap[0],heap[i]=heap[i],heap[0]
sift(heap,0,i-1) #i-1是新的堆的high
return heap
li=list(range(100))
import random
random.shuffle(li)
print(li)
#li=[0,100,23,3,4,5,6,7,8,12,3,4,56,7,8,9,123,1111,12]
print(topk(li,10))