手写一个节点大小平衡树(SBT)模板,留着用
Posted yxysuanfa
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写一个节点大小平衡树(SBT)模板,留着用相关的知识,希望对你有一定的参考价值。
看了一下午,感觉有了些了解。应该没有错,有错希望斧正,感谢
#include<stdio.h> #include<string.h> struct s { int key,left,right,size; }tree[10010]; int top; void left_rot(int &x)// 左旋 { int y=tree[x].right; tree[x].right=tree[y].left; tree[y].left=x; tree[y].size=tree[x].size; tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1; x=y; } void right_rot(int &x)//右旋 { int y=tree[x].left; tree[x].left=tree[y].right; tree[y].right=x; tree[y].size=tree[x].size; tree[x].size=tree[tree[x].left].size+tree[tree[x].right].size+1; x=y; } void maintain(int &x,bool flag)//维护SBT状态 { if(flag==false)//左边 { if(tree[tree[tree[x].left].left].size>tree[tree[x].right].size)//左孩子的左孩子大于右孩子 right_rot(x); else if(tree[tree[tree[x].left].right].size>tree[tree[x].right].size)//左孩子的右孩子大于右孩子 { left_rot(tree[x].left); right_rot(x); } else return; } else//右边 { if(tree[tree[tree[x].right].right].size>tree[tree[x].left].size)//右孩子的右孩子大于左孩子 left_rot(x); else if(tree[tree[tree[x].right].left].size>tree[tree[x].left].size)//右孩子的左孩子大于左孩子 { right_rot(tree[x].right); left_rot(x); } else return; } maintain(tree[x].left,false); maintain(tree[x].right,true); maintain(x,true); maintain(x,false); } void insert(int &x,int key)//插入 { if(x==0) { x=++top; tree[x].left=0; tree[x].right=0; tree[x].size=1; tree[x].key=key; } else { tree[x].size++; if(key<tree[x].key) insert(tree[x].left,key); else insert(tree[x].right,key);//同样元素可插右子树 maintain(x,key>=tree[x].key); } } int remove(int &x,int key)//利用后继删除 { tree[x].size--; if(key>tree[x].key) remove(tree[x].right,key); else if(key<tree[x].key) remove(tree[x].left,key); else if(tree[x].left!=0&&tree[x].right==0)//有左子树,无右子树 { int temp=x; x=tree[x].left; return temp; } else if(!tree[x].left&&tree[x].right!=0)//有右子树,无左子树 { int temp=x; x=tree[x].right; return temp; } else if(!tree[x].left&&!tree[x].right)//无左右子树 { int temp=x; x=0; return temp; } else//左右子树都有 { int temp=tree[x].right; while(tree[temp].left) temp=tree[temp].left; tree[x].key=tree[temp].key; remove(tree[x].right,tree[temp].key); } } int getmin(int x)//求最小值 { while(tree[x].left) x=tree[x].left; return tree[x].key; } int getmax(int x)//求最大值 { while(tree[x].right) x=tree[x].right; return tree[x].key; } int pred(int &x,int y,int key)//前驱,y初始前驱,从0開始, 终于要的是返回值的key值 { if(x==0) return y; if(key>tree[x].key) return pred(tree[x].right,x,key); else return pred(tree[x].left,y,key); } int succ(int &x,int y,int key)//后继。同上 { if(x==0) return y; if(key<tree[x].key) return succ(tree[x].left,x,key); else return succ(tree[x].right,y,key); } int select(int &x,int k)//选第k小的数 { int r=tree[tree[x].left].size+1; if(r==k) return tree[x].key; else if(r<k) return select(tree[x].right,k-r); else return select(tree[x].left,k); } int rank(int &x,int key)//key排第几 { if(key<tree[x].key) { return rank(tree[x].left,key); } else if(key>tree[x].key) return rank(tree[x].right,key)+tree[tree[x].left].size+1; else return tree[tree[x].left].size+1; } void order(int &x) { if(x==0) return; order(tree[x].left); printf("%d\n",tree[x].key); order(tree[x].right); } int main() { top=0; }
以上是关于手写一个节点大小平衡树(SBT)模板,留着用的主要内容,如果未能解决你的问题,请参考以下文章
平衡树初阶——AVL平衡二叉查找树+三大平衡树(Treap + Splay + SBT)模板超详解