鱼C论坛

 找回密码
 立即注册
查看: 19|回复: 1

【求助】python 跳表实现

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
请各位大神帮忙看一下有没有问题,顺便指点一下(不完全理解)
import random

# 定义跳表节点类
class SkipListNode:
    def __init__(self, key=None, value=None, level=0):
        self.key = key          # 节点的键(用于排序)
        self.value = value      # 节点的值
        self.forward = [None] * (level + 1)  # 存储各层的后继节点

# 定义跳表类
class SkipList:
    # 跳表的默认配置
    MAX_LEVEL = 16  # 最大层数
    P = 0.5         # 随机生成层数的概率因子
    def __init__(self):
        self.level = 0  # 当前跳表的最大层数(初始为0层)
        self.header = SkipListNode(level=self.MAX_LEVEL)  # 头节点(不存数据)

    # 随机生成新节点的层数(核心:保证跳表的稀疏性)
    def _random_level(self):
        level = 0
        # 以P的概率增加层数,直到达到最大层数
        while random.random() < self.P and level < self.MAX_LEVEL:
            level += 1
        return level

    # 插入节点(key: 排序键,value: 存储值)
    def insert(self, key, value):
        # update数组:存储每一层需要更新的前驱节点
        update = [None] * (self.MAX_LEVEL + 1)
        current = self.header

        # 1. 从最高层开始,找到每一层的前驱节点
        for i in range(self.level, -1, -1):
            # 向右查找,直到找到比key大的节点
            while current.forward[i] and current.forward[i].key < key:
                current = current.forward[i]
            update[i] = current  # 记录当前层的前驱节点

        # 2. 检查底层是否已存在该key(存在则更新值)
        current = current.forward[0]
        if current and current.key == key:
            current.value = value
            return

        # 3. 生成新节点的随机层数
        new_level = self._random_level()

        # 4. 如果新层数超过当前跳表最大层数,补充update数组
        if new_level > self.level:
            for i in range(self.level + 1, new_level + 1):
                update[i] = self.header
            self.level = new_level  # 更新跳表最大层数

        # 5. 创建新节点,并将各层的指针指向后继节点
        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

    # 查找节点(根据key返回value,不存在则返回None)
    def search(self, key):
        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]

        # 检查底层是否存在目标key
        current = current.forward[0]
        if current and current.key == key:
            return current.value
        return None

    # 删除节点(根据key删除,返回是否删除成功)
    def delete(self, key):
        # update数组:存储每一层需要更新的前驱节点
        update = [None] * (self.MAX_LEVEL + 1)
        current = self.header

        # 1. 从最高层开始,找到每一层的前驱节点
        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

        # 2. 检查底层是否存在目标key
        current = current.forward[0]
        if not current or current.key != key:
            return False  # 不存在该key,删除失败

        # 3. 更新各层的指针,跳过被删除的节点
        for i in range(self.level + 1):
            if update[i].forward[i] != current:
                break  # 该层没有指向当前节点,无需更新
            update[i].forward[i] = current.forward[i]

        # 4. 更新跳表的最大层数(如果最高层没有节点)
        while self.level > 0 and self.header.forward[self.level] is None:
            self.level -= 1

        return True  # 删除成功

    # 遍历跳表(按key升序返回所有(key, value)对)
    def traverse(self):
        result = []
        current = self.header.forward[0]  # 从底层第一个节点开始
        while current:
            result.append((current.key, current.value))
            current = current.forward[0]
        return result

# ------------------- 测试代码 -------------------
if __name__ == "__main__":
    # 创建跳表实例
    skip_list = SkipList()

    # 插入测试
    skip_list.insert(3, "apple")
    skip_list.insert(1, "banana")
    skip_list.insert(5, "orange")
    skip_list.insert(2, "grape")
    print("插入后遍历(升序):", skip_list.traverse())
    # 输出:[(1, 'banana'), (2, 'grape'), (3, 'apple'), (5, 'orange')]

    # 查找测试
    print("查找key=3:", skip_list.search(3))  # 输出:apple
    print("查找key=4:", skip_list.search(4))  # 输出:None

    # 更新测试(插入相同key会更新值)
    skip_list.insert(3, "pear")
    print("更新key=3后遍历:", skip_list.traverse())
    # 输出:[(1, 'banana'), (2, 'grape'), (3, 'pear'), (5, 'orange')]

    # 删除测试
    skip_list.delete(2)
    print("删除key=2后遍历:", skip_list.traverse())
    # 输出:[(1, 'banana'), (3, 'pear'), (5, 'orange')]
    print("删除不存在的key=4:", skip_list.delete(4))  # 输出:False
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层
以下是修正后的跳表实现,主要修复了语法错误和逻辑问题:


  1. import random

  2. class SkipListNode:
  3.     def __init__(self, key=None, value=None, level=0):
  4.         self.key = key
  5.         self.value = value
  6.         self.forward = [None] * (level + 1)  # 修正:添加列表初始化

  7. class SkipList:
  8.     MAX_LEVEL = 16
  9.     P = 0.5
  10.    
  11.     def __init__(self):
  12.         self.level = 0
  13.         self.header = SkipListNode(level=self.MAX_LEVEL)
  14.    
  15.     def _random_level(self):
  16.         level = 0
  17.         while random.random() < self.P and level < self.MAX_LEVEL:
  18.             level += 1
  19.         return level
  20.    
  21.     def insert(self, key, value):
  22.         update = [None] * (self.MAX_LEVEL + 1)  # 修正:初始化列表
  23.         current = self.header
  24.         
  25.         # 从最高层开始查找插入位置
  26.         for i in range(self.level, -1, -1):
  27.             while current.forward[i] and current.forward[i].key < key:
  28.                 current = current.forward[i]
  29.             update[i] = current  # 修正:记录每层的前驱节点
  30.         
  31.         # 检查是否已存在
  32.         current = current.forward[0]
  33.         if current and current.key == key:
  34.             current.value = value
  35.             return
  36.         
  37.         # 创建新节点
  38.         new_level = self._random_level()
  39.         if new_level > self.level:
  40.             for i in range(self.level + 1, new_level + 1):
  41.                 update[i] = self.header
  42.             self.level = new_level
  43.         
  44.         new_node = SkipListNode(key, value, new_level)
  45.         for i in range(new_level + 1):
  46.             new_node.forward[i] = update[i].forward[i]
  47.             update[i].forward[i] = new_node
  48.    
  49.     def search(self, key):
  50.         current = self.header
  51.         for i in range(self.level, -1, -1):
  52.             while current.forward[i] and current.forward[i].key < key:
  53.                 current = current.forward[i]
  54.         
  55.         current = current.forward[0]
  56.         if current and current.key == key:
  57.             return current.value
  58.         return None
  59.    
  60.     def delete(self, key):
  61.         update = [None] * (self.MAX_LEVEL + 1)
  62.         current = self.header
  63.         
  64.         for i in range(self.level, -1, -1):
  65.             while current.forward[i] and current.forward[i].key < key:
  66.                 current = current.forward[i]
  67.             update[i] = current
  68.         
  69.         current = current.forward[0]
  70.         if not current or current.key != key:
  71.             return False
  72.         
  73.         # 更新各层指针
  74.         for i in range(self.level + 1):
  75.             if update[i].forward[i] != current:
  76.                 break
  77.             update[i].forward[i] = current.forward[i]
  78.         
  79.         # 更新跳表层数
  80.         while self.level > 0 and self.header.forward[self.level] is None:
  81.             self.level -= 1
  82.         
  83.         return True
  84.    
  85.     def traverse(self):
  86.         result = []
  87.         current = self.header.forward[0]
  88.         while current:
  89.             result.append((current.key, current.value))
  90.             current = current.forward[0]
  91.         return result

  92. # 测试代码
  93. if __name__ == "__main__":
  94.     skip_list = SkipList()
  95.    
  96.     skip_list.insert(3, "apple")
  97.     skip_list.insert(1, "banana")
  98.     skip_list.insert(5, "orange")
  99.     skip_list.insert(2, "grape")
  100.     print("插入后遍历:", skip_list.traverse())
  101.    
  102.     print("查找key=3:", skip_list.search(3))
  103.     print("查找key=4:", skip_list.search(4))
  104.    
  105.     skip_list.insert(3, "pear")
  106.     print("更新key=3后遍历:", skip_list.traverse())
  107.    
  108.     skip_list.delete(2)
  109.     print("删除key=2后遍历:", skip_list.traverse())
  110.     print("删除不存在的key=4:", skip_list.delete(4))
复制代码


主要修正内容:

1. 列表初始化问题
- 原代码中 forward =  * (level + 1) 缺少列表声明,改为 forward = [None] * (level + 1)
- update =  * (self.MAX_LEVEL + 1) 同样修正

2. 多层指针访问问题
- 原代码直接使用 current.forward 访问,但实际应该是按层访问 current.forward[i]
- 在循环中需要指定层数索引

3. 前驱节点记录问题
- update 数组需要按层记录,将 update = current 改为 update[i] = current

4. 层数更新逻辑修正
- 删除节点后,需要检查最高层是否还有节点,原代码只检查了第0层

跳表核心思想理解:

1. 多层结构:跳表通过多级索引加速查找,类似电梯的楼层设计
2. 随机层数:新节点层数随机生成,保证平衡性
3. 空间换时间:用额外指针空间换取O(log n)的查询效率
4. 有序性:所有节点按键值排序,便于范围查询

测试输出示例:

  1. 插入后遍历: [(1, 'banana'), (2, 'grape'), (3, 'apple'), (5, 'orange')]
  2. 查找key=3: apple
  3. 查找key=4: None
  4. 更新key=3后遍历: [(1, 'banana'), (2, 'grape'), (3, 'pear'), (5, 'orange')]
  5. 删除key=2后遍历: [(1, 'banana'), (3, 'pear'), (5, 'orange')]
  6. 删除不存在的key=4: False
复制代码


以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2026-1-27 18:54

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表