堆
堆通常是一个可以被看做一棵完全二叉树的数组对象
完全二叉树性质之一
如果对一棵有n个结点的完全二叉树的结点按层序编号(从第1层到第 +1层,每层从左到右),则对任一结点i(1<=i<=n),有:
(1)如果i=1,则结点i无双亲,是二叉树的根;如果i>1,则其双亲是结点。
(2)如果2i>n,则结点i为叶子结点,无左孩子;否则,其左孩子是结点2i。
(3)如果2i+1>n,则结点i无右孩子;否则,其右孩子是结点2i+1。
(4)若对二叉树的根结点从0开始编号,则相应的i号结点的双亲结点的编号为(i-1)/2,左孩子的编号为2i+1,右孩子的编号为2i+2。
大顶堆
每个结点的值都大于或等于其左右孩子结点的值
小顶堆
每个结点的值都小于或等于其左右孩子结点的值
对堆加上以上限制,我们可以作出大顶堆:
f
[
i
]
=
F
(
i
)
,
i
∈
[
0
,
l
e
n
)
若
∃
2
∗
i
+
1
<
l
e
n
,
则
f
[
i
]
>
f
[
2
∗
i
+
1
]
若
∃
2
∗
i
+
2
<
l
e
n
,
则
f
[
i
]
>
f
[
2
∗
i
+
2
]
f[i]=F(i), i\in[0,len)\\ 若\exist 2*i+1<len,则f[i]>f[2*i+1]\\ 若\exist2*i+2<len,则f[i]>f[2*i+2]
f[i]=F(i),i∈[0,len)若∃2∗i+1<len,则f[i]>f[2∗i+1]若∃2∗i+2<len,则f[i]>f[2∗i+2]
依据以上性质,我们每次有新数据加入数组,可以从最后一个非叶子节点即
f
[
l
e
n
/
2
−
1
]
f[len/2-1]
f[len/2−1]对数组进行整理,得到大顶堆。
void BuildMaxHeap(int *num, int len){
for(int i = len/2-1; i >= 0; i--){
if(num[i] < num[2*i+1] && 2*i+1 < len){
swap(num[2*i+1],num[i]);
printn(num,len);
if(2*(2*i+1)+1 < len && num[2*i+1] < num[2*(2*i+1)+1] || 2*(2*i+1)+2 < len && num[2*i+1] < num[2*(2*i+1)+2]){
BuildMaxHeap(num,len);
}
}
if(num[i] < num[2*i+2] && 2*i+2 < len){
swap(num[2*i+2],num[i]);
printn(num,len);
if(2*(2*i+2)+2 < len && num[2*i+2] < num[2*(2*i+2)+2] || 2*(2*i+2)+1 < len && num[2*i+2] < num[2*(2*i+2)+1]){
BuildMaxHeap(num,len);
}
}
}
}