https://www.nowcoder.com/feed/main/detail/d8dd74b804dd44c7aaf1bb0249f86dee?sourceSSR=users
https://www.cnblogs.com/use-D/p/18272513
Redis使用跳表(Skip List)作为有序集合(Sorted Set)的底层数据结构之一。跳表是一种随机化的数据结构,它通过在链表的不同层级上构建索引来加速搜索操作,提供了比普通链表更快的查找速度,平均时间复杂度为O(log n)。
以下是Redis中跳表插入数据的基本过程:
以下是Redis中跳表插入数据的基本过程:
- 初始化和随机化层级:
- 首先,初始化一个新节点,并为其分配足够的空间来存储键值和分值。
- 然后,随机确定新节点的层级高度。Redis通常使用一种类似于抛硬币的方法,每次都有一定的概率增加层级,直到抛硬币的结果不允许再增加为止。层级越高,新节点将在更多的层级上出现,这有助于加速后续的查找操作。
- 寻找插入位置:
- 从跳表的最高层级开始,找到小于等于新节点分值的最大节点。这一过程类似于二分查找,从顶部开始向下移动,直到找到正确的插入位置。
- 为了加速这一过程,Redis会维护一个栈(或数组)来保存沿途经过的节点,这被称为
update
栈。栈中的元素代表了每一层的前驱节点。
- 插入新节点:
- 在找到正确的插入位置后,将新节点插入到跳表的每一层中,从最高层级开始,直到新节点的随机层级高度为止。
- 更新
update
栈中对应层级的前驱节点的后继指针,指向新插入的节点。
- 同时,新节点的前驱指针指向栈中的前驱节点,后继指针指向原来的后继节点。
- 更新跳表的高度:
- 如果新插入的节点的层级高度超过了跳表当前的最大高度,那么跳表的高度将会更新为新节点的高度。
- 调整跨度(span):
- 跳表中的节点还包含一个跨度(span),表示从该节点到下一节点的距离。在插入新节点后,需要更新受影响节点的跨度值,确保它们反映最新的跳表结构。
- 跳表节点计数更新:
- 插入操作完成后,跳表的节点总数会增加,需要更新跳表的节点计数统计。
通过上述过程,Redis能够有效地在跳表中插入新的键值对,同时保持数据结构的有序性和高效性。值得注意的是,尽管插入操作理论上可以在O(log n)的时间内完成,但由于需要更新多层索引,实际操作中可能需要进行多次内存分配和链接操作。然而,由于跳表的随机化性质,这些操作的平均成本仍然较低。
redis跳跃表图解&插入详述