【学习笔记】堆

堆的简介

堆是一个完全二叉树,它能同时支持删除、插入、查询,因此,堆是一种神奇的数据结构。

堆的性质

堆的每个父亲节点都大于等于它的儿子节点/堆的每个父亲节点都小于等于它的儿子节点。

堆的操作

堆的操作有五种:下移(down)、上移(up)、插入(insert)、删除(delete)、建堆(build)。

下移(down)

假设我们需要一个小根堆,就是每个父亲节点都小于等于它的儿子节点这样的一个堆。每次父亲节点就要跟两个儿子(2x和2x+1)节点中较小的比较,如果比他大,则交换。

 1 procedure down(x:longint);
 2 var
 3         y,t:longint;
 4 begin
 5         while (a[x]>a[x*2]) and (x*2<=num) or (x*2+1<=num) and (a[x]>=a[x*2+1]) do//num是堆里元素的个数
 6         begin
 7                 y:=x*2;
 8                 if (a[y]>a[y+1]) and (y+1<=num) then inc(y);
 9                 t:=a[x];
10                 a[x]:=a[y];
11                 a[y]:=t;
12                 x:=y;
13         end;
14 end;
上移(up)

我们仍然假设需要一个小根堆,每次儿子节点节点就要跟父亲节点(x/2)比较,如果比他小,则交换

 1 procedure up(x:longint);
 2 var
 3         t:longint;
 4 begin
 5         while (a[x]<a[x div 2]) and (x>1) do
 6         begin
 7                 t:=a[x];
 8                 a[x]:=a[x div 2];
 9                 a[x div 2]:=t;
10                 x:=x div 2;
11         end;
12 end;
删除(delete)

每次删除都是删除堆顶,删除后,由于现在没有堆顶,所以我们把堆末尾的数放上去,再down下来。

1 procedure delete;//删除堆顶
2 begin
3     h[1]:=h[num];
4     dec(num);
5     down(1);
6 end;
插入(insert)

插入也很简单,就是把它放到堆的末尾,然后up一下就好了。

1 procedure insert(x:longint);//插入x
2 begin
3     inc(num);
4     a[num]:=x;
5     up(num);
6 end;
最后就是建堆了(build)

建堆也不难,有两种方法:

方法一:
1 for i:=1 to n do 
2     insert(a[i]);

时间复杂度O(nlog2n);

方法二:
1 for i:=n div 2 downto1 do 
2     down(i);

时间复杂度O(n)。 

扫描二维码关注公众号,回复: 8729385 查看本文章

例题:

合并果子

堆排序

……

猜你喜欢

转载自www.cnblogs.com/LeeCongWei/p/12217435.html