伸展树(Splay)复杂度证明
本文用势能法证明\(Splay\)的均摊复杂度,对\(Splay\)的具体操作不进行讲述。
为了方便本文的描述,定义如下内容:
在文中我们用\(T\)表示一棵完整的\(Splay\),并(不严谨地)用\(|T|\)表示\(T\)这棵\(Splay\)的节点数目。
如无特殊说明,小写英文字母(如\(x\),\(y\),\(z\))在本文中表示\(T\)的一个节点,并(不严谨地)用\(|x|\)表示以节点\(x\)为根的子树的大小,\(x\in T\)表示节点\(x\)在\(T\)中。
一般我们默认\(x'\)代表节点\(x\)在经过了上下文中描述的操作以后的状态,因此对应的\(x\)代表之前的状态。
我们用\(\Phi(T)\)表示整棵\(Splay\)的势能函数,\(\phi(x)\)则表示节点\(x\)对\(T\)贡献的势能。
=============================================
先来讲一下我们的势能函数,我们定义:
\[\phi(x)=\log|x|\]
\[\Phi(T)=\sum_{x\in T}\phi(x)\]
可以发现,对于任意时刻,因为\(|x|\geq 1\),因此\(\log|x|\geq 0\),从而得到\(\Phi(T)\geq 0\),因此势能函数是合法的。同时\(\forall |x|\leq |T|\),因此我们总有\(\Phi(T)\leq |T|\log|T|\)。这个上界是比较松的,但是对我们的分析没有影响。
下面考虑一次伸展操作对于势能函数的影响。由于我们可以把从根向下查找的代价计算到伸展过程中对应的旋转操作上,此时旋转操作复杂度不变,只是常数增大,从而忽略了查找对复杂度的影响。我们可以简单地通过增大势的单位来支配隐藏在操作中的常数。因此我们只需证明对于一次伸展操作的所有旋转操作,其复杂度是均摊\(O(\log|T|)\)的,我们就完成了对\(Splay\)复杂度的证明。
\(1\)、\(zig\)操作
由于\(zag\)操作与\(zig\)相似,因此只需要证明\(zig\)即可。
假设我们\(zig\)的对象是\(x\),其父亲为\(y\),显然在旋转以后,只有\(x\)和\(y\)的子树大小发生了变化。因此势能变化量为:
\[\Delta\Phi(T)=\phi(x')+\phi(y')-\phi(x)-\phi(y)\]
显然\(\phi(x')=\phi(y)\),且\(\phi(x')\geq \phi(y')\),因此消去\(\phi(x')\)与\(\phi(y)\),并将\(\phi(y')\)替换为\(\phi(x')\),有:
\[\Delta\Phi(T)\leq \phi(x')-\phi(x)\]
因此\(zig\)操作的均摊代价为\(O(1+\phi(x')-\phi(x))\),其中\(O(1)\)代表旋转操作本身的复杂度,而在一次伸展操作中也只会有一次\(zig\)操作,因此这额外的\(O(1)\)代价不会对分析造成影响,因此我们可以只关心其中的\(O(\phi(x')-\phi(x))\)。
\(2\)、\(zig-zig\)操作
由于\(zag-zag\)操作与\(zig-zig\)相似,因此只需要证明\(zig-zig\)即可。
假设我们\(zig-zig\)的对象是\(x\),其父亲为\(y\),其祖父为\(z\),与\(zig\)操作类似,势能变化量为:
\[\Delta\Phi(T)=\phi(x')+\phi(y')+\phi(z')-\phi(x)-\phi(y)-\phi(z)\]
同样地,由于\(\phi(x')=\phi(z)\),因此将它们消去:
\[\Delta\Phi(T)=\phi(y')+\phi(z')-\phi(x)-\phi(y)\]
而我们又有\(\phi(x')\geq \phi(y')\),\(\phi(x)\leq \phi(y)\),因此有:
\[\Delta\Phi(T)\leq \phi(x')+\phi(z')-2\phi(x)\]
推到这里,我们先来做一个小工作,来证明\(\phi(x)+\phi(z')-2\phi(x')\)(注意与上面的式子不一样)的值不大于\(-1\)。
假设\(|x|=a\),\(|z'|=b\),那么我们有:
\[\phi(x)+\phi(z')-2\phi(x')=\log|x|+\log|z'|-2\log|x'|\]
我们将\(\log\)合并,得到:
\[\phi(x)+\phi(z')-2\phi(x')=\log(\frac{|x||z'|}{|x'|^2})\]
由于\(|x'|\geq a+b\)(可以结合旋转过程思考一下),而\(\log\)是单调的,因此:
\[\phi(x)+\phi(z')-2\phi(x')\leq \log(\frac{ab}{(a+b)^2})\leq \log(\frac{ab}{2ab})\leq -1\]
证明完毕。现在我们已经知道\(zig-zig\)操作的摊还代价不大于:
\[O(1)+\phi(x')+\phi(z')-2\phi(x)\]
其中\(O(1)\)为旋转操作的复杂度。由于之前的推导我们可以知道\(\phi(x)+\phi(z')-2\phi(x')\leq -1\),因此\(-1-(\phi(x)+\phi(z')-2\phi(x'))\geq 0\),我们在摊还代价上加上这个非负数得到:
\[O(1)+\phi(x')+\phi(z')-2\phi(x)-1-(\phi(x)+\phi(z')-2\phi(x'))\]
化简一下,就得到:
\[O(1)+O(\phi(x')-\phi(x))-1\]
通过增大我们刚刚加的那个非负数以及势的单位,我们就可以支配隐藏在\(O(1)\)中的常数,因此一次\(zig-zig\)操作的摊还代价为:
\[O(\phi(x')-\phi(x))\]
\(3\)、\(zig-zag\)操作
分析的过程和\(zig-zig\)操作完全一样,之前分析用到的所有性质此时仍然适用,因此略过分析过程。其摊还代价依然为:
\[O(\phi(x')-\phi(x))\]
\(4\)、总结
综上所述,除了最后一次旋转可能增加\(O(1)\)的代价以外,其余操作的摊还代价只和我们伸展的对象\(x\)的势有关。我们假设旋转操作一共执行了\(n\)次,并用\(x_i\)来表示节点\(x\)在经过\(i\)次旋转后的状态,那么整一个伸展操作的摊还代价就为:
\[O\Big(1+\sum_{i=1}^n\phi(x_i)-\phi(x_{i-1})\Big)\]
显然除了\(\phi(x_n)\)与\(\phi(x_0)\)外,所有的势都被抵消了,因此摊还代价为:
\[O(1+\phi(x_n)-\phi(x_0))\]
至此,我们不必关心\(\phi(x_0)\)的值了。此时\(x_n\)是整棵\(Splay\)的根,因此\(\phi(x_n)=\log|T|\)。我们成功的证明了一次伸展操作的摊还代价为\(O(\log|T|)\)。
伸展树(Splay)复杂度证明的更多相关文章
- 纸上谈兵: 伸展树 (splay tree)[转]
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我们讨论过,树的搜索效率与树的深度有关.二叉搜索树的深度可能为n,这种情况下,每 ...
- K:伸展树(splay tree)
伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它能在O(lgN)内完成插入.查找和删除操作.在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使 ...
- 高级搜索树-伸展树(Splay Tree)
目录 局部性 双层伸展 查找操作 插入操作 删除操作 性能分析 完整源码 与AVL树一样,伸展树(Splay Tree)也是平衡二叉搜索树的一致,伸展树无需时刻都严格保持整棵树的平衡,也不需要对基本的 ...
- 树-伸展树(Splay Tree)
伸展树概念 伸展树(Splay Tree)是一种二叉排序树,它能在O(log n)内完成插入.查找和删除操作.它由Daniel Sleator和Robert Tarjan创造. (01) 伸展树属于二 ...
- [Splay伸展树]splay树入门级教程
首先声明,本教程的对象是完全没有接触过splay的OIer,大牛请右上角.. 首先引入一下splay的概念,他的中文名是伸展树,意思差不多就是可以随意翻转的二叉树 PS:百度百科中伸展树读作:BoGa ...
- 伸展树(Splay tree)的基本操作与应用
伸展树的基本操作与应用 [伸展树的基本操作] 伸展树是二叉查找树的一种改进,与二叉查找树一样,伸展树也具有有序性.即伸展树中的每一个节点 x 都满足:该节点左子树中的每一个元素都小于 x,而其右子树中 ...
- 【BBST 之伸展树 (Splay Tree)】
最近“hiho一下”出了平衡树专题,这周的Splay一直出现RE,应该删除操作指针没处理好,还没找出原因. 不过其他操作运行正常,尝试用它写了一道之前用set做的平衡树的题http://codefor ...
- 伸展树Splay【非指针版】
·伸展树有以下基本操作(基于一道强大模板题:codevs维护队列): a[]读入的数组;id[]表示当前数组中的元素在树中节点的临时标号;fa[]当前节点的父节点的编号;c[][]类似于Trie,就是 ...
- ZOJ 3765 Lights (zju March I)伸展树Splay
ZJU 三月月赛题,当时见这个题目没辙,没学过splay,敲了个链表TLE了,所以回来好好学了下Splay,这道题目是伸展树的第二题,对于伸展树的各项操作有了更多的理解,这题不同于上一题的用指针表示整 ...
- [数据结构]伸展树(Splay)
#0.0 写在前面 Splay(伸展树)是较为重要的一种平衡树,理解起来也依旧很容易,但是细节是真的多QnQ,学一次忘一次,还是得用博客加深一下理解( #1.0 Splay! #1.1 基本构架 Sp ...
随机推荐
- 20155321 《网络攻防》 Exp9 Web安全基础
20155321 <网络攻防> Exp9 Web安全基础 基础问题 SQL注入攻击原理,如何防御 原理:在事先定义好的SQL语句的结尾上添加额外的SQL语句(感觉一般是或上一个永真式),以 ...
- [转]JVM系列三:JVM参数设置、分析
不管是YGC还是Full GC,GC过程中都会对导致程序运行中中断,正确的选择不同的GC策略,调整JVM.GC的参数,可以极大的减少由于GC工作,而导致的程序运行中断方面的问题,进而适当的提高Java ...
- vue初学实践之路——vue简单日历组件(3)
这一篇我们来实现管理员修改每一天剩余数量的功能. <div id="calendar"> <div id="left"> <spa ...
- 如何使用URLOS进行docker应用开发
使用Docker技术可以帮助企业快速水平扩展服务,从而到达弹性部署业务的能力.在云服务概念兴起之后,Docker的使用场景和范围进一步发展,如今在微服务架构越来越流行的情况下,微服务+Docker的完 ...
- B1015 德才论 (25 分)
19/25 #include<bits/stdc++.h> using namespace std; /* 1.de>=H && cai>=H 2.de> ...
- BugPhobia沟通篇章:Solr模式配置与数据导入调研
0x01 :Scrum Meeting特别说明 特别说明,考虑到编译原理课程考核的时间安排,每天开发时间急剧缩短以至于难以维系正常的Scrum Meeting,因此,将2015/12/13 00:00 ...
- 电梯V1.0
电梯V1.0 GitHub仓库地址 Problem 一栋3层的大楼(楼层编号0-2),设有一台无限载重的电梯,初始时电梯停在0层.电梯移动1层的耗时为1,在某一层停靠的耗时为1(时间初始为0).电梯不 ...
- Alpha 答辩总结
前言 作业发布 组长 成员 贡献比例 ★ 530 雨勤 23% 311 旭 23% 403 俊 18% 223 元 23% 437 海辉 13% 10天 Alpha 冲刺站立会议博客链接汇总 Alph ...
- NetFPGA Demo ——reference_nic_nf1_cml
NetFPGA Demo --reference_nic_nf1_cml 实验平台 OS:deepin 15.4 开发板:NetFPGA_1G_CML 实验过程 从NetFPGA-1G-CML从零开始 ...
- Photoshop一些常用的快捷键
1.按住Alt键,点击图层上的小眼睛,只显示当前图层 2.新建纯色图层,抠图 3.Fn+ num 调整不透明度 4.Shift + num 调整流量 5.调整图层透明度,在移动工具状态下,输入数字:0 ...