splay tree.java_伸展树--java

文字转载自:http://www.cnblogs.com/vamei

代码转载自:http://www.blogjava.net/javacap/archive/2007/12/19/168627.html

我们讨论过,树的搜索效率与树的深度有关。二叉搜索树的深度可能为n,这种情况下,每次搜索的复杂度为n的量级。AVL树通过动态平衡树的深度,单次搜索的复杂度为log(n) (以上参考纸上谈兵 AVL树)。我们下面看伸展树(splay tree),它对于m次连续搜索操作有很好的效率。

伸展树会在一次搜索后,对树进行一些特殊的操作。这些操作的理念与AVL树有些类似,即通过旋转,来改变树节点的分布,并减小树的深度。但伸展树并没有AVL的平衡要求,任意节点的左右子树可以相差任意深度。与二叉搜索树类似,伸展树的单次搜索也可能需要n次操作。但伸展树可以保证,m次的连续搜索操作的复杂度为mlog(n)的量级,而不是mn量级。

具体来说,在查询到目标节点后,伸展树会不断进行下面三种操作中的一个,直到目标节点成为根节点 (注意,祖父节点是指父节点的父节点)

1. zig: 当目标节点是根节点的左子节点或右子节点时,进行一次单旋转,将目标节点调整到根节点的位置。

0f60b9e14bb784633e5e6c160f6ac941.png

zig

2. zig-zag: 当目标节点、父节点和祖父节点成"zig-zag"构型时,进行一次双旋转,将目标节点调整到祖父节点的位置。

c7f27b26858d1da3e2ca35b4f3904cf0.png

zig-zag

3. zig-zig:当目标节点、父节点和祖父节点成"zig-zig"构型时,进行一次zig-zig操作,将目标节点调整到祖父节点的位置。

046f480fd64766a09ca28da5103fc017.png

zig-zig

单旋转操作和双旋转操作见AVL树。下面是zig-zig操作的示意图:

c3b764bdeeb10f166f55add9a24ddbfb.png

zig-zig operation

在伸展树中,zig-zig操作(基本上)取代了AVL树中的单旋转。通常来说,如果上面的树是失衡的,那么A、B子树很可能深度比较大。相对于单旋转(想一下单旋转的效果),zig-zig可以将A、B子树放在比较高的位置,从而减小树总的深度。

下面我们用一个具体的例子示范。我们将从树中搜索节点2:

728f88566b65bdcd13bbf21e9cfb480b.png

Original

3676680ea3cbe9326ac7946604fce771.png

zig-zag (double rotation)

7cae8c6dca92ad897788361b532c1888.png

zig-zig

d233521b023e62de8d2c882638a1d94e.png

zig (single rotation at root)

上面的第一次查询需要n次操作。然而经过一次查询后,2节点成为了根节点,树的深度大减小。整体上看,树的大部分节点深度都减小。此后对各个节点的查询将更有效率。

伸展树的另一个好处是将最近搜索的节点放在最容易搜索的根节点的位置。在许多应用环境中,比如网络应用中,某些固定内容会被大量重复访问(比如江南style的MV)。伸展树可以让这种重复搜索以很高的效率完成。

java代码:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagealgorithms.tree;/***@authoryovn

**/

public class SplayTree> extends DefaultBSTree implements BSTree{static class SplayTreeNode> extends BSTNode{

SplayTreeNodeparent;

SplayTreeNode(SplayTreeNodeparent,E key) {super(key);this.parent=parent;

}

}

@Overridepublic booleandelete(E ele) {return _delete((SplayTreeNode)root,ele);

}private boolean _delete(SplayTreeNodepointer, E ele) {int cmp=ele.compareTo(pointer.key);while(cmp!=0)

{if(cmp<0)

{

pointer=(SplayTreeNode)pointer.left;

}else{

pointer=(SplayTreeNode)pointer.right;

}if(pointer==null)return false;

cmp=ele.compareTo(pointer.key);

}//okay find it

SplayTreeNode p=pointer.parent;if(pointer.left==null)

{if(p!=null)

{

keep_right(pointer);

splay(p);

}else{

root=p.right;if(root!=null)((SplayTreeNode)root).parent=null;

}

}else if(pointer.right==null)

{if(p!=null)

{

keep_left(pointer);

splay(p);

}else{

root=p.left;if(root!=null)((SplayTreeNode)root).parent=null;

}

}else{

SplayTreeNode todo=(SplayTreeNode)pointer.left;

SplayTreeNode todoP=null;while(todo.right!=null)

{

todoP=todo;

todo=(SplayTreeNode)todo.right;

}

pointer.key=todo.key;if (todoP != null) {

todoP.right=todo.left;if (todo.left != null)

((SplayTreeNode) todo.left).parent =todoP;

}else{

pointer.left=null;

}

splay(pointer.parent);

}return true;

}private void keep_left(SplayTreeNodepointer) {

SplayTreeNode p=pointer.parent;if(p.left==pointer)

{

p.left=pointer.left;if(p.left!=null)((SplayTreeNode)p.left).parent=p;

}else if(p.right==pointer)

{

p.right=pointer.left;if(p.right!=null)((SplayTreeNode)p.right).parent=p;

}

}private void keep_right(SplayTreeNodepointer) {

SplayTreeNode p=pointer.parent;if(p.left==pointer)

{

p.left=pointer.right;if(p.left!=null)((SplayTreeNode)p.left).parent=p;

}else if(p.right==pointer)

{

p.right=pointer.right;if(p.right!=null)((SplayTreeNode)p.right).parent=p;

}

}protected void splay(SplayTreeNodecur) {if(cur==null)return;while(cur!=root)

{if(cur.parent==root)

{//single Rotation

SingleRotation(cur,cur.parent);

cur.parent=null;

root=cur;

}else if(cur.parent.left==cur&&cur.parent.parent.left==cur.parent)

{

cur=Left_ZigZig(cur,cur.parent,cur.parent.parent);

}else if(cur.parent.right==cur&&cur.parent.parent.right==cur.parent)

{

cur=Right_ZigZig(cur,cur.parent,cur.parent.parent);

}else if(cur.parent.left==cur&&cur.parent.parent.right==cur.parent)

{

cur=RL_ZigZag(cur,cur.parent,cur.parent.parent);

}else if(cur.parent.right==cur&&cur.parent.parent.left==cur.parent)

{

cur=LR_ZigZag(cur,cur.parent,cur.parent.parent);

}else{

System.out.println("Oooops!!!");

}

}

}private SplayTreeNode LR_ZigZag(SplayTreeNodecur,

SplayTreeNode p, SplayTreeNodeg) {

SplayTreeNode gp=g.parent;

g.left=cur.right;

setParent(cur.right,g);

g.parent=cur;

cur.right=g;

p.right=cur.left;

setParent(cur.left,p);

p.parent=cur;

cur.left=p;if(gp!=null)

{if(gp.left==g)

{

gp.left=cur;

}else{

gp.right=cur;

}

}else root=cur;

cur.parent=gp;returncur;

}private SplayTreeNode RL_ZigZag(SplayTreeNodecur,

SplayTreeNode p, SplayTreeNodeg) {

SplayTreeNode gp=g.parent;

g.right=cur.left;

setParent(cur.left,g);

g.parent=cur;

cur.left=g;

p.left=cur.right;

setParent(cur.right,p);

p.parent=cur;

cur.right=p;if(gp!=null)

{if(gp.left==g)

{

gp.left=cur;

}else{

gp.right=cur;

}

}else root=cur;

cur.parent=gp;returncur;

}protected SplayTreeNode Right_ZigZig(SplayTreeNode cur, SplayTreeNodep,

SplayTreeNodeg) {

SplayTreeNode gp=g.parent;

g.right=p.left;

setParent(p.left,g);

p.right=cur.left;

setParent(cur.left,p);

g.parent=p;

p.left=g;

p.parent=cur;

cur.left=p;if(gp!=null)

{if(gp.left==g)

{

gp.left=cur;

}else{

gp.right=cur;

}

}else root=cur;

cur.parent=gp;returncur;

}protected SplayTreeNode Left_ZigZig(SplayTreeNode cur, SplayTreeNodep,

SplayTreeNodeg) {

SplayTreeNode gp=g.parent;

g.left=p.right;

setParent(p.right,g);

g.parent=p;

p.right=g;

p.left=cur.right;

setParent(cur.right,p);

p.parent=cur;

cur.right=p;if(gp!=null)

{if(gp.left==g)

{

gp.left=cur;

}else{

gp.right=cur;

}

}else root=cur;

cur.parent=gp;returncur;

}final void setParent(BSTNode c, BSTNodep) {if(c!=null)((SplayTreeNode)c).parent=(SplayTreeNode)p;

}private void SingleRotation(SplayTreeNode cur, SplayTreeNodep) {if(p.left==cur)

{

p.left=cur.right;if(cur.right!=null)((SplayTreeNode)cur.right).parent=p;

cur.right=p;

p.parent=cur;

}else if(p.right==cur)

{

p.right=cur.left;if(cur.left!=null)((SplayTreeNode)cur.left).parent=p;

cur.left=p;

p.parent=cur;

}

}

@Overridepublic voidinsert(E ele) {if (root == null) {

root= new SplayTreeNode(null,ele);return;

}

_insert((SplayTreeNode)root,ele);

}private final void _insert(SplayTreeNodepointer,E ele)

{int cmp=pointer.key.compareTo(ele);if(cmp==0)

{throw newIllegalArgumentException();

}if(cmp>0)

{if(pointer.left==null)

{

pointer.left=new SplayTreeNode(pointer,ele);

splay((SplayTreeNode)pointer.left);return;

}

_insert((SplayTreeNode)pointer.left,ele);

}else{if(pointer.right==null)

{

pointer.right=new SplayTreeNode(pointer,ele);

splay((SplayTreeNode)pointer.right);return;

}

_insert((SplayTreeNode)pointer.right,ele);

}

}

@Overridepublic booleansearch(E ele) {return _search((SplayTreeNode)root,ele);

}private boolean _search(SplayTreeNodepointer, E ele) {if(pointer==null)return false;int cmp=pointer.key.compareTo(ele);if(cmp==0)

{

splay(pointer);return true;

}if(cmp>0)

{return _search((SplayTreeNode)pointer.left,ele);

}else{return _search((SplayTreeNode)pointer.right,ele);

}

}/****/

publicSplayTree() {

}

}

伸展树java代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值