几种平衡树

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #define ls(x) (x->ch[0])
  5 #define rs(x) (x->ch[1])
  6 #define sz(x) (x->size)
  7 #define p(x) (x->p)
  8 using namespace std;
  9 const int INF=0x7fffffff;
 10 struct son
 11 {
 12     int v,size;
 13     son *ch[2],*p;
 14     son(int x)
 15     {
 16         v=x;size=1;
 17     }
 18 };
 19 son *root,*null;
 20 son* newson(int val)
 21 {
 22     son *x=new son(val);
 23     ls(x)=rs(x)=p(x)=null;
 24     return x;
 25 }
 26 void pushup(son *x){sz(x)=sz(ls(x))+sz(rs(x))+1;}
 27 int rank(int val)
 28 {
 29     son *x=root;
 30     int ans=0;
 31     while(x!=null)
 32     {
 33         if(val>x->v){ans+=(sz(ls(x))+1);x=rs(x);}
 34         else x=ls(x);
 35     }
 36     return ans;
 37 }
 38 son* kth(int k)
 39 {
 40     //printf("sha bi qin shi yu\n");
 41     son *x=root;
 42     while(x!=null)
 43     {
 44         if(sz(ls(x))+1==k)return x;
 45         if(sz(ls(x))+1>k)x=ls(x);
 46         else {k-=(sz(ls(x))+1);x=rs(x);}
 47     }
 48     return null;
 49 }
 50 int islc(son *x){return ls(p(x))==x;}
 51 // is left child ???
 52 //x在右,就左旋  在左,就右旋
 53 void rot(son *x,int d)
 54 {
 55     son *y=x->ch[d^1];
 56     if(p(x)!=null)p(x)->ch[islc(x)^1]=y;//祖父儿子=y
 57     else root=y;
 58     p(y)=p(x);//把祖父儿子设成y
 59     x->ch[d^1]=y->ch[d];//
 60     if(y->ch[d])p(y->ch[d])=x;//把y的d同向儿子改成x的d逆向儿子
 61     y->ch[d]=x;p(x)=y;//把x的爸爸改成y
 62     pushup(x);pushup(y);
 63 }
 64 void splay(son *x,son *t=null)//把x旋到以t为祖父节点
 65 {
 66     for(son *rt=p(x);rt!=t;rt=p(x))
 67     {
 68         if(p(rt)==t)
 69         {
 70             rot(rt,islc(x));
 71             return ;
 72         }
 73         if(islc(x)==islc(rt))rot(p(rt),islc(rt));//一字型旋转 第一步
 74         else rot(rt,islc(x));//之字形旋转 第一步
 75         rot(p(x),islc(x));//第二步 (此时x已经转上去)
 76     }
 77 }
 78 void add(int val)
 79 {
 80     int pos=rank(val);//val排名-1
 81     splay(kth(pos));//把前一个转到root
 82     splay(kth(pos+1),root);//把pos+1的转到root右儿子
 83     //val 卡在pos和pos+1之间
 84     son *x=newson(val);
 85     root->ch[1]->ch[0]=x;
 86     p(x)=root->ch[1];
 87     pushup(root->ch[1]);pushup(root);
 88 }
 89 void del(int val)
 90 {
 91     int pos=rank(val)+1;
 92     splay(kth(pos-1));splay(kth(pos+1),root);
 93     //把val卡在pos-1和pos+1之间
 94     root->ch[1]->ch[0]=null;
 95     pushup(root->ch[1]);pushup(root);
 96 }
 97 int n;
 98
 99 int main(){
100     //freopen("phs.in","r",stdin);
101     //freopen("phs.out","w",stdout);
102     null=new son(0);sz(null)=0;
103     root=newson(-INF);
104     root->ch[1]=newson(INF);//即把一开始的区间调成-INF到INF
105     p(root->ch[1])=root;
106     scanf("%d",&n);
107     for(int i=1;i<=n;++i)
108     {
109         int opt,x;scanf("%d%d",&opt,&x);
110         switch(opt)
111         {
112             case 1:add(x);break;
113             case 2:del(x);break;
114             case 3:printf("%d\n",rank(x));break;
115             //返回值就是rank的原因:********
116             //一开始root的值=-INF root右儿子=INF *******
117             //每次查找一定会到这两个节点,而他们size=1
118             case 4:printf("%d\n",kth(x+1)->v);break;
119             //不能轻易在rank上+1,必须在x上+1
120             case 5:printf("%d\n",kth(rank(x))->v);break;
121             case 6:printf("%d\n",kth(rank(x+1)+1)->v);break;
122         }
123     }
124     while(1);
125     return 0;
126 }

Splay详细注释

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define ls(x) (x->l)
  6 #define rs(x) (x->r)
  7 #define sz(x) ((x)?(x->size):(0))
  8 using namespace std;
  9 struct Treap
 10 {
 11     struct treap
 12     {
 13         int size,fix,val;
 14         treap *l,*r;
 15         treap(int x)
 16         {
 17             val=x;fix=rand();size=1;
 18             l=r=NULL;
 19         }
 20     }*root;
 21     void pushup(treap *x){x->size=sz(ls(x))+sz(rs(x))+1;}
 22     void lturn(treap *&x)
 23     {
 24         treap *y=rs(x);
 25         rs(x)=ls(y);pushup(x);
 26         ls(y)=x;pushup(y);
 27         x=y;
 28     }
 29     void rturn(treap *&x)
 30     {
 31         treap *y=ls(x);
 32         ls(x)=rs(y);pushup(x);
 33         rs(y)=x;pushup(y);
 34         x=y;
 35     }
 36     void add(treap *&x,int val)
 37     {
 38         if(x==NULL)
 39         {
 40             x=new treap(val);
 41             return ;
 42         }
 43         if(val<x->val)
 44         {
 45             add(ls(x),val);
 46             pushup(x);
 47             if(ls(x)->fix>x->fix)rturn(x);
 48         }
 49         else
 50         {
 51             add(rs(x),val);
 52             pushup(x);
 53             if(rs(x)->fix>x->fix)lturn(x);
 54         }
 55     }
 56     void del(treap *&x,int val)
 57     {
 58         if(val==x->val)
 59         {
 60             if(ls(x)&&rs(x))
 61             {
 62                 if(ls(x)->fix>rs(x)->fix){rturn(x);del(rs(x),val);}
 63                 else {lturn(x);del(ls(x),val);}
 64             }
 65             else
 66             {
 67                 treap *y=NULL;
 68                 if(ls(x))y=ls(x);
 69                 else y=rs(x);
 70                 delete x;x=y;
 71             }
 72         }
 73         else
 74         {
 75             if(val<x->val)del(ls(x),val);
 76             else del(rs(x),val);
 77         }
 78         if(x)pushup(x);
 79     }
 80     int rank(int val)
 81     {
 82         treap *x=root;
 83         int ans=0;
 84         while(x)
 85         {
 86             if(val>x->val){ans+=(sz(ls(x))+1);x=rs(x);}
 87             else x=ls(x);
 88         }
 89         return ans;
 90     }
 91     treap* kth(int k)
 92     {
 93         treap *x=root;
 94         while(x)
 95         {
 96             int size=sz(ls(x))+1;
 97             if(size==k)return x;
 98             if(size>=k)x=ls(x);
 99             // = 向右走,因为add的时候就是向右
100             else {k-=size;x=rs(x);}
101         }
102     }
103 }T;
104
105 int m,u,o;
106
107 int main(){
108     //freopen("phs.in","r",stdin);
109     //freopen("phs.out","w",stdout);
110     scanf("%d",&m);
111     while(m--)
112     {
113         scanf("%d%d",&u,&o);
114         if(u==1)T.add(T.root,o);
115         else if(u==2)T.del(T.root,o);
116         else if(u==3)printf("%d\n",T.rank(o)+1);
117         else if(u==4)printf("%d\n",T.kth(o)->val);
118         else if(u==5)printf("%d\n",T.kth(T.rank(o))->val);
119         else printf("%d\n",T.kth(T.rank(o+1)+1)->val);
120         //加2有可能返回一个空指针,炸掉你
121     }
122     while(1);
123     return 0;
124 }

旋转Treap

时间: 2024-11-07 17:45:51

几种平衡树的相关文章

几种平衡树的总结

一.2-3-4树介绍 2-3-4树是一种多叉树(multiway tree),它的每个节点最多有四个子节点和3个数据项,2-3-4 树可以看做是阶为4 的B树.B树是另一种平衡的多叉树,专门用在外部存储中来组织数据(通常是指磁盘驱动器).B树中的节点可以有几时或几百个. 2-3-4树名字中的2.3.4的含义是指一个节点可能含有的子节点数. 有1个数据项的节点总是有2个子节点 有2个数据项的节点总是有3个子节点 有3个数据项的节点总是有4个子节点 简言之,非叶子节点的子节点数总是比它含有的数据项多

各种平衡树Treap/SBT/Avl/Splay tree

看了这么久的平衡树,是时候做个总结了. 以poj 3481为例,敲了四份代码,分别是Treap ,Size Balance Tree,Avl Tree,splay tree. 唯独少了红黑树T_T... 总的来说每种平衡树各有各的优点吧: Treap写起来简单上手也快如果熟练的话不到十分种可以敲完. SBT速度快名不虚传... Avl树高度平衡吧,不过实际的效果不尽如人意,可能是我实现的姿势不对吧/(ㄒoㄒ)/~~ splay tree各方面比较均衡,特别的伸展树在维护序列方面相对其它几种树优势

子树大小平衡树

#include<cstdio> #define MXN 100000+3 #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define nil 0 #define LEFT false #define RIGHT true int val[MXN],size[MXN],fa[MXN],left[MXN],right[MXN],recycle[1001],root; int ntop,rtop=-1,rcount; in

平衡树讲解(旋转treap,非旋转treap,splay)

在刷了许多道平衡树的题之后,对平衡树有了较为深入的理解,在这里和大家分享一下,希望对大家学习平衡树能有帮助. 平衡树有好多种,比如treap,splay,红黑树,STL中的set.在这里只介绍几种常用的:treap和splay(其中treap包括旋转treap和非旋转treap). 一.treap treap这个词是由tree和heap组合而成,意思是树上的的堆(其实就是字面意思啦qwq).treap可以说是由二叉搜索树(BST)进化而来,二叉搜索树每个点满足它左子树中所有点权值都比它小,它右子

平衡树代码总结

这里给出博主的几种平衡树模板代码 vector 代码: // luogu-judger-enable-o2 #include<bits/stdc++.h> #define rd(x) x=read() using namespace std; int n; vector<int>v; inline int read() { int f=1,x=0;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar

平衡树之Splay

算法简介 Splay是一种平衡树,支持插入.删除.求排名.求第\(k\)大数.求前驱和求后继的操作,并且它还能做到一般平衡树做不到的区间操作. 定义与性质 先说二叉查找树:就是把所有数建在树上,且左边的数永远小于右边的. 对于上面说的那6个操作,其实在数据随机时二叉查找树时最强的,但是数据一条链你就Good Game了. 这种情况我们希望这棵二叉查找树的节点深度差不要太大,这就有了平衡树. 顾名思义,平衡树是平衡的二叉查找树,意思就是说1条链这种数据对于平衡树来说完全不存在,这样复杂度就有保证了

【codeforces85D】

去实验培训回来了--写个题先玩玩 这题给人一种平衡树的感觉 但是呢,实际上操作离线+离散化+线段树一样能做 #include<bits/stdc++.h> #define lson (o<<1) #define rson (o<<1|1) const int N=2e5+5; typedef long long ll; using namespace std; struct Opt{int tp,num;}op[N]; int n,a[N],cnt=0,tot=0; l

[数据结构]替罪羊树简介

替罪羊树是不通过旋转而是重构的一种平衡树.当某一棵子树的节点总数超过其父节点的一定时,就进行重构操作. 目录 节点定义 重构操作 插入操作 删除操作 其他各种操作 完整代码&总结 [节点定义] 为了判断是否需要重构,所以需要加入cover(实际节点个数)域.这次直接加入可重操作,所以还需要增加一个size域.为了体现C++面向对象的思想(分明就是Java用多了),所以判断一个子树是否需用重构写成成员函数bad().(真开心,因为是重构,不需要那么多的father,终于可以轻松地删掉父节点指针)

支持泛型AVL Tree的简单实现,并和STL map比较了插入,删除,查找的性能

1.问题描述: 1)AVL tree是一种自平衡树.它通过左右子树的高度差来控制树的平衡,当高度差是不大于1的时候,认为树是平衡的.树的平衡保证了树在极端情况下 (输入序列不够随机)的性能.很显然当左右子树高度平衡,保证了任何插入,删除,查找操作平均性能呢个,当不平衡时(有的子树很高),当 要操作的元素在这个子树时,性能会很差: 2)AVL tree 和Red black tree 都是一种平衡树,它的操作的时间复杂度是:O(lgN) ,N是树的节点的数目: 3)本文实现了AVL Tree, 并