学习跳跃表的过程中,发现现有的博客文章大部分只是给出了定义、插入删除操作、时间空间复杂度结论,没有清晰的证明。因此结合网易公开课上关于跳跃表的视频(http://open.163.com/movie/2010/12/7/S/M6UTT5U0I_M6V2TTJ7S.html),以及现有博客,整理出跳跃表的逻辑和相关证明。
- 产生动机
- 定义
- 跳跃表高度
- 跳跃表搜索时间复杂度
- 跳跃表空间复杂度
- 跳跃表插入删除时间复杂度
产生动机
我们知道,如果用有序数组进行二分查找(Binary Search),则用时为O(log n)。
但有序数组的问题是:
1.它的容量有限,不能插入比它更多的元素;
2.每次增加一个元素,需要O(n)的时间,这样花费很大
所以我们会选择用链表(Linked-List)来实现数据存储。但链表的问题是,因为只能进行线性搜索,查找耗时O(n)。
因此,我们希望一种存储方式,能够在链表上实现O(logn)的查找时间,当然传统的红黑树和AVL可以实现,但是其形式复杂,维持平衡的代价较大,而跳跃表与上述两者效率相当,但形式相对简单很多。
定义
关于定义部分可以看下网易公开课上的视频(越来纽约地铁就用到了跳跃表的思想。。),更容易理解。跳跃表的性质:
跳跃表由多条链构成(S0,S1,S2 ……,Sh),且满足如下三个条件:
- 每条链必须包含两个特殊元素:+∞ 和 -∞
- S0包含所有的元素,并且所有链中的元素按照升序排列。
- 每条链中的元素集合必须包含于序数较小的链的元素集合
跳跃表高度(期望)
对于每层的每个节点来说,它向上层增加的概率为1/2,因此对于包含n个元素的跳跃表,其第m层的期望节点数为n/(2^m),顶层元素为1,因此令n/(2^m)=1,可以得到:m=logn,即期望高度h=O(logn)。
跳跃表搜索时间复杂度(期望)
这一部分看了很多博客的介绍,感觉都讲的很清晰,这部分网易公开课讲的更好,因此在这里总结下。(敲公式太麻烦,直接上图吧。。)
注意:在跳跃表中,为了保证对每个元素的搜索效率,理想跳跃表的每一层的节点为均匀分布。
跳跃表的空间复杂度(期望)
因为跳跃表引入了概率的概念,即插入每一个节点时,通过抛硬币(概率为1/2)的方式来决定上一层是否添加该节点,当为正面则添加,然后继续抛硬币,直到抛到反面为止。因此,跳跃表的高度、空间复杂度、时间复杂度、搜索(插入/删除)等都是期望值。
对于每层的期待:第一层n,第二层n/2,第三层n/4,…,直到 n/2^log n=1。所以,总空间需求:
S = n + n/2 + n/2^2 + ... + n/2^log n < n(1 + 1/2 + 1/2^2 + ... + 1/2^∞) =2n
因此空间复杂度为O(n)
插入删除时间复杂度(期望)
因为查找的时间复杂度为O(logn),因此插入删除的时间复杂度也为O(logn)。
参考: