最小堆特点:
- 类似一颗完全二叉树
- 二叉树中所有的父节点的值都小于其子节点;
- 根节点的值必定是所有节点中最小的。
父节点值不大于子节点且根节点值最小称为最小堆,反之称为最大堆。最大堆和最小堆没有本质上的区别。如下图是一个典型的最小堆:
方法一:
从根节点(index = 0)遍历到最后一个拥有子节点的节点(index = N//2 -1),将父节点与其子节点值作比较,必要时进行交换即可。完成一次上述过程后就能完成最底层节点的归位了。元素个数为N的二叉树层数为ceil(log2n),因此一共执行floor(log2n)次上述过程就能实现最小堆的建堆了。
如下例:
import math
def heap(li):
n=len(li)
for i in range(0,int(math.log(n,2))):
for j in range(0,n//2):
if 2*j+2<n and li[2*j+2]<li[2*j+1]:
k=2*j+2
else:
k=2*j+1
if li[k]<li[j]:
li[k],li[j]=li[j],li[k]
d
if __name__ == '__main__':
li=[1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
heap(li)
print(li)
结果:[-4, 2, 1, 23, 7, 2, 18, 23, 42, 37, 8]
方法2:
思路还是一样,这次从最后一个拥有子节点的节点向上遍历
import math
def heap2(li,root):
if 2*root+1<len(li):
if 2*root+2<len(li) and li[2*root+2]<li[2*root+1]:
k=2*root+2
else:
k=2*root+1
if li[k]<li[root]:
li[k],li[root]=li[root],li[k]
heap2(li,k)
if __name__ == '__main__':
for i in range(len(li)//2-1,-1,-1):
heap2(li,i)
print(li)
结果:[-4, 2, 1, 23, 7, 2, 18, 23, 42, 37, 8]