伸展树(Splay Tree)

伸展树是一种平衡二叉树。在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置。于是想到设计一个简单方法, 在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方。伸展树应运而生。

 

平衡二叉树都需要通过旋转操作来维持树的平衡性.

Left_Rotate(Node &x)//x.right ≠ NIL
    Node y = x.right                // set y
    x.right = y.left           //turn y's left subtree to x's right subtree
    if y.left ≠ NIL
        y.left.p = x
    y.p = x.p                  //link x's parent to y
    if x.p == NIL
        //T.root = y
    else if x == x.p.left    
        x.p.left = y
    else
        x.p.right = y
    y.left = x                 //put x on y's left
    x.p = y
    //x = y这句代码可以让x重新指向这棵子树的根结点

Right_Rotate(Node &y)//y.left ≠ NIL
    Node x = y.left                 // set x
    y.left = x.right           //turn x's right subtree to y's left subtree
    if x.right ≠ NIL
        x.right.p = y
    x.p = y.p                  //link y's parent to x
    if y.p == NIL
        //T.root = x
    else if y == y.p.left    
        y.p.left = x
    else
        y.p.right = x
    x.right = y                 //put y on x's right
    y.p = x
    //y = x

如果不考虑父结点这个属性的话,有更简单的方式.

void left_rotate(Node* &x){
    Node* y =x->right;
    x->right = y->left;
    y->left = x;
    x = y;
}

void right_rotate(Node* &x){
    Node* y =x->left;
    x->left = y->right;
    y->right = x;
    x = y;
}

伸展操作:

void splay( node *x ) {
    while( x->parent ) {
      if( !x->parent->parent ) {//x的父结点为树根
        if( x->parent->left == x ) right_rotate( x->parent );
        else left_rotate( x->parent );
      } 
      else if( x->parent->left == x && x->parent->parent->left == x->parent ) {//左"一字型"
        right_rotate( x->parent->parent );
        right_rotate( x->parent );
      } 
      else if( x->parent->right == x && x->parent->parent->right == x->parent ) {//右"一字型"
        left_rotate( x->parent->parent );
        left_rotate( x->parent );
      } 
      else if( x->parent->left == x && x->parent->parent->right == x->parent ) {//左右"之自型"(从下至上看)
        right_rotate( x->parent );
        left_rotate( x->parent );
      } 
      else {//右左"之自型"(从下至上看)
        left_rotate( x->parent );
        right_rotate( x->parent );
      }
    }
  }

 

posted @ 2015-04-13 13:43  fosmj  阅读(218)  评论(0)    收藏  举报