跳跃列表(Skip List)详解

什么是跳跃列表?

跳跃列表是一种概率性的数据结构,旨在提高链表的搜索、插入和删除效率。它通过在普通链表的基础上增加多个层次,以实现更快的访问速度。跳跃列表的设计灵感来源于跳跃图(Skip Graph)和多层索引的概念,适合需要频繁进行动态数据操作的场景。

跳跃列表的基本结构

跳跃列表由多个层次的链表组成。最底层的链表包含所有的元素,而上层的链表则通过指针跳过一些节点,从而加快搜索速度。每个节点不仅存储自己的值,还持有一个指针数组,指向同层的下一个节点。

结构示例

  • 头节点:通常存储负无穷,方便搜索。
  • 节点:每个节点包含一个值和多个指针,指向相同或更高层的节点。

操作实现

1. 节点类

首先定义节点类,包含节点的值和指针数组。

python 复制代码
class Node:
    def __init__(self, value, level):
        self.value = value
        self.forward = [None] * (level + 1)  # 指针数组

2. 跳跃列表类

实现跳跃列表类,包含插入、删除和搜索的方法。

python 复制代码
import random

class SkipList:
    def __init__(self, max_level):
        self.max_level = max_level
        self.header = Node(float('-inf'), max_level)  # 头节点
        self.level = 0  # 当前层数

    def random_level(self):
        level = 0
        while random.random() < 0.5 and level < self.max_level:
            level += 1
        return level

    def insert(self, value):
        update = [None] * (self.max_level + 1)  # 保存前驱节点
        current = self.header
        
        for i in range(self.level, -1, -1):
            while current.forward[i] and current.forward[i].value < value:
                current = current.forward[i]
            update[i] = current

        current = current.forward[0]  # 最底层的下一个节点
        
        if current is None or current.value != value:
            new_level = self.random_level()  # 随机层数
            if new_level > self.level:
                for i in range(self.level + 1, new_level + 1):
                    update[i] = self.header
                self.level = new_level

            new_node = Node(value, new_level)  # 新节点
            for i in range(new_level + 1):
                new_node.forward[i] = update[i].forward[i]
                update[i].forward[i] = new_node

    def delete(self, value):
        update = [None] * (self.max_level + 1)
        current = self.header
        
        for i in range(self.level, -1, -1):
            while current.forward[i] and current.forward[i].value < value:
                current = current.forward[i]
            update[i] = current

        current = current.forward[0]

        if current and current.value == value:
            for i in range(self.level + 1):
                if update[i].forward[i] != current:
                    break
                update[i].forward[i] = current.forward[i]

            while self.level > 0 and self.header.forward[self.level] is None:
                self.level -= 1

    def search(self, value):
        current = self.header
        for i in range(self.level, -1, -1):
            while current.forward[i] and current.forward[i].value < value:
                current = current.forward[i]
        current = current.forward[0]
        return current is not None and current.value == value

示例使用

python 复制代码
skip_list = SkipList(max_level=4)
skip_list.insert(3)
skip_list.insert(6)
skip_list.insert(7)
skip_list.insert(9)
skip_list.insert(12)
skip_list.insert(19)

print(skip_list.search(7))  # True
print(skip_list.search(15))  # False

skip_list.delete(3)
print(skip_list.search(3))  # False

时间复杂度分析

  1. 搜索 (Search): 平均时间复杂度为 O(log n),因其可以在多层中快速跳跃。
  2. 插入 (Insert): 平均时间复杂度也是 O(log n),通过随机选择层数实现高效插入。
  3. 删除 (Delete): 平均时间复杂度同样为 O(log n)。

最坏情况

在最坏情况下,所有元素都在同一层,此时时间复杂度为 O(n)。不过这种情况的概率较低,跳跃列表在实际应用中通常表现良好。

总结

跳跃列表是一种高效的概率性数据结构,适合动态数据的处理。通过引入随机性,跳跃列表在搜索、插入和删除操作中都能实现平均 O(log n) 的时间复杂度,成为解决许多实际问题的优秀选择。

如果你对跳跃列表有更多的疑问或想要进一步探讨的内容,欢迎在评论区留言!

相关推荐
iiiiyu16 分钟前
⾯向对象和集合编程题
java·大数据·开发语言·数据结构·编程语言
YuanDaima204816 分钟前
贪心算法基础原理与题目说明
数据结构·人工智能·python·算法·贪心算法·手撕代码
人道领域28 分钟前
【LeetCode刷题日记】513.二叉树左下角值的三种解法:从常规BFS到DFS的优雅之旅
数据结构·算法·leetcode·深度优先·广度优先
雁迟31 分钟前
第七章:R 向量用法(最核心数据结构)
开发语言·数据结构·r语言
兰令水1 小时前
topcode【随机算法题】【2026.5.16打卡-java版本】
java·数据结构·算法
Shan12051 小时前
广度优先搜索之层序遍历
数据结构·算法·宽度优先
清辞8531 小时前
集合竞价选股程序开发学习
数据结构
_深海凉_1 小时前
LeetCode热题100-将有序数组转换为二叉搜索树
数据结构·算法·leetcode
liu****2 小时前
第16届国赛蓝桥杯大赛C/C++大学B组
c语言·数据结构·c++·算法·蓝桥杯
ChoSeitaku2 小时前
04.数组
java·开发语言·数据结构