伸展树 模板(指针+数组)

来源:互联网 发布:js如何获取对象的长度 编辑:程序博客网 时间:2024/05/29 17:55

转载自:http://blog.csdn.net/leolin_/article/details/6436037

#include <iostream>using namespace std;#define MAXN 100010struct Node{    int key, sz, cnt;    Node *ch[2], *pnt;//左右儿子和父亲    Node(){}    Node(int x, int y, int z){    key = x, sz = y, cnt = z;    }    void rs(){    sz = ch[0]->sz + ch[1]->sz + cnt;    }}nil(0, 0, 0), *NIL = &nil;struct Splay{//伸展树结构体类型    Node *root;    int ncnt;//计算key值不同的结点数,注意已经去重了    Node nod[MAXN];    void init(){// 首先要初始化        root = NIL;        ncnt = 0;    }    void rotate(Node *x, bool d){//旋转操作,d为true表示右旋        Node *y = x->pnt;        y->ch[!d] = x->ch[d];        if (x->ch[d] != NIL)            x->ch[d]->pnt = y;        x->pnt = y->pnt;        if (y->pnt != NIL){            if (y == y->pnt->ch[d])                y->pnt->ch[d] = x;            else                y->pnt->ch[!d] = x;        }        x->ch[d] = y;        y->pnt = x;        y->rs();        x->rs();    }    void splay(Node *x, Node *target){//将x伸展到target的儿子位置处        Node *y;        while (x->pnt != target){            y = x->pnt;            if (x == y->ch[0]){                if (y->pnt != target && y == y->pnt->ch[0])                    rotate(y, true);                    rotate(x, true);            }            else{                if (y->pnt != target && y == y->pnt->ch[1])                    rotate(y, false);                    rotate(x, false);            }        }        if (target == NIL)            root = x;    }    /************************以上一般不用修改************************/    void insert(int key){//插入一个值        if (root == NIL){            ncnt = 0;            root = &nod[++ncnt];            root->ch[0] = root->ch[1] = root->pnt = NIL;            root->key = key;            root->sz = root->cnt = 1;            return;        }        Node *x = root, *y;        while (1){            x->sz++;            if (key == x->key){                x->cnt++;                x->rs();                y = x;                break;            }            else if (key < x->key){                    if (x->ch[0] != NIL)                        x = x->ch[0];                    else{                        x->ch[0] = &nod[++ncnt];                        y = x->ch[0];                        y->key = key;                        y->sz = y->cnt = 1;                        y->ch[0] = y->ch[1] = NIL;                        y->pnt = x;                        break;                    }            }            else{                if (x->ch[1] != NIL)                    x = x->ch[1];                else{                    x->ch[1] = &nod[++ncnt];                    y = x->ch[1];                    y->key = key;                    y->sz = y->cnt = 1;                    y->ch[0] = y->ch[1] = NIL;                    y->pnt = x;                    break;                }            }        }        splay(y, NIL);    }    Node* search(int key){//查找一个值,返回指针        if (root == NIL)            return NIL;        Node *x = root, *y = NIL;        while (1){            if (key == x->key){                y = x;                break;            }            else if (key > x->key){                if (x->ch[1] != NIL)                x = x->ch[1];                else                    break;            }            else{                if (x->ch[0] != NIL)                    x = x->ch[0];                else                    break;            }        }        splay(x, NIL);        return y;    }    Node* searchmin(Node *x){//查找最小值,返回指针        Node *y = x->pnt;        while (x->ch[0] != NIL){//遍历到最左的儿子就是最小值            x = x->ch[0];        }            splay(x, y);            return x;    }    void del(int key){//删除一个值        if (root == NIL)            return;        Node *x = search(key), *y;        if (x == NIL)            return;        if (x->cnt > 1){            x->cnt--;            x->rs();            return;        }        else if (x->ch[0] == NIL && x->ch[1] == NIL){            init();            return;        }        else if (x->ch[0] == NIL){            root = x->ch[1];            x->ch[1]->pnt = NIL;            return;        }        else if (x->ch[1] == NIL){            root = x->ch[0];            x->ch[0]->pnt = NIL;            return;        }        y = searchmin(x->ch[1]);        y->pnt = NIL;        y->ch[0] = x->ch[0];        x->ch[0]->pnt = y;        y->rs();        root = y;    }    int rank(int key){//求结点高度        Node *x = search(key);        if (x == NIL)            return 0;        return x->ch[0]->sz + 1/* or x->cnt*/;    }    Node* findk(int kth){//查找第k小的值        if (root == NIL || kth > root->sz)            return NIL;        Node *x = root;        while (1){            if (x->ch[0]->sz +1 <= kth && kth <= x->ch[0]->sz + x->cnt)                break;            else if (kth <= x->ch[0]->sz)                x = x->ch[0];            else{                kth -= x->ch[0]->sz + x->cnt;                x = x->ch[1];            }        }        splay(x, NIL);        return x;    }}sp;int main(){    sp.init();    sp.insert(10);    sp.insert(2);    sp.insert(2);    sp.insert(2);    sp.insert(3);    sp.insert(3);    sp.insert(10);    for (int i = 1; i <= 7; i++)        cout << sp.findk(i)->key << endl;    cout<<sp.searchmin(sp.root)->key<<endl;    sp.del(2);    sp.del(3);    sp.del(1);    return 0;}突然发现这种指针形模板有他的局限性,所以这面这是数组模拟
#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define MAXN 1000000struct Spaly{    int ch[MAXN][2],f[MAXN],size[MAXN],cnt[MAXN],key[MAXN];    int sz,root;    void init()    {        sz=root=0;    }    inline void clear(int x)    {        ch[x][0]=ch[x][1]=f[x]=size[x]=cnt[x]=key[x]=0;    }    inline bool get(int x)    {        return ch[f[x]][1]==x;    }    inline void update(int x)    {        if (x)        {            size[x]=cnt[x];            if (ch[x][0]) size[x]+=size[ch[x][0]];            if (ch[x][1]) size[x]+=size[ch[x][1]];        }    }    inline void rotate(int x)    {        int old=f[x],oldf=f[old],whichx=get(x);        ch[old][whichx]=ch[x][whichx^1];        f[ch[old][whichx]]=old;        ch[x][whichx^1]=old;        f[old]=x;        f[x]=oldf;        if (oldf)            ch[oldf][ch[oldf][1]==old]=x;        update(old);        update(x);    }       inline void splay(int o, int aim)///    {        while(f[o] != aim)        {            int fa=f[o], g = f[fa];            if(g != aim) rotate(fa);            rotate(o);        }        update(o);        if(!aim) root = o;    }    inline void insert(int x)    {        if (root==0)        {            sz++;            ch[sz][0]=ch[sz][1]=f[sz]=0;            root=sz;            size[sz]=cnt[sz]=1;            key[sz]=x;            return;        }        int now=root,fa=0;        while(1)        {            if (x==key[now])            {                cnt[now]++;                update(now);                update(fa);                splay(now);                break;            }            fa=now;            now=ch[now][key[now]<x];            if (now==0)            {                sz++;                ch[sz][0]=ch[sz][1]=0;                f[sz]=fa;                size[sz]=cnt[sz]=1;                ch[fa][key[fa]<x]=sz;                key[sz]=x;                update(fa);                splay(sz);                break;            }        }    }    inline int find(int x)    {        int now=root,ans=0;        while(1)        {            if (x<key[now])                now=ch[now][0];            else            {                ans+=(ch[now][0]?size[ch[now][0]]:0);                if (x==key[now])                {                    splay(now);                    return ans+1;                }                ans+=cnt[now];                now=ch[now][1];            }        }    }    inline int findx(int x)    {        int now=root;        while(1)        {            if (ch[now][0]&&x<=size[ch[now][0]])                now=ch[now][0];            else            {                int temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];                if (x<=temp) return key[now];                x-=temp;                now=ch[now][1];            }        }    }    inline int pre()    {        int now=ch[root][0];        while (ch[now][1]) now=ch[now][1];        return now;    }    inline int next()    {        int now=ch[root][1];        while (ch[now][0]) now=ch[now][0];        return now;    }    inline void del(int x)    {        int whatever=find(x);        if (cnt[root]>1)        {            cnt[root]--;            update(root);            return;        }        if (!ch[root][0]&&!ch[root][1])        {            clear(root);            root=0;            return;        }        if (!ch[root][0])        {            int oldroot=root;            root=ch[root][1];            f[root]=0;            clear(oldroot);            return;        }        else if (!ch[root][1])        {            int oldroot=root;            root=ch[root][0];            f[root]=0;            clear(oldroot);            return;        }        int leftbig=pre(),oldroot=root;        splay(leftbig);        ch[root][1]=ch[oldroot][1];        f[ch[oldroot][1]]=root;        clear(oldroot);        update(root);    }} sp;int main(){    sp.init();    sp.insert(5);    sp.insert(7);    sp.insert(9);    sp.del(5);    sp.del(9);    sp.insert(9);    printf("%d %d\n",sp.size[sp.root],sp.root);}