splay tree  营业额统计

来源:互联网 发布:法条软件 编辑:程序博客网 时间:2024/05/13 12:21

Splaytree

伸展树是一种平横二叉树, 支持查找,插入之类的二叉树具有的功能,还独自具有树的合并和分离(合并是由条件的:要求一棵树的所有值小于另一棵树)。若有了其他平衡树的经验,写一个splay tree应该不难,但不知道后期扩展的时候的可扩性如何。

代码还是比较好些的,我自己写的也比较挫,你后做题的过程中慢慢精益求精吧。像所有人说的一样,伸展树最重要的,最核心的就是那个splayx)操作,而且操作比较易懂,通过若干次splayx)操作将x移到根的位置去;下面是splay的情况,和红黑树类似。

伸展操作Splay(x,S) 情况1

ZigZag操作:

  节点x的父节点y是根节点。

splay <wbr>tree <wbr> <wbr>营业额统计

即通常所说的左旋和右旋。

伸展操作Splay(x,S) 情况2

Zig-ZigZag-Zag操作:

   节点x的父节点y不是根节点,且xy同时是各自父节点的左孩子或者同时是各自父节点的右孩子。

splay <wbr>tree <wbr> <wbr>营业额统计

伸展操作Splay(x,S) 情况3

Zig-ZagZag-Zig操作:

   节点x的父节点y不是根节点,xy中一个是其父节点的左孩子而另一个是其父节点的右孩子。

splay <wbr>tree <wbr> <wbr>营业额统计

 

 

只要相应的将这三种情况写出来就好了。例题可用http://www.zybbs.org/JudgeOnline/problem.php?id=1588营业额统计

 

 

代码:

#include <cstdio>

#include <cstring>

#include <iostream>

#include <cmath>

#include <cstdlib>

using namespacestd;

 

#define INF 210000000

#define maxn 1000000

 

structsplayTreeNode{

   int data;

   splayTreeNode* l,* r,* p;

   void init(int x, splayTreeNode* sl, splayTreeNode* sr,splayTreeNode* fa){

      data = x, l = sl, r = sr, p = fa;

   }

};

 

structsplayTree{

   splayTreeNode* root;

   splayTreeNode* link;

   int ad;

   splayTree(){

      root = NULL;

      link = newsplayTreeNode[maxn];

      ad = 0;

   }

   ~splayTree() { delete[] link;}

   void rotateRight(splayTreeNode*&rt){

      splayTreeNode* temp = rt->l;

      rt->l = temp->r;

      if(temp->r != NULL)temp->r->p = rt;

      temp->r = rt;

      temp->p = rt->p;

      rt->p = temp;

      rt = temp;

   }

   void rotateLeft(splayTreeNode*&rt){

      splayTreeNode* temp = rt->r;

      rt->r = temp->l;

      if(temp->l !=NULL)temp->l->p = rt;

      temp->l = rt;

      temp->p = rt->p;

      rt->p = temp;

      rt = temp;

   }

   void splay(splayTreeNode*x){

      if(x == root) return;

      if(root->l == x ||root->r == x){

          if(root->l == x)rotateRight(root);

          else rotateLeft(root);

          return;

      }

      splayTreeNode* y,* z;

      y = x->p;

      z = y->p;

      if((z->l == y&& y->l == x) ||(z->r == y &&y->r == x)){

          if((z->l ==y)){

             if(z == root)rotateRight(root);

             else{

                 if(z->p->l == z)rotateRight(z->p->l);

                 elserotateRight(z->p->r);

             }

             if(y == root)rotateRight(root);

             else{

                 if(y->p->l == y)rotateRight(y->p->l);

                 elserotateRight(y->p->r);

             }

          }

          else{

             if(z == root)rotateLeft(root);

             else{

                 if(z->p->l == z)rotateLeft(z->p->l);

                 elserotateLeft(z->p->r);

             }

             if(y == root)rotateLeft(root);

             else{

                 if(y->p->l == y)rotateLeft(y->p->l);

                 elserotateLeft(y->p->r);

             }

          }

      }

      else{

          if(z->l ==y){

             if(y->p->l == y)rotateLeft(y->p->l);

             elserotateLeft(y->p->r);

             if(z == root)rotateRight(root);

             else{

                 if(z->p->l == z)rotateRight(z->p->l);

                 elserotateRight(z->p->r);

             }

          }

          else{

             if(y->p->l == y)rotateRight(y->p->l);

             elserotateRight(y->p->r);

             if(z == root)rotateLeft(root);

             else{

                 if(z->p->l == z)rotateLeft(z->p->l);

                 elserotateLeft(z->p->r);

             }

          }

      }

      splay(x);

   }

   void insert(int x, splayTreeNode* &rt,splayTreeNode* rf){

      if(rt == NULL){

          rt = &link[ad ++];

          rt->init(x, NULL, NULL, rf);

          splay(rt);

          return;

      }

      if(x <rt->data) insert(x, rt->l,rt);

      else insert(x,rt->r, rt);

   }

   bool find(int x){

      for(splayTreeNode* tp = root; tp !=NULL;){

          if(tp->data ==x){

             splay(tp);

             return 1;

          }

          if(x >tp->data) tp = tp->r;

          else tp =tp->l;

      }

      return 0;

   }

   void remove(int x){

      splayTreeNode* tp = root,* fp = root, * *temp;

      for(; tp->data != x;fp = tp){

          if(x <tp->data) tp = tp->l;

          else tp =tp->r;

      }

      if(tp == NULL) return;

      if(tp->l == NULL ||tp->r == NULL){

          if(tp->l != NULL)temp = &(tp->l);

          else temp =&(tp->r);

          if(tp == fp->l)fp->l = *temp;

          else fp->r =*temp;

          (*temp)->p = fp;

          splay(fp);

      }

      else{

          fp = tp->l;

          while(fp->r !=NULL){

             fp = fp->r;

          }

          if(fp ==tp->l){

             tp->l = fp->l;

          }

          else{

             fp->p->r =fp->l;

             fp->r->p =fp->p;

             tp->data = fp->data;

          }

          splay(tp);

      }

   }

   void clear(){

      root = NULL;

   }

   int small(){

      if(root == NULL ||root->l == NULL) return INF;

      splayTreeNode* tp = root->l;

      while(tp->r != NULL)tp = tp->r;

      returntp->data;

   }

   int big(){

      if(root == NULL ||root->r == NULL) return INF;

      splayTreeNode* tp = root->r;

      while(tp->l != NULL)tp = tp->l;

      returntp->data;

   }

};

 

int main(){

   int n, x, sum;

   while(~scanf("%d %d", &n,&sum)){

      splayTree spl;

      spl.insert(sum, spl.root, NULL);

      for(int i = 1; i < n; ++i){

          if(!(~scanf("%d", &x))) x =0;

          if(spl.find(x)) continue;

          spl.insert(x, spl.root, NULL);

          int l = abs(x - spl.small()), r =abs(spl.big() - x);

          sum += l < r ? l : r;

      }

      printf("%d\n", sum);

   }

   return 0;

}

 

 

 

原创粉丝点击