堆
堆的简介
堆是一个完全二叉树,它能同时支持删除、插入、查询,因此,堆是一种神奇的数据结构。
堆的性质
堆的每个父亲节点都大于等于它的儿子节点/堆的每个父亲节点都小于等于它的儿子节点。
堆的操作
堆的操作有五种:下移(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 查看本文章
例题:
合并果子
堆排序
……