跳跃表原理和实战

一 跳跃表的引入

对有序顺序表可以采用二分查找,查找的时间复杂度为O (logn),插入、删除的时间复杂度为 O(n )。但是对有序链表不可以采用二分查找,查找、插入和删除的时间复杂度均为O (n)。

有序链表如下图所示,若查找 8,则必须从第 1 个节点开始,依次比较 8 次才能查找成功。

如何利用链表的有序性来提高查找效率?如何在一个有序链表中进行二分查找?若增加一级索引,把奇数位序作为索引,则如下图所示,若查找 8,则可以先从索引进行比较,依次比较 1、3、5、7、9,8 比 7 大但比 9 小,7 向下一层,继续向后比较,比较 6 次即可查找成功。

若再增加一级索引,把索引层的奇数位序作为索引,则如下图所示,若查找 7,则可以先从索引开始比较,依次 1、5、9,7 比 5 大但比 9 小,5 向下一层,继续向后比较,比较 4 次即可查找成功。

在增加两级索引后,若查找 5,则比较两次即可查找成功;若查找比 5 大的数,则以 5 为界向后查找;若查找比 5 小的数,则以 5 为界向前查找。这就是一个可进行二分查找的有序链表。

二 算法分析

若有 n 个元素,则增加 h 级索引后的数据结构如下图所示。

1 时间复杂度

底层包含所有元素(n个),即 2^(h +1)=n ,索引层数 h=logn-1。搜索时,首先在顶层索引中进行查找,然后二分搜索,最多从顶层搜索到底层,最多 O(logn) 层,因此查找的时间复杂度为 O(logn)。

2 空间复杂度

增加索引需要一些辅助空间,那么索引一共有多少个节点呢?从上图中可以看出,每层索引的节点之和都为 2+2^2 +…+2^h =2^(h +1)-2=n-2,因此空间复杂度为 O(n )。实际上,索引节点并不是原节点

的复制,只是附加了一些指针建立索引。以上正是跳跃表的实现原理。

三 跳跃表介绍

跳跃表(Skip list)是有序链表的扩展,简称跳表,它在原有的有序链表上增加了多级索引,通过索引来实现快速查找,实质上是一种可以进行二分查找的有序链表。

实际上,跳跃表并不是简单地通过奇偶次序建立索引的,而是通过随机技术实现的,因此也可以说它是一种随机化的数据结构。假如跳跃表每一层的晋升概率都是 1/2,则最理想的索引就是在原始链表中每隔一个元素抽取一个元素作为一级索引。其实在原始链表中随机选择 n/2 个元素作为一级索引也可以,因为随机选择的元素相对均匀,对查找效率来讲影响不大。当原始链表中元素数量足够大且抽取足够随机时,得到的索引是均匀的。因此随机选择 n/2 个元素作为一级索引,随机选择 n/4 个元素作为二级索引,随机选择 n/8 个元素作为三级索引,以此类推,一直到顶层索引。我们可以通过索引来提升跳跃表的查找效率。

跳跃表不仅可以提高搜索性能,还可以提高插入和删除操作的性能。平衡二叉查找树在进行插入、删除操作后需要多次调整平衡,而跳跃表完全依靠随机技术,其性能和平衡二叉查找树不相上下,但是原理非常简单。跳跃表是一种性能比较优秀的动态数据结构,Redis 中的有序集合 Sorted Set 和 LevelDB 中的 MemTable 都是采用跳跃表实现的。

四 跳跃表的实现

1 数据结构定义

在每个节点都可以设置向右、向下指针,当然,也可以附加向左、向上指针,构建四联表。通过四联表可以快速地在四个方向访问前驱和后继。在此仅设置向右指针,在每个节点都定义一个后继指针数组,通过层次控制向下访问。

2 查找

在跳跃表中查找元素 x ,需要从最上层索引开始逐层查找,算法步骤如下。

(1)从最上层 Sh 的头节点开始。

(2)假设当前位置为 p ,p 的后继节点的值为 y ,若 x=y,则查找成功;若 x>y ,则 p 向后移一个位置,继续查找;若 x<y ,则 p 向下移动一个位置,继续查找。

(3)若到达底层还要向下移动,则查找失败。

例如,跳跃表如下图所示,在表中查找元素 36,则先从顶层的头节点开始,比 20 大,向后为空,p 向下移动到第 2 层;比下一个元素 50 小,p 向下移动到第 1 层;比下一个元素 30 大,p 向右移动;比下一个元素 50 小,p 向下移动到第 0 层;与下一个元素 36 比较,查找成功。

3 插入

在跳跃表中插入一个元素时,相当于在某一个位置插入一个高度为 level 的列。插入的位置可以通过查找确定,而插入列的高度可以采用随机化决策确定。

随机化获取插入元素的层次:

① 初始时 lay=0,可设定晋升概率P为 0.5 或 0.25。

② 利用随机函数产生 0~1的随机数 r。

④ 若 r 小于 P 且 lay 小于最大层次,则 lay+1;否则返回 lay,作为新插入元素的高度。

在跳跃表中插入元素的算法步骤如下。

(1)查找插入位置,在查找过程中用 updata[i] 记录经过的每一层的最大节点位置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值