二叉查找树,对于任意一个节点,该节点的关键码大于它的左子树中任意节点的关键码,该节点的关键码小于它的右子树中任意节点的关键码,且没有键值相等的点
二叉查找树的中序遍历是一个关键码单调递增的节点序列
数组及变量
\(fa[i]:\) 节点\(i\)的父节点
\(son[i][0]:\) 节点\(i\)的左儿子
\(son[i][1]:\) 节点\(i\)的右儿子
\(key[i]:\) 节点\(i\)的关键字
\(siz[i]:\) 以节点\(i\)为根的子树元素个数
\(cnt[i]:\) 节点\(i\)所表示的元素的出现次数
\(tot:\) 共有多少元素
\(root:\) 树的根
函数
\(check:\) 判断节点\(x\)是它父亲的左儿子还是右儿子
\(pushup:\) 更新节点\(x\)的\(siz\)
\(rotate:\) 将是左儿子的右旋,是右儿子的左旋

\(splay :\) 进行伸展,不断\(rotate\)直到达到目标状态
\(insert:\) 插入一个值
\(find:\) 查找\(x\)的位置,并将其旋转到根节点
\(rnk:\) 查询\(x\)的排名
\(val:\) 查询排名为\(x\)的数
\(get:\) \(k=0\)时,求\(x\)的前驱,\(k=1\)时,求\(x\)的后继
\(del:\) 删除为\(x\)的数
\(code\):
bool check(int x) { return ch[fa[x]][1]==x; } void pushup(int x) { siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+cnt[x]; } void rotate(int x) { int y=fa[x],z=fa[y],k=check(x); ch[z][check(y)]=x,fa[x]=z; ch[y][k]=ch[x][k^1],fa[ch[x][k^1]]=y; ch[x][k^1]=y,fa[y]=x; pushup(y),pushup(x); } void splay(int x,int goal) { for(int y;fa[x]!=goal;rotate(x)) if(fa[y=fa[x]]!=goal) rotate(check(x)^check(y)?x:y); if(!goal) root=x; } void insert(int x) { int p=root,pre=0; while(p&&key[p]!=x) { pre=p; p=ch[p][key[p]<x]; } if(p) cnt[p]++; else { p=++tot; if(pre) ch[pre][key[pre]<x]=p; fa[p]=pre; key[p]=x; cnt[p]=siz[p]=1; ch[p][0]=ch[p][1]=0; } splay(p,0); } void find(int x) { int p=root; while(ch[p][key[p]<x]&&x!=key[p]) p=ch[p][key[p]<x]; splay(p,0); } int rnk(int x) { find(x); return siz[ch[root][0]]; } int val(int x) { int p=root; x++; while(1) { if(ch[p][0]&&x<=siz[ch[p][0]]) p=ch[p][0]; else { int tmp=siz[ch[p][0]]+cnt[p]; if(x<=tmp) return key[p]; x-=tmp; p=ch[p][1]; } } } int get(int x,int k) { find(x); int p=root; if(key[p]>x&&k) return p; if(key[p]<x&&!k) return p; p=ch[p][k]; while(ch[p][k^1]) p=ch[p][k^1]; return p; } void del(int x) { int pre=get(x,0),nxt=get(x,1); splay(pre,0),splay(nxt,pre); int d=ch[nxt][0]; if(cnt[d]>1) { cnt[d]--; splay(d,0); } else { ch[nxt][0]=0; pushup(nxt),pushup(root); } } ...... insert(inf),insert(-inf); insert(a) del(a) rnk(a) val(a) key[get(a,0)] key[get(a,1)]
来源:https://www.cnblogs.com/lhm-/p/12229482.html