BST(Binary Search Tree)二叉搜索树

BST(Binary Search Tree)二叉搜索树

blog

是一棵空树或具有以下几种性质(简而言之,就是中序遍历有序)的树

  1. 若左子树不空,则左子树上所有结点的值均小于它的根结点的值
  2. 若右子树不空,则右子树上所有结点的值均大于它的根结点的值
  3. 左、右子树也分别为二叉搜索树
  4. 没有权值相等的结点。

遇到多个相等的数该怎么办呢,显然我们可以多加一个计数器

那么我们的每一个节点都包含以下几个信息:

  1. 当前节点的权值,也就是序列里的数
  2. 左孩子的下标和右孩子的下标,如果没有则为0
  3. 计数器,代表当前的值出现了几遍
  4. 子树大小和自己的大小的和

至于为什么要有4.我们放到后面讲。

节点是这样的:

struct node{
    int val,ls,rs,cnt,siz;
}tree[500010];

其中 val是权值, ls rs 是左/右 孩子的下标, cnt 是当前的权值出现了几次, siz 是子树大小和自己的大小的和。

#include <iostream>
#include <cstdio>
using namespace std;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int N=500005;
const int INF=2147483647;
int n,tree_cnt;
struct TREE{
    int cnt,ls,rs,val,siz;
}t[N];

void insert(int x,int v){
    t[x].siz++;
    if(t[x].val==v){t[x].cnt++;return;}
    if(t[x].val>v){
         if(!t[x].ls){
            tree_cnt++;
            t[tree_cnt].cnt=t[tree_cnt].siz=1;
            t[tree_cnt].val=v;
            t[x].ls=tree_cnt;
        }else {  insert(t[x].ls,v);  }     
    }else{
        if(!t[x].rs){
            tree_cnt++;
            t[tree_cnt].cnt=t[tree_cnt].siz=1;
            t[tree_cnt].val=v;
            t[x].rs=tree_cnt;
        }else { insert(t[x].rs,v); }
    }
}

int get_pre(int x,int v,int ans){//ans 是目前找到的比 val小的数的最大值
    if(t[x].val>=v){
        if(t[x].ls==0) return ans;
        else return get_pre(t[x].ls,v,ans);
    }else{
        if(t[x].rs==0) return t[x].val<v?t[x].val:ans;
        if(t[x].cnt) return get_pre(t[x].rs,v,t[x].val);//更新ans
        else return get_pre(t[x].rs,v,ans);
    }
}

int get_nxt(int x,int v,int ans){
    if(t[x].val<=v){
        if(t[x].rs==0) return ans;
        else return get_nxt(t[x].rs,v,ans);
    }else{
        if(t[x].ls==0) return t[x].val>v?t[x].val:ans;
        if(t[x].cnt) return get_nxt(t[x].ls,v,t[x].val);//更新ans
        else return get_nxt(t[x].ls,v,ans);
    }
}

int get_rk(int x,int v){
    if(x==0) return 0;
    if(v==t[x].val) return t[t[x].ls].siz+1;
    if(v<t[x].val) return get_rk(t[x].ls,v);
    return get_rk(t[x].rs,v)+t[t[x].ls].siz+t[x].cnt;
}

int get_val(int x,int rk){
    if(x==0) return INF;
    if(t[t[x].ls].siz>=rk) return get_val(t[x].ls,rk);
    if(t[t[x].ls].siz+t[x].cnt>=rk) return t[x].val;
    return get_val(t[x].rs,rk-t[t[x].ls].siz-t[x].cnt);
}
int main(){
    n=read();
    int opt,x;
    while(n--){
        opt=read();x=read();
        if(opt==1) printf("%d\n",get_rk(1,x)+1);
        else if(opt==2) printf("%d\n",get_val(1,x));
        else if(opt==3) printf("%d\n",get_pre(1,x,-INF));
        else if(opt==4) printf("%d\n",get_nxt(1,x,INF));
        else{
            if(!tree_cnt){
                tree_cnt++;
                t[tree_cnt].cnt=t[tree_cnt].siz=1;
                t[tree_cnt].val=x;
            }
            else insert(1,x);
        }
    }
    return 0;
}

posted @ 2020-08-14 00:28  ke_xin  阅读(30)  评论(0编辑  收藏  举报