从redis跳表实现理解查找时间复杂度

本文解析了跳表为何能实现平均时间复杂度为O(logN),通过介绍一种随机层数算法,解释了如何通过概率控制确保跳表的高效查找性能。
​之前一直不太懂,为什么跳表的平均时间复杂度为O(logN)
但是后来看了下[url]http://blog.xiaoheshang.info/?p=248[/url] 算是理解了一些,再结合自己的思考,记录一下

首先,需要理解刚才那篇文章中的 "如果每2^i个节点都指向前面2^i个节点,寻找一个节点的复杂度变成logn(类似于二分查找)", 这个应该没什么问题
那么问题来了,为什么随机的层数也能保证logN的复杂度?
原因就在于,这里说的随机,并不是完全的随机一个层数出来,而是通过随机的算法,算出一个并不随机的层数来
以redis中的随机层数的算法来看


int zslRandomLevel(void) {
int level = 1;
while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))
level += 1;
return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
}


这里假设 ZSKIPLIST_P 为2 (实际为4,便于理解设置为2),这段代码我们可以理解为,落到层数为i + 1的概率为0.5^i
而反过来理解,每两个节点出现层数为2的期望就是1,每4个节点出现第三层的期望也为1,每8个节点出现第四层(0.5^3)的期望为1 (期望值 = 单个概率 * 数量)
正是基于此,如果我们的数据量越大,越是可以接近期望的值,所以,我们可以认为,我们实现了 "如果每2^i个节点都指向前面2^i个节点"的效果,也就是说,查找的平均复杂度为O(logN)
### Redis 跳表实现原理 Redis 使用跳表(Skip List)作为一种高效的数据结构,主要用于实现有序集合(Sorted Set)。以下是关于 Redis 跳表的具体实现原理: #### 1. 基本概念和特点 跳表是一种基于多层链表构建的概率型数据结构,能够提供高效的插入、删除以及查询操作。其核心特点是通过引入随机化机制,在不同层次上建立索引来加速查找过程[^1]。 跳表支持平均时间复杂度为 \(O(\log N)\),最坏情况下为 \(O(N)\) 的节点查找能力[^3]。 #### 2. 结构组成 跳表由多个层级构成,每一层都是一条水平方向上的单向链表。顶层链表包含较少的节点,而越往下的层级包含越多的节点。最低一层包含了所有的元素,并按升序排列。这种分层设计使得跳表能够在较高的概率下快速定位目标节点[^4]。 #### 3. 插入操作 当新节点被插入时,会先计算该节点应该位于哪些层级中。这个层数通常是通过一种随机算法决定的,比如抛硬币的方式:每次投掷正面,则增加一层;遇到反面停止。这种方式确保了各层之间的稀疏性和均匀分布特性[^5]。 一旦确定好要加入的新节点所在的层数之后,程序会在各个对应的高度位置更新指针关系完成连接工作。 #### 4. 查询操作 为了提高访问效率,跳表采用了自顶向下逐层扫描的方法来进行搜索。从最高的一层开始寻找第一个大于等于目标关键字的位置,然后切换至下一较低级别重复此步骤直至到达底部列表为止。由于高层级覆盖范围较大,因此可以显著减少比较次数达到优化效果。 #### 5. 删除操作 删除某个特定项只需沿着各级路径找到待移除对象所在之处并切断相应链接即可。因为每个项目都有明确记录它所处的所有高度信息,所以整个流程相对简单明了。 #### 6. 应用场景 在 Redis 中,当 ZSet (sorted set)中的成员数量较多或者成员本身较为庞大时,会选择采用 SkipList 来代替 ZipList 存储方式。这是因为前者具备更好的扩展性与稳定性表现,尤其针对频繁变动的大规模数据集而言更是如此。 ```c // C语言伪代码展示部分关键函数定义 typedef struct zskiplistNode { sds ele; /* 字符串表示 */ double score; /* 分数值 */ struct zskiplistLevel { struct zskiplistNode *forward; unsigned int span; } level[]; } zskiplistNode; typedef struct zskiplist { struct zskiplistNode *header, *tail; unsigned long length; int level; } zskiplist; ``` 以上展示了 redis 源码里有关 skiplist 定义的部分片段,从中可以看出每一个节点不仅保存着自己的数据域还包括指向下一个同级节点地址字段 forward 和跨度计数值 span ,这些属性共同构成了完整的跳跃表体系结构。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值