二叉搜索树(BST)模版

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int MAXN=1024;
  4 struct node{
  5     int val;  // val:该节点储存的数值 
  6     int lch, rch; // lch: 左子树根节点编号,rch:右子树根节点编号
  7     int cnt; //该节点储存的数出现的次数(由于我们这里维护的是可重集)
  8     int sz; //以该节点为根节点的子树的节点数目(即子树大小)
  9 };
 10 node bst[MAXN];
 11 int id=1;
 12 //插入 
 13 void insert(int v, int pos=1)//插入
 14 {
 15     bst[pos].sz++;// 以该节点为根节点的子树大小+1
 16     if(bst[pos].val==0 && bst[pos].lch==0 && bst[pos].rch==0){//空节点 
 17         bst[pos].val=v;
 18         bst[pos].cnt=1;
 19     }
 20     else if(v<bst[pos].val){// 向左搜索
 21         if(bst[pos].lch==0)// 如果应该向左搜,但不存在左节点,则创建一个新节点
 22             bst[pos].lch=++id;
 23         insert(v, bst[pos].lch);
 24     }
 25     else if(v>bst[pos].val){// 向右搜索
 26         if(bst[pos].rch==0)
 27             bst[pos].rch=++id;
 28         insert(v, bst[pos].rch);
 29     }
 30     else//已经存在相同值的点 
 31         bst[pos].cnt++;
 32 } 
 33 //删除
 34 void remove(int v, int pos=1){
 35     bst[pos].sz--;
 36     if(v<bst[pos].val)
 37         remove(v, bst[pos].lch);
 38     else if(v>bst[pos].val)
 39         remove(v, bst[pos].rch);
 40     else
 41         bst[pos].cnt--;
 42 } 
 43 //求排名:因为排名被定义为比某数小的数+1,所以我们直接实现两个函数countl和countg,
 44 //用来求比某数小的数的数量和比某数大的数的数量。(这两个函数后面也会用到)
 45 int countl(int v, int pos=1){// 求比某数小的数的个数
 46     if(v<bst[pos].val)
 47         return bst[pos].lch?countl(v, bst[pos].lch):0;
 48     else if(v>bst[pos].val)
 49         return bst[bst[pos].lch].sz+bst[pos].cnt+bst[pos].rch?countl(v, bst[pos].rch):0;
 50     else
 51         return bst[bst[pos].lch].sz;
 52 }
 53 int countg(int v, int pos=1){// 求比某数大的数的个数
 54     if(v>bst[pos].val)
 55         return bst[pos].rch?countg(v, bst[pos].rch):0;
 56     else if(v<bst[pos].val)
 57         return bst[bst[pos].rch].sz+bst[pos].cnt+bst[pos].lch?countg(v, bst[pos].lch):0;
 58     else
 59         return bst[bst[pos].rch].sz;
 60 }
 61 //查询某值在数列中排名 
 62 int rank(int v){
 63     return countl(v, 1)+1;
 64 }
 65 //求指定排名的数
 66 int kth(int k, int pos=1)// 求指定排名的数
 67 {
 68     if(bst[bst[pos].lch].sz+1>k)// 答案在左,在左子树中找排名为k的数
 69         return kth(k, bst[pos].lch);
 70     else if(bst[bst[pos].lch].sz+bst[pos].cnt<k)// 答案在右,在右子树中找排名为k - size[L[pos]] - N[pos]的数
 71         return kth(k-bst[bst[pos].lch].sz-bst[pos].cnt, bst[pos].rch);
 72     else 
 73         return bst[pos].val;
 74 }
 75 //注意,假如某个数的排名为2,且它出现了3次,那么这个函数传入2、3、4都会返回这个数,这也提供了一些方便。
 76 
 77 
 78 //求前驱:根据我们kth函数的性质,直接找到排名比当前数小1的那个数即可。
 79 int pre(int v){
 80     int r=countl(v);
 81     return kth(r);
 82 }
 83 
 84 //求后继:后继的排名则是小于等于当前数的数的数量+1。
 85 int suc(int v){
 86     int r = bst[1].sz - countg(v) + 1;
 87     return kth(r);
 88 } 
 89 int main()
 90 {
 91     //依次插入  10 6 2 5 1 7 4 2 5 9 5
 92     int n;
 93     cin>>n;
 94     for(int i=0; i<n; i++){
 95         int x;
 96         cin>>x;
 97         insert(x);
 98     }
 99     for(int i=1; i<=id; i++)
100         cout<<i<<":"<<bst[i].val<<" "<<bst[i].lch<<" "<<bst[i].rch<<" "<<bst[i].sz<<" "<<bst[i].cnt<<endl;
101     cout<<rank(6)<<endl; 
102     return 0;
103  } 

 

posted @ 2020-12-22 17:51  TFLSNOI  阅读(181)  评论(0编辑  收藏  举报