Splay tree
类别:二叉排序树
时间效率:O(log n)内完成插入、查找、删除操作
伸展树的另一个好处是将最近搜索的节点放在最容易搜索的根节点的位置。在许多应用环境中,比如网络应用中,某些固定内容会被大量重复访问(比如江南style的MV)。伸展树可以让这种重复搜索以很高的效率完成。
注:所有图片来自wiki。
Tree Rotation

Splaying
- 节点x是父节点p的左孩子还是右孩子
- 节点p是不是根节点,如果不是
- 节点p是父节点g的左孩子还是右孩子
Zig Step

Zig-Zig Step

Zig-Zag Step

应用
POJ2764 Feed the dogs
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100005;
const int MAXM = 100005;
const int INF = 0x7fffffff;
class SplayTree
{
public:
SplayTree()
{
nil.size = 0;
nil.value = INF;
nil.min = INF;
nil.lchild = &nil;
nil.rchild = &nil;
nil.parent = &nil;
}
inline void make(int array[], int n)
{
nodeNumber = 0;
int mid = (n - 1) >> 1;
root = newNode(&nil, array[mid]);
root->lchild = make(0, mid - 1, root, array);
root->rchild = make(mid + 1, n - 1, root, array);
update(root);
}
inline void ADD(int x, int y, int D)
{
find(x, &nil);
find(y + 2, root);
root->rchild->lchild->lazy += D;
}
inline void REVERSE(int x, int y)
{
find(x, &nil);
find(y + 2, root);
root->rchild->lchild->isReverse ^= true;
}
inline void REVOLVE(int x, int y, int T)
{
int len = y - x + 1;
T = ((T % len) + len) % len;
if(T)
{
find(y - T + 1, &nil);
find(y + 2, root);
SplayNode *d = root->rchild->lchild;
root->rchild->lchild = &nil;
find(x, &nil);
find(x + 1, root);
root->rchild->lchild = d;
d->parent = root->rchild;
}
}
inline void INSERT(int x, int P)
{
find(x + 1, &nil);
find(x + 2, root);
root->rchild->lchild = newNode(root->rchild, P);
}
inline void DELETE(int x)
{
find(x, &nil);
find(x + 2, root);
root->rchild->lchild = &nil;
}
inline void MIN(int x, int y)
{
find(x, &nil);
find(y + 2, root);
pushdown(root->rchild->lchild);
printf("%d\n", root->rchild->lchild->min);
}
inline void print()
{
printf("Splay Linear: \n");
print(root);
printf("\n");
}
inline void prints()
{
printf("Splay Structure: \n");
prints(root);
printf("\n");
}
private:
struct SplayNode
{
int value, size, lazy;
SplayNode *parent, *lchild, *rchild;
int min;
bool isReverse;
} nil, node[MAXN + MAXM];
int nodeNumber;
SplayNode *root;
inline SplayNode *newNode(SplayNode *parent, const int value)
{
node[nodeNumber].value = value;
node[nodeNumber].size = 1;
node[nodeNumber].lazy = 0;
node[nodeNumber].parent = parent;
node[nodeNumber].lchild = &nil;
node[nodeNumber].rchild = &nil;
node[nodeNumber].min = value;
node[nodeNumber].isReverse = false;
return &node[nodeNumber++];
}
SplayNode *make(int l, int r, SplayNode *parent, int array[])
{
if(l > r)
{
return &nil;
}
int mid = (l + r) >> 1;
SplayNode *x = newNode(parent, array[mid]);
x->lchild = make(l, mid - 1, x, array);
x->rchild = make(mid + 1, r, x, array);
update(x);
return x;
}
inline void update(SplayNode *x)
{
if(x == &nil)
{
return;
}
x->size = x->lchild->size + x->rchild->size + 1;
x->min = min(x->value, min(x->lchild->min, x->rchild->min));
}
inline void pushdown(SplayNode *x)
{
if(x == &nil)
{
return;
}
if(x->isReverse)
{
swap(x->lchild, x->rchild);
x->lchild->isReverse ^= true;
x->rchild->isReverse ^= true;
x->isReverse = false;
}
if(x->lazy)
{
x->value += x->lazy;
x->min += x->lazy;
x->lchild->lazy += x->lazy;
x->rchild->lazy += x->lazy;
x->lazy = 0;
}
}
inline void rotateLeft(SplayNode *x)
{
SplayNode *p = x->parent;
pushdown(x->lchild);
pushdown(x->rchild);
pushdown(p->lchild);
p->rchild = x->lchild;
p->rchild->parent = p;
x->lchild = p;
x->parent = p->parent;
if(p->parent->lchild == p)
{
p->parent->lchild = x;
}
else
{
p->parent->rchild = x;
}
p->parent = x;
update(p);
update(x);
if(root == p)
{
root = x;
}
}
inline void rotateRight(SplayNode *x)
{
SplayNode *p = x->parent;
pushdown(x->lchild);
pushdown(x->rchild);
pushdown(p->rchild);
p->lchild = x->rchild;
p->lchild->parent = p;
x->rchild = p;
x->parent = p->parent;
if(p->parent->lchild == p)
{
p->parent->lchild = x;
}
else
{
p->parent->rchild = x;
}
p->parent = x;
update(p);
update(x);
if(root == p)
{
root = x;
}
}
inline void splay(SplayNode *x, SplayNode *y)
{
pushdown(x);
while(x->parent != y)
{
if(x->parent->parent == y)
{
if(x->parent->lchild == x)
{
rotateRight(x);
}
else
{
rotateLeft(x);
}
}
else if(x->parent->parent->lchild == x->parent)
{
if(x->parent->lchild == x)
{
rotateRight(x->parent);
rotateRight(x);
}
else
{
rotateLeft(x);
rotateRight(x);
}
}
else
{
if(x->parent->rchild == x)
{
rotateLeft(x->parent);
rotateLeft(x);
}
else
{
rotateRight(x);
rotateLeft(x);
}
}
}
update(x);
}
inline void find(int k, SplayNode *y)
{
SplayNode *x = root;
pushdown(x);
while(k != x->lchild->size + 1)
{
if(k <= x->lchild->size)
{
x = x->lchild;
}
else
{
k -= x->lchild->size + 1;
x = x->rchild;
}
pushdown(x);
}
splay(x, y);
}
inline void print(SplayNode *x)
{
if(x == &nil)
{
return;
}
pushdown(x);
print(x->lchild);
printf("%d: %d %d %d %d\n", x->value, x->min, x->parent->value, x->lchild->value, x->rchild->value);
print(x->rchild);
}
inline void prints(SplayNode *x)
{
if(x == &nil)
{
return;
}
pushdown(x);
if(x->value == INF)
{
printf("INF : ");
}
else
{
printf("%d : ", x->value);
}
if(x->lchild == &nil)
{
printf("nil ");
}
else
{
if(x->lchild->value == INF)
{
printf("INF ");
}
else
{
printf("%d ", x->lchild->value);
}
}
if(x->rchild == &nil)
{
printf("nil\n");
}
else
{
if(x->rchild->value == INF)
{
printf("INF\n");
}
else
{
printf("%d\n", x->rchild->value);
}
}
prints(x->lchild);
prints(x->rchild);
}
} splayTree;
char buffer[128];int array[MAXN];int n, m;
int main()
{
int x, y, D, T, P;
scanf("%d", &n);
for(int i=1;i<=n;++i)
{
scanf("%d", &array[i]);
}
array[0] = INF;
array[n+1] = INF;
splayTree.make(array, n + 2);
scanf("%d", &m);
while(m--)
{
scanf("%s", buffer);
switch(buffer[0])
{
case 'A':
scanf("%d%d%d", &x, &y, &D);
splayTree.ADD(x, y, D);
break;
case 'R':
if('E' == buffer[3])
{
scanf("%d%d", &x, &y);
splayTree.REVERSE(x, y);
}
else
{
scanf("%d%d%d", &x, &y, &T);
splayTree.REVOLVE(x, y, T);
}
break;
case 'I':
scanf("%d%d", &x, &P);
splayTree.INSERT(x, P);
break;
case 'D':
scanf("%d", &x);
splayTree.DELETE(x);
break;
case 'M':
scanf("%d%d", &x, &y);
splayTree.MIN(x, y);
break;
}
}
return 0;
}
Splay tree的更多相关文章
- 纸上谈兵:伸展树(splay tree)
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我们讨论过,树的搜索效率与树的深度有关.二叉搜索树的深度可能为n,这种情况下,每次 ...
- bzoj 3223/tyvj 1729 文艺平衡树 splay tree
原题链接:http://www.tyvj.cn/p/1729 这道题以前用c语言写的splay tree水过了.. 现在接触了c++重写一遍... 只涉及区间翻转,由于没有删除操作故不带垃圾回收,具体 ...
- 伸展树 Splay Tree
Splay Tree 是二叉查找树的一种,它与平衡二叉树.红黑树不同的是,Splay Tree从不强制地保持自身的平衡,每当查找到某个节点n的时候,在返回节点n的同时,Splay Tree会将节点n旋 ...
- [转] Splay Tree(伸展树)
好久没写过了,比赛的时候就调了一个小时,差点悲剧,重新复习一下,觉得这个写的很不错.转自:here Splay Tree(伸展树) 二叉查找树(Binary Search Tree)能够支持多种动态集 ...
- 树-伸展树(Splay Tree)
伸展树概念 伸展树(Splay Tree)是一种二叉排序树,它能在O(log n)内完成插入.查找和删除操作.它由Daniel Sleator和Robert Tarjan创造. (01) 伸展树属于二 ...
- HDU-3436 Queue-jumpers 树状数组 | Splay tree删除,移动
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3436 树状数组做法<猛戳> Splay tree的经典题目,有删除和移动操作.首先要离散化 ...
- HDU1890 Robotic Sort Splay tree反转,删除
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890 题目中涉及数的反转和删除操作,需要用Splay tree来实现.首先对数列排序,得到每个数在数列 ...
- POJ-3468 A Simple Problem with Integers Splay Tree区间练习
题目链接:http://poj.org/problem?id=3468 以前用线段树做过,现在用Splay Tree A了,向HH.kuangbin.cxlove大牛学习了各种Splay各种操作,,, ...
- Splay Tree的删除操作
Splay Tree的插入操作,搜索操作,和删除操作都实现了,那么就能够使用来解题了. 指针的删除操作的处理还是那么难的,非常多坎须要避开. 同一个坎还是坑了我好多次,就是指针传递的问题,什么时候须要 ...
随机推荐
- PHP中的empty()和isset()的比较
- HW4.36
import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner i ...
- POJ-3648 Wedding 2sat
题目链接:http://poj.org/problem?id=3648‘ 题意:一对情人举行婚礼,有n对夫妇参加,别人对着坐在一个长桌子的两边,新娘和新郎坐在最后面,新娘只能看见坐在他对面的人.现在, ...
- iOS 开发 NSLog调试小技巧
NSLog其实是一个非常损耗性能的东西,当你在开发了很长时间的一个项目中,想必为了方便调试,里面会有很多的NSLog输出,为了优化性能,同时又方便调试,可以在pch中定义一个宏,既可以替换原有的NSL ...
- Kali无法定位软件包的解决方案
异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 以前遇到过,后来好久没碰Linux了,忘记了.之后上网搜了一下....呃,发现解 ...
- ActiveMQ, Qpid, HornetQ and RabbitMQ in Comparison
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- 深入理解JavaScript系列+ 深入理解javascript之执行上下文
http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html http://blog.csdn.net/hi_kevin/article/d ...
- MantisBT
官方网站:http://www.mantisbt.org/ MantisBT is a free popular web-based bugtracking system (feature list) ...
- cocos2d-x 2.1.4学习笔记01:windows平台搭建cocos2d-x开发环境
cocos2d-x的大致开发流程是,首先使用win32版进行代码编写并完成游戏,然后将代码迁移到对应的开发环境上进行交叉编译完成游戏打包,如iphone上是mac+xcode,android是ecli ...
- Servlet中的转发
public class OneServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServ ...