Splay的几种操作(代码)

来源:互联网 发布:土豆for mac下载 编辑:程序博客网 时间:2024/05/22 15:40

1.右旋(zig)

void _zig(int x){int y,z;y=pr[x];z=pr[y];if(z==0)    root=x;else if(ls[z]==y)    ls[z]=x;else     rs[z]=x;pr[x]=z;pr[y]=x;ls[y]=rs[x];pr[rs[x]]=y;rs[x]=y;size[x]=size[y];size[y]=size[ls[y]]+size[rs[y]]+1;}
2.左旋(zag)

void _zag(int x){int y,z;y=pr[x];z=pr[y];if(z==0)    root=x;else if(ls[z]==y)    ls[z]=x;else     rs[z]=x;pr[x]=z;pr[y]=x;rs[y]=ls[x];pr[ls[x]]=y;ls[x]=y;size[x]=size[y];size[y]=size[ls[y]]+size[rs[y]]+1;}
3.splay旋转(平衡性较好的一种写法)
void _splay(int x){    int j;    while(x!=root)    {        j=pr[x];        if(j==root)        {            if(x==ls[j])_zig(x);            else _zag(x);        }        else         {            if(j==ls[pr[j]])            {                if(x==ls[j]){_zig(j);_zig(x);}                else {_zag(x);_zig(x);}            }            else             {                if(x==rs[j]){_zag(j);_zag(x);}                else {_zig(x);_zag(x);}            }        }    }}
4.插入(insert)(记了左右子节点数量的一种写法,便于查找第k小)
void _insert(int key){int i=root;if(size[i]==0){data[i]=key;pr[i]=0;size[i]=1;tot++;return;}if(_find(key)==-1){    while(true)    {    if(key<data[i])    {    if(ls[i]!=0)    {    size[i]++;        i=ls[i];    }    else     {    pr[tot]=i;    data[tot]=key;    ls[i]=tot;    size[tot]=1;    size[i]++;    tot++;    return;    }    }    else if(key>data[i])    {    if(rs[i]!=0)    {    size[i]++;        i=rs[i];    }     else     {    pr[tot]=i;    data[tot]=key;    rs[i]=tot;    size[tot]=1;    size[i]++;    tot++;    return;    }    }    else    {    _splay(i);    return;    }    }}}
5.删除(del)
void _del(int key){int x,y=0,z=0;x=_find(key);if(x==-1)    return;_splay(x);y=_findpre(x);if(y!=0){_splay(y);rs[y]=rs[x];pr[rs[x]]=y;size[y]--;root=y;}else{z=rs[x];pr[z]=0;root=z;}}
6.查找(find)
int _find(int key){int i=root;while(i!=0){if(key<data[i])    i=ls[i];else if(key>data[i])    i=rs[i];else     return i;}return -1;}
7.找前驱(findpre)
int _findpre(int x){int i;if(x!=root)    _splay(x);i=ls[x];while(rs[i]!=0) i=rs[i];return i;}
8.找后继(findnex)
int findnex(int key)//返回值为key的后继的下标{int k=root,ans=0;while(k)if(key>data[k])k=rs[k];else{ans=k;k=ls[k];}return ans;}
9.找第k小数(findkth)

int _findkth(int x){    int i=root;    while(i!=0)    {        if(ls[i]!=0&&x<=size[ls[i]])    i=ls[i];        else if(x>size[ls[i]]+1)        {            x-=size[ls[i]]+1;            i=rs[i];        }        else            return data[i];    }    if(i==0)    return 0;}