二叉堆的实现

篇首:

二叉堆是非常非常简单的数据结构,是入门级别的基础,但是我知道算法思想,没有去实践过(一般用到堆时直接STL的priority_queue),最近在刷刷基础且李总让我们总结算法,于是心血来潮手打一波二叉堆。(重要的事情说三遍:priority_queue是大根堆性质、priority_queue是大根堆性质、priority_queue是大根堆性质

理解:

二叉堆首先是一颗二叉树,然后满足堆的性质。若子节点小于等于父节点,则称该二叉树为大根堆,同理若子节点大于等于父节点,则称该二叉树为小根堆。

二叉堆操作的实现(以大根堆为例):

插入:

直接将需要插入的数x放在heap末尾,然后向上调整,直到满足大根堆性质结束。

求max值:

由于维护的是大根堆,所以直接返回堆首heap[1]

删去堆首:

直接将堆首与heap末尾节点交换,并使节点个数减1,然后由新的根节点不断向下调整,直到满足大根堆性质为止(注意每次调整应该和左右儿子中的较大值交换,显然so不解释)。

删去某个下标的值:

方法类似于删去堆首,将所需删除下标x的heap[x]与末尾节点交换,节点个数减1,然后要么向上调整要么向下调整(显然so不解释)

完整代码:

 1 #include<bits/stdc++.h>
 2 #define il inline
 3 #define ll long long
 4 #define debug printf("%d %s
",__LINE__,__FUNCTION__)
 5 using namespace std;
 6 const int N=500005;
 7 int n,x,heap[N],cnt;
 8 il int gi()
 9 {
10     int a=0;char x=getchar();bool f=0;
11     while((x<'0'||x>'9')&&x!='-')x=getchar();
12     if(x=='-')x=getchar(),f=1;
13     while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
14     return f?-a:a;
15 }
16 il void up(int x)   //上调
17 {
18     while(x>1){
19         if(heap[x]>heap[x>>1]){swap(heap[x],heap[x>>1]);x>>=1;}
20         else break;
21     }
22 }
23 il void insert(int x){heap[++cnt]=x;up(cnt);}  //插入
24 
25 il int gettop(){return cnt?heap[1]:-1;}   //取出堆顶,即最大值
26 
27 il void down(int x)
28 {
29     int s=x<<1;   //x左儿子
30     while(s<=cnt){
31         if(s<cnt&&heap[s]<heap[s+1])s++;   //取左右儿子的较大值
32         if(heap[s]>heap[x]){swap(heap[s],heap[x]);x=s,s=x<<1;}  //维护大根堆父节点大于子节点的性质
33     }
34 }
35 il void extrat(){heap[1]=heap[cnt--];down(1);} //删除堆顶
36 
37 il void remove(int x){heap[x]=heap[cnt--];up(x),down(x);}   //删除下标位置为x的节点
38 int main()
39 {
40     n=gi();
41     while(n--){
42         int a=gi();
43         if(a==1)x=gi(),insert(x);
44         if(a==2)printf("%d
",gettop());
45         if(a==3)extrat();
46         if(a==4)x=gi(),remove(x);
47     }
48     return 0;
49 }
原文地址:https://www.cnblogs.com/five20/p/8536684.html