#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))