defheapify(arr,root,end): whileTrue: child = 2*root+1# 左节点的位置 if child>end: # 左节点在末尾节点之外 break if child+1<=end and arr[child+1]>arr[child]: # 右节点在末尾节点之内,选择左右节点较大者的索引 child+=1 if arr[child]>arr[root]: # 三个节点的最大值放在根节点 arr[child],arr[root] = arr[root],arr[child] root = child # 因为孩子节点的值改变了,所以需要调整该节点往下的堆 else: # 根节点已经是最大值,即已经满足最大堆性质 break
defheap_sort(arr): n = len(arr) first_root = n//2-1# 找到最深最后的那个根节点的位置 for root inrange(first_root,-1,-1): heapify(arr,root,n-1) for end inrange(n-1,0,-1): arr[0],arr[end] = arr[end],arr[0] heapify(arr,0,end-1)
应用
TopK问题(找出前K小的数)
维护一个大小为K的大顶堆,依次将数据放入堆中,当堆满了之后,只需要将堆顶的元素与下一个数比较:
如果大于堆顶元素,则直接忽略,比较下一个元素
如果小于堆顶元素,将该元素与堆顶元素交换,然后重新建立最大堆
重复上面步骤直到全部元素遍历完
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
deftopk(a,k): heap = [] for item in a[:k]: heap.append(item) iflen(heap)<=k: return heap heapify(heap,0,k-1) for item in a[k:]: if item>heap[0]: continue heap[0] = item heapify(heap,0,k-1)