BST 即 搜索二叉树,它的性质,简而言之,就是对于每一个结点,他的左节点严格小于它,它的右节点严格大于他,满足这样性质的数就是搜索二叉树,它支持求x数的排名(在这里规定,有多个相同的数时,求他的最大排名),求排名x的数,求x数的前驱和后继,加入结点,删除结点
那么,要满足上面的性质,如果有多个相同的数该如何处理呢?我们的处理办法是增加一个变量cnt,记录这样的数出现的次数即可
代码实现如下:
#include<iostream> #include<cstdio> using namespace std; struct node { int ls,rs,cnt,v,size; node(int left,int right,int size,int value) :(ls)left,(rs)right,size(size),v(value),cnt(1){} node(){} }tree[100001]; int num; inline void update(int root) { tree[root].size = tree[tree[root].ls].size+tree[tree[root].rs].size+tree[root].cnt; } void Insert(int x, int root) { if(x==tree[root].v) tree[root].cnt++; return ; else if(x<tree[root].v) { if(tree[root].ls) Insert(x,tree[root].ls); else tree[tree[root].ls = ++num ] = node(0,0,1,x); } else if(x>tree[root].v) { if(tree[root].rs) Insert(x,tree[root].rs); else tree[tree[root].rs = ++num] = node(0,0,1,x) } return ; update(root); } int rank_value(int x, int root) { if(x<=tree[tree[root].ls].size) return rank_value(x,tree[root].ls); else if(x<=tree[tree[root].ls].size+tree[root].cnt) return tree[root].v; else return rank_value(x-tree[tree[root].ls].size-tree[root].cnt,tree[root].rs); }//查询排名x的数 int value_rank(int x, int root) { if(root) { if(tree[root].v<x) return value_rank(x,tree[root].ls) else if(tree[root].v>x) return value_rank(x,tree[root].rs)+tree[root].cnt+tree[tree[root].ls].size; else if(tree[root].v == x) return tree[tree[root].ls].size+tree[root].cnt; }//对于一个不存在的数,也可以查询他在序列中的相对位置 return 1; }//查询数x的排名 int pre(int x, int root, int ans ) { if(x<=tree[root].v) { if(!tree[root].ls) return ans; else return pre(x,tree[root].ls,ans); } if(x>tree[root].v) { if(!tree[root].rs) return ans; else return pre(x,tree[root].rs,tree[root].v) } }//查询数x的前驱 int main() { int n,op,x,root; scanf("%d",&n); tree[root = ++num] = node(0,0,1,2147483647); while(n--) { scanf("%d%d",&op,&x); if(op==1) { cout<<value_rank(x,root)<<endl;//x 的 rank } else if(op==2) { cout<<rank_value(x,root)<<endl;//rank为x的数 } else if(op==3) { cout<<pre(x,root,2147483647)<<endl; } else if(op==4) { cout<<rank_value(value_rank(x+1,root),root)<<endl;//可以替代后继函数 } else Insert(x,root); } return 0; }