数据结构学习——跳表

结构:

多层链表结构,每层是有序的

工作原理 :

  • 最底层包含所有元素,按分数排序
  • 上层为"快速通道",包含部分元素
  • 查找时从顶层开始,逐步降级,类似二分查找

优势 :

  • 插入/删除/查找:O(log N)
  • 实现简单,比平衡树更容易维护
  • 并发性能好,无需复杂的锁机制

代码实现:

python 复制代码
class SkipListNode:
    """跳表节点"""
    def __init__(self, key: float, value: Any, level: int):
        self.key = key  # 排序键
        self.value = value  # 存储的值
        self.forward = [None] * (level + 1)  # 每层的前向指针


class SkipList:
    """跳表实现"""
    
    def __init__(self, max_level: int = 16, p: float = 0.5):
        """
        初始化跳表
        
        Args:
            max_level: 最大层数
            p: 晋升概率
        """
        self.max_level = max_level
        self.p = p
        self.level = 0  # 当前最大层数
        self.header = SkipListNode(float('-inf'), None, max_level)  # 头节点
    
    def random_level(self) -> int:
        """
        随机生成节点层数
        遵循几何分布,概率为 p^level
        """
        level = 0
        while random.random() < self.p and level < self.max_level:
            level += 1
        return level
    
    def search(self, key: float) -> Optional[Any]:
        """
        查找指定键的值
        
        Args:
            key: 要查找的键
            
        Returns:
            找到的值,未找到返回None
        """
        current = self.header
        
        # 从最高层开始查找
        for i in range(self.level, -1, -1):
            while current.forward[i] and current.forward[i].key < key:
                current = current.forward[i]
        
        # 到达第0层,检查是否找到
        current = current.forward[0]
        if current and current.key == key:
            return current.value
        return None
    
    def insert(self, key: float, value: Any) -> None:
        """
        插入键值对
        
        Args:
            key: 键
            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].key < key:
                current = current.forward[i]
            update[i] = current
        
        # 生成随机层数
        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 = SkipListNode(key, 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, key: float) -> bool:
        """
        删除指定键
        
        Args:
            key: 要删除的键
            
        Returns:
            是否删除成功
        """
        # 记录每层的删除位置
        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].key < key:
                current = current.forward[i]
            update[i] = current
        
        # 到达第0层,检查是否找到
        current = current.forward[0]
        if not current or current.key != key:
            return False
        
        # 更新各层的指针
        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 not self.header.forward[self.level]:
            self.level -= 1
        
        return True
    
    def range_query(self, start: float, end: float) -> List[Tuple[float, Any]]:
        """
        范围查询
        
        Args:
            start: 起始键
            end: 结束键
            
        Returns:
            键值对列表
        """
        result = []
        current = self.header
        
        # 从最高层开始查找起始位置
        for i in range(self.level, -1, -1):
            while current.forward[i] and current.forward[i].key < start:
                current = current.forward[i]
        
        # 从起始位置开始收集结果
        current = current.forward[0]
        while current and current.key <= end:
            result.append((current.key, current.value))
            current = current.forward[0]
        
        return result
    
    def get_all(self) -> List[Tuple[float, Any]]:
        """
        获取所有键值对
        
        Returns:
            键值对列表
        """
        result = []
        current = self.header.forward[0]
        while current:
            result.append((current.key, current.value))
            current = current.forward[0]
        return result
    
    def __str__(self) -> str:
        """
        字符串表示
        """
        result = []
        for i in range(self.level, -1, -1):
            level_str = f"Level {i}: "
            current = self.header.forward[i]
            nodes = []
            while current:
                nodes.append(f"({current.key}, {current.value})")
                current = current.forward[i]
            level_str += " -> ".join(nodes)
            result.append(level_str)
        return "\n".join(result)
相关推荐
海海不掉头发9 小时前
CSDN博客_时序预测9模型复现对比
人工智能·学习·软件工程
卡提西亚10 小时前
FastAPI基础入门
python·fastapi
fanruitian10 小时前
python 机器学习 ML LinearRegression KNN KMeans
python·机器学习·kmeans
鱼宵10 小时前
取集合第一个元素,Java 为什么要写三种写法?
java·windows·python·java21
卷无止境10 小时前
给AI装上一双眼睛:快速构建代码验证器的思路与落地方案
后端·python
维克兜率天11 小时前
【维克】指数调整:哪些股票会被“强制买入“?
人工智能·python·算法
come1123411 小时前
Codex 下不同场景 模式选择
python
蓝祁子yoky11 小时前
Qt学习日记 Day13:网络编程(一)-TCP基础与Socket实战
网络·qt·学习
神也畏惧菠萝11 小时前
Day08 Python流程控制从入门到上瘾:if/match/while/for四件套,从B站登录一路打到猜数字游戏
python·算法·数据存储·for·while·if·ifelse
言乐612 小时前
通过 3D 动画直观演示球形瓶内可滑动半圆机构在倾倒时防粘盖、回正时刮膏体的运动学过程
python·3d·django·virtualenv·pygame