堆
堆?
堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。
——选自“百度百科”
堆的特性?
- 堆中某个节点的值总是不大于(大根堆)或不小于(小根堆)其父节点的值;
- 堆总是一棵完全二叉树。
堆的作用?
- 堆支持插入、删除、查找最大(小)值的操作。
堆的操作?
终于到了堆的操作了。
堆有5种操作,上移(
u
p
up
up)、下移(
d
o
w
n
down
down)、插入(
i
n
s
e
r
t
insert
insert)、删除(
d
e
l
e
t
e
delete
delete)、建堆。
规定:
h数组表示堆里面的值
swap函数表示把堆两个元素交换
num表示堆中元素个数
上移( u p up up)
上移操作:当我们插入进来的数(一般是最后一个数)使得堆不符合特性时,我们就每次把它与它的父亲比较,然后上移;
//我们以小根堆为例:
void up(int x){//把x这个位置上移
while (x>0&&h[x]<h[x/2]){
swap(x,x/2);//交换
x/=2;//very important!
}
return;
}
下移( d o w n down down)
下移操作:当我们的堆不符合特性(一般是堆顶)时,我们就每次把它与它的儿子比较,然后下移;
//我们以小根堆为例:
void down(int x){//把x这个位置下移
while (x*2<=num&&h[x]>h[x/2]||x*2+1<=num&&h[x]>=h[x*2+1]){
int y=x*2;
if (y+1<=num&&h[y]>h[y+1]) y++;//尽量选小的换
swap(x,y);//交换
x=y;//very important!
}
return;
}
插入( i n s e r t insert insert)
插入操作:很多时候我们需要插入元素进堆里面,于是乎,我们就num++并把它插入到堆的最后一个位置;
void insert(int x){//插入x
h[++num]=x;
up(num);
return
}
删除( d e l e t e delete delete)
删除操作:很多时候我们需要删除堆里面的最大(小)值,于是乎,我们就先把堆顶弹出。
很多人就问了:弹出后不久没堆顶了吗?
不着急“孩子,慢慢来”。
这时我们就采取将最后一个元素放到堆顶,然后下移(自己感性理解一下)。
void del(int x){//删除x
h[1]=h[num--];
down(1);
return
}
建堆
讲了那么久,终于到了建堆时刻了!
对于建堆,我们有两种方法:
方法一:
for (int i=1;i<=n;i++){
scanf("%d",&x);
insert(x);
}
时间复杂度:
O
(
n
l
o
g
2
n
)
O(nlog_2n)
O(nlog2n)(很显然吧)
方法二
for (int i=1;i<=n;i++){
scanf("%d",&h[i]);
}
for (int i=n/2;i>0;i--)
down(i);
时间复杂度: O ( n ) O(n) O(n),感兴趣的可以自己去证明一下,嘿嘿;
总结
这篇文章就这么结束了,感谢大家的支持!下一篇我将讲关与堆的一些例题,让大家多了解堆。
我可能是为数不多的手打堆的人了,很多人都在用优先队列(感兴趣的可以自己学一下),可能是因为当年我是P党所以我才手打堆吧 !
如果这篇文章有问题,欢迎大家踊跃“投稿”!
哦,别忘了我的blog
下一章,堆(二)堆的应用