splay tree

Posted Code--Dream

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了splay tree相关的知识,希望对你有一定的参考价值。



类别:二叉排序树
空间效率:O(n)
时间效率:O(log n)内完成插入、查找、删除操作
创造者:Daniel Sleator和Robert Tarjan 优点:每次查询会调整树的结构,使被查询频率高的条目更靠近树根。

注:所有图片来自wiki。
http://blog.csdn.net/cyberzhg/article/details/8058208

Tree Rotation




树的旋转是splay的基础,对于二叉查找树来说,树的旋转不破坏查找树的结构。

Splaying


Splaying是Splay Tree中的基本操作,为了让被查询的条目更接近树根,Splay Tree使用了树的旋转操作,同时保证二叉排序树的性质不变。 Splaying的操作受以下三种因素影响:
  • 节点x是父节点p的左孩子还是右孩子
  • 节点p是不是根节点,如果不是
  • 节点p是父节点g的左孩子还是右孩子
同时有三种基本操作:

Zig Step



当p为根节点时,进行zip step操作。 当x是p的左孩子时,对x右旋; 当x是p的右孩子时,对x左旋。

Zig-Zig Step



当p不是根节点,且x和p同为左孩子或右孩子时进行Zig-Zig操作。 当x和p同为左孩子时,依次将p和x右旋; 当x和p同为右孩子时,依次将p和x左旋。

Zig-Zag Step



当p不是根节点,且x和p不同为左孩子或右孩子时,进行Zig-Zag操作。 当p为左孩子,x为右孩子时,将x左旋后再右旋。 当p为右孩子,x为左孩子时,将x右旋后再左旋。

应用


Splay Tree可以方便的解决一些区间问题,根据不同形状二叉树先序遍历结果不变的特性,可以将区间按顺序建二叉查找树。 每次自下而上的一套splay都可以将x移动到根节点的位置,利用这个特性,可以方便的利用Lazy的思想进行区间操作。 对于每个节点记录size,代表子树中节点的数目,这样就可以很方便地查找区间中的第k小或第k大元素。 对于一段要处理的区间[x, y],首先splay x-1到root,再splay y+1到root的右孩子,这时root的右孩子的左孩子对应子树就是整个区间。 这样,大部分区间问题都可以很方便的解决, 操作同样也适用于一个或多个条目的添加或删除,和区间的移动。


POJ2764 Feed the dogs

http://poj.org/problem?id=2764
http://blog.csdn.net/cyberzhg/article/details/8058154

区间不会重叠,所以不可能有首首相同或尾尾相同的情况,读入所有区间,按照右端由小到大排序。然后通过维护splay进行第k小元素的查询操作。
    
     
      
       [cpp] 
       view plain
       copy
       print
       ?
       
       
      
     
     
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <algorithm>  
  4. using namespace std;  
  5. const int MAXN = 100005;  
  6. const int MAXM = 50005;  
  7. const int INF = 0x7FFFFFFF;  
  8.   
  9. class SplayTree  
  10.   
  11. public:  
  12.     SplayTree()  
  13.       
  14.         nil = &_nil;  
  15.         _nil.value = 0;  
  16.         _nil.size = 0;  
  17.         _nil.parent = nil;  
  18.         _nil.child[LEFT] = nil;  
  19.         _nil.child[RIGHT] = nil;  
  20.       
  21.   
  22.     inline void clear()  
  23.       
  24.         nodeNumber = 0;  
  25.         root = nil;  
  26.         insert(-INF);  
  27.         insert(INF);  
  28.       
  29.   
  30.     inline void insert(const int value)  
  31.       
  32.         if(root == nil)  
  33.           
  34.             root = newNode(nil, value);  
  35.             return;  
  36.           
  37.         Node *x = root;  
  38.         while(true)  
  39.           
  40.             int dir = x->value < value;  
  41.             if(x->child[dir] == nil)  
  42.               
  43.                 x->child[dir] = newNode(x, value);  
  44.                 update(x);  
  45.                 splay(x->child[dir], nil);  
  46.                 return;  
  47.               
  48.             else  
  49.               
  50.                 x = x->child[dir];  
  51.               
  52.           
  53.       
  54.   
  55.     inline void remove(const int value)  
  56.       
  57.         int k = find(value);  
  58.         find(k - 1, nil);  
  59.         find(k + 1, root);  
  60.         root->child[RIGHT]->child[LEFT] = nil;  
  61.         update(root->child[RIGHT]);  
  62.         update(root);  
  63.       
  64.   
  65.     inline int getKth(const int k)  
  66.       
  67.         find(k + 1, nil);  
  68.         return root->value;  
  69.       
  70.   
  71.     inline void print()  
  72.       
  73.         printf("Splay Tree: \\n");  
  74.         print(root);  
  75.         printf("\\n");  
  76.     private:  
  77.     static const int LEFT = 0;  
  78.     static const int RIGHT = 1;  
  79.     struct Node  
  80.       
  81.         int value, size;  
  82.         Node *parent, *child[2];  
  83.      _nil, node[MAXN];  
  84.     int nodeNumber;  
  85.     Node *root, *nil;  
  86.   
  87.     inline Node *newNode(Node *parent, const int value)  
  88.       
  89.         node[nodeNumber].value = value;  
  90.         node[nodeNumber].size = 1;  
  91.         node[nodeNumber].parent = parent;  
  92.         node[nodeNumber].child[LEFT] = nil;  
  93.         node[nodeNumber].child[RIGHT] = nil;  
  94.         return &node[nodeNumber++];  
  95.       
  96.   
  97.     inline void update(Node *x)  
  98.       
  99.         if(x == nil)  
  100.           
  101.             return;  
  102.           
  103.         x->size = x->child[LEFT]->size + x->child[RIGHT]->size + 1;  
  104.       
  105.   
  106.     inline void rotate(Node *x, const int dir)  
  107. splay tree

    伸展树(splay tree)

    POJ3468--A Simple Problem with Integers(Splay Tree)

    loj 104 普通平衡树splay

    Splay_Tree 模板(区间修改,旋转操作)

    LCT动态树入门