Splay Tree - JoishBadeR - Holy Sh*t

Splay Tree

JoishBadeR posted @ 2014年4月09日 09:26 in 奇怪的数据结构 , 543 阅读

个人复习用品

 

不喜勿喷,右(左)上有叉号,点好

 

 

从前有一种树叫做伸展树

 

每次操作复杂度均摊O(logN),证明略

有几种旋转操作都可以使其保持平衡。第一种是ZigZag,第二种是Rotate。

这里介绍一下Rotate

 

void Rotate(int x, int w)
{
	Pushdown(p[p[x]]); Pushdown(p[x]);
	int i = p[x], y = kind[i], cc = p[i]; 
	p[x] = cc; if((kind[x] = y) != 3) son[cc][y] = x;
	p[son[i][w] = cc = son[x][y = 3 - w]] = i; kind[cc] = w;
	son[p[i] = x][kind[i] = y] = i;
	Update(i);
}

void Splay(int x, int y)
{
	Pushdown(x);
	while(p[x] != y)
	{
		int a = kind[x], i = p[x], b = kind[i];
		if(p[i] == y) { Rotate(x, a); break; }
		if(a == b) Rotate(i, a); else Rotate(x, a); Rotate(x, b);
	}
	Update(x); if(y == 0) Root = x;
}

 

Rotate(x, w)的意义是将x左(w = 2时)或右(w = 1时)旋

每次旋转时影响三代的结点,先下传x的爷爷的标记,再下传x的父亲的标记

用i记录x的父亲,y记录i的属性,cc记录x的爷爷

x的父亲更改为cc,x的属性更改为i的属性

如果cc不是虚拟根,那么把cc的儿子记录为x

如果是左旋,i显然会变成x的右儿子,x的右儿子会被i当做左儿子接受

如果是右旋,i显然会变成x的左儿子,x的左儿子会被i当做右儿子接受

所以在x的左(右)旋意义下,此时y赋值为右(左)旋属性(3-w),i的左(右)儿子赋值为用cc记录的x的右(左)儿子,cc属性记录为左(右)旋属性(w)。最后处理i,i的父亲变更为x,i的属性变更为y,x的儿子赋值为i,更新一下i的键值。

 

Splay(x, y)的意义是将x旋转到y下。

Splay(x, y)前,需要将x的标记下传,然后每次用a记录x的属性(1为左儿子,2为右儿子),i记录x的父亲,b记录i的属性

如果x的爷爷就是y了,那么只需要将x进行Rotate(x, a)就可以把x旋转到y下了

如果x,i都在一条直线上,那么只需要先将i旋转,x再进行相同的旋转就行了

如果不是的话,需要将x进行相应的旋转,此时x代替了i的位置,x也继承了i的属性,只需要再将x进行相应的i属性的旋转就行了

 


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter
Host by is-Programmer.com | Power by Chito 1.3.3 beta | © 2007 LinuxGem | Design by Matthew "Agent Spork" McGee