树:伸展树
来源:互联网 发布:微博关键词优化 编辑:程序博客网 时间:2024/05/11 21:17
我们知道AVL树为了保持严格的平衡,所以在数据插入上会呈现过多的旋转,影响了插入和删除的性能,此时AVL的一个变种,伸展树(Splay)就应运而生了,我们知道万事万物都遵循一个“八二原则“,也就是说80%的人只会用到20%的数据,比如说我们的“xx输入法”,平常打的字也就那么多,或许还没有20%呢。
在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置。于是想到设计一个简单方法, 在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方。伸展树应运而生。伸展树是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转把这个节点搬移到树根去。
它的优势在于不需要记录用于平衡树的冗余信息。
已知重构方法与伸展树的重构方法
先前,已经存在两种重构方法:
1、单旋:在查找完位于节点x中的条目i之后,旋转链接x和其父节点的边。(除非x就是树根)
2、搬移至树根:在查找完位于节点x中的条目i之后,旋转链接x和其父节点的边,然后重复这个操作直至x成为树根。
splay tree的重构方法和搬移至树根的方法相似,它也会沿着查找路径做自底向上的旋转,将被查找条目移至树根。但不同的是,它的旋转是成对进行的,顺序取决于查找路径的结构。为了在节点x处对树进行splay操作,我们需要重复下面的步骤,直至x成为树根为止:
1、第一种情况:如果x的父节点p(x)是树根,则旋转连接x和p(x)的边。(这种情况是最后一步)
2、第二种情况:如果p(x)不是树根,而且x和p(x)本身都是左孩子或者都是右孩子,则先旋转连接p(x)和x的祖父节点g(x)的边,然后再旋转连接x和p(x)的边。
3、第三种情况:如果p(x)不是树根,而且x是左孩子,p(x)是右孩子,或者相反,则先旋转连接x和p(x)的边,再旋转连接x和新的p(x)的边。
在节点x处进行splay操作的时间是和查找x所需的时间成比例的。splay操作不单是把x搬移到了树根,而且还把查找路径上的每个节点的深度都大致减掉了一半。
伸展树的优势
可靠的性能——它的平均效率不输于其他平衡树。
存储所需的内存少——伸展树无需记录额外的什么值来维护树的信息,相对于其他平衡树,内存占用要小。
由于Splay Tree仅仅是不断调整,并没有引入额外的标记,因而树结构与标准红黑树没有任何不同,从空间角度来看,它比Treap、SBT、AVL要高效得多。因为结构不变,因此只要是通过左旋和右旋进行的操作对Splay Tree性质都没有丝毫影响,因而它也提供了BST中最丰富的功能,包括快速的拆分和合并,并且实现极为便捷。这一点是其它结构较难实现的。其时间效率也相当稳定,和Treap基本相当,常数较高。
伸展树的缺点
伸展树最显著的缺点是它有可能会变成一条链。这种情况可能发生在以非降顺序访问n个元素之后。然而均摊的最坏情况是对数级的——O(logn)
参考:
http://www.cnblogs.com/huangxincheng/archive/2012/08/04/2623455.html
http://baike.baidu.com/link?url=HPLz0KKZv3zqYom5uJ_Lxmmzbfx6EDSyR9NjOh_EJOhf3k145NgrHyjp0nQW9y4NiEDp4_s2tMH4HCDWEJlasK
- 伸展树:双层伸展
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- 伸展树
- android 完全退出应用程序实现代码
- Redis中sentinel集群的搭建
- Java设计模式之--迭代器模式(Iterator)
- iOS TableView实现QQ好友列表
- 南阳宾馆管理系统
- 树:伸展树
- 深入浅出RxJava(一:基础篇)
- accessibilityservice 自动安装 取消删除安装包(二)
- eclipse内存溢出问题解决方案
- java 打印日志的几种方式
- Abstract&Interface 抽象类与接口
- IE浏览器下new Date('2016-06-23 12:12:12')初始化返回NaN
- oracle透明网关通过dblink连接slq server和mysql
- 在HANA里设置后台Job