【伸展树篇】正常向的伸展树

来源:互联网 发布:傲慢与偏见与僵尸 知乎 编辑:程序博客网 时间:2024/06/06 09:11
#include <cstdio>const int MAXN = 100000 + 500;struct Node{    int size;    int value;    Node* parent;    Node* child[2];}_memory[MAXN],*EMPTY = _memory;inline void Update(Node* x){x->size = x->child[0]->size + x->child[1]->size + 1;}void Zig(Node* x){    Node* y = x->parent;    y->child[0] = x->child[1];    if(x->child[1] != EMPTY) x->child[1]->parent = y;    x->parent = y->parent;    if(y->parent != EMPTY){        if(y->parent->child[0] == y) y->parent->child[0] = x;        else        if(y->parent->child[1] == y) y->parent->child[1] = x;    }    y->parent = x;    x->child[1] = y;}void Zag(Node* x){    Node* y = x->parent;    y->child[1] = x->child[0];    if(x->child[0] != EMPTY) x->child[0]->parent = y;    x->parent = y->parent;    if(y->parent != EMPTY){        if(y->parent->child[0] == y) y->parent->child[0] = x;        else        if(y->parent->child[1] == y) y->parent->child[1] = x;    }    y->parent = x;    x->child[0] = y;}void Splay(Node* &x){    Node* p = EMPTY;    while(x->parent != EMPTY){        p = x->parent;        if(p->parent == EMPTY){            if(x == p->child[0]) return Zag(x);            else            if(x == p->child[1]) return Zig(x);        }        else {            if(x == p->parent->child[0]){                if(x == p->child[0]) Zig(p), Zig(x);                else                if(x == p->child[1]) Zig(x), Zag(x);            }            else            if(x == p->parent->child[1]){                if(x == p->child[1]) Zag(p), Zig(x);                else                if(x == p->child[0]) Zag(x), Zig(x);            }        }    }}Node* Find(Node* &root,int d){    Node* tmp = root;    while(tmp != EMPTY){        if(tmp->value == d) break;        tmp = tmp->child[tmp->value > d];    }if(tmp != EMPTY) Splay(tmp);return tmp;}int main(){    return 0;}

 

首先使用Zig,和Zag一定是强迫症,因为怎么搞LeftRotate和RightRotate都不一样长。

 

之后使用一个EMPTY指针的方式是值得学习的方式,简化了自底向上递归的更新操作,使其不必判断空子树,最主要的是构造这个EMPTY是在编译期搞定的,而不用考虑之后的

初始化问题。

 

普通的用法一般是搞一个空的变量然后取地址然后搞,但是这样需要把准备动作搞到主函数去,这样最好了(强迫症晚期何弃疗)。

 

再者对于Node* n,和Node *n又有了新的理解,首先从定义上来说,Node*  才是正解(不然哪来的int[]),但是如果同一行申请多个变量,那么只能用Node *a,*b,反正都是强迫症的错。

 

最后提一下struct Node{int x,y;}node[MAXN];的好处是不必另外开一行申请数组了(扯),其实是把结构体名给屏蔽掉(因为这种结构体之后都不会单独申请变量了),这里使用Node命名然后以node实现不用在起名字上大费周章了。

 

只有程序员才能懂得烦恼----命名。


 

原创粉丝点击