数据结构-跳表:自己理解的通俗总结 + 使用python实现

前提 :有序数据 + 基于链表
操作 :有序数据的查询 + 插入 + 删除
时间复杂度 :O(logn)
思想 :将有序数据进行分层,最底层是存储所有的数据,之后每一层逐层减少数据,并且需要注意 每一层的数据是基于其前一层的数据随机而来。(这里有一个点需要注意:这种随机可能会造成上层的数据失控,因此是实现时一般会做一定的 数据数量限制的伪随机 / 动态的变化概率 防止出现数据失控,造成数据太少或太多)

举例

现有数据(设定总共 3 层):1 -> 2 -> 5 -> 7 ->14 -> 23 -> 47

则分层完成后结果如下(每一层的每一个值是通过设定的概率筛选出来的):

第 0 层:1 -> 2 -> 5 -> 7 ->14 -> 23 -> 47

第 1 层:1 -> 5 -> 7 -> 23

第 2 层:1 -> 23

  • 查询逻辑 :每次查询都从顶层开始查询,并且降层时是从本层现校验的元素开始筛选而不是从头开始。
    现在查询 14:
    -1- :首先查询第 2 层,发现比 1 大比 23 小,开始查询第 1 层
    -2- :从 1 开始查询第 1 层,发现比最后一个值 23 小,开始查询第 0 层
    -3-:从 7 开始查询第 0 层,发现 7 的下一个值就是 14,查询完成
  • 插入数据逻辑 :每次从最底层开始插入
    首先插入第 0 层对应的位置,然后根据设定的概率判断是否要升层,如果升层则每一层都做同样的判断直到到达最顶层或者不需要升层为止。
  • 删除数据逻辑 :从顶层开始逐层查询元素删除
    首先从第 2 层开始查询,如果查询到了则删除,然后依次降层查询删除。

实现

接下来用python3来实现一下跳表(该实现没做伪随机,有一定概率出现上层数据失控):

python 复制代码
import random

class SkipListNode:
    def __init__(self, key, level):
        self.key = key
        self.forward = [None] * (level + 1)

class SkipList:
    def __init__(self, max_level, p):
        self.max_level = max_level  # 最大层数
        self.p = p  # 向上提升一个级别的概率
        self.header = SkipListNode(None, max_level)  # 创建头节点
        self.level = 0  # 当前最高层数

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

    def insert(self, key):
        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

        # 移动到下一层
        current = current.forward[0]

        # 如果当前层没有该键,则插入
        if current is None or current.key != key:
            # 随机确定节点高度
            rlevel = self.random_level()

            # 如果新节点的层数更高
            if rlevel > self.level:
                for i in range(self.level + 1, rlevel + 1):
                    update[i] = self.header
                self.level = rlevel

            # 创建新节点
            n = SkipListNode(key, rlevel)
            for i in range(rlevel + 1):
                n.forward[i] = update[i].forward[i]
                update[i].forward[i] = n

    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]
        current = current.forward[0]
        if current and current.key == key:
            return True
        return False

    def display(self):
        print("Skip List")
        for i in range(self.level + 1):
            print("Level {}: ".format(i), end="")
            node = self.header.forward[i]
            while node:
                print(node.key, end=" ")
                node = node.forward[i]
            print("")


# 创建跳表实例,最大层设为3,提升概率为0.5(这个概率随便设置)
skip_list = SkipList(3, 0.5)
skip_list.insert(3)
skip_list.insert(6)
skip_list.insert(7)
skip_list.insert(9)
skip_list.insert(12)
skip_list.insert(19)
skip_list.insert(17)

# 显示跳表
skip_list.display()

# 搜索元素
print("Search for 6:", skip_list.search(6))
print("Search for 15:", skip_list.search(15))

本文完~

相关推荐
王老师青少年编程12 分钟前
gesp(二级)(16)洛谷:B4037:[GESP202409 二级] 小杨的 N 字矩阵
数据结构·c++·算法·gesp·csp·信奥赛
茶猫_2 小时前
力扣面试题 - 40 迷路的机器人 C语言解法
c语言·数据结构·算法·leetcode·机器人·深度优先
青春男大3 小时前
java队列--数据结构
java·开发语言·数据结构·学习·eclipse
想要AC的sjh4 小时前
【Leetcode】3159. 查询数组中元素的出现位置
数据结构·算法·leetcode
南宫生4 小时前
力扣-数据结构-4【算法学习day.75】
java·数据结构·学习·算法·leetcode
TANGLONG2224 小时前
【初阶数据结构与算法】八大排序算法之归并排序与非比较排序(计数排序)
java·数据结构·c++·算法·面试·蓝桥杯·排序算法
坊钰5 小时前
【Java 数据结构】LinkedList 类 和 模拟实现链表
java·开发语言·数据结构·学习·算法·链表
橘颂TA5 小时前
【C++】数据结构 单链表的实现(企业存储用户数据的实现)
开发语言·数据结构·c++
向宇it6 小时前
【从零开始入门unity游戏开发之——C#篇32】C#其他不常用的泛型数据结构类、顺序存储和链式存储
java·开发语言·数据结构·unity·c#·游戏引擎
武昌库里写JAVA6 小时前
Golang内存管理与优化
数据结构·vue.js·spring boot·算法·课程设计