跳跃列表(Skip List)详解

news2024/10/1 17:17:22

什么是跳跃列表?

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

跳跃列表的基本结构

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

结构示例

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

操作实现

1. 节点类

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

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

2. 跳跃列表类

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

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

示例使用

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) 的时间复杂度,成为解决许多实际问题的优秀选择。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2182796.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用Materialize制作unity的贴图,Materialize的简单教程,Materialize学习日志

Materialize 官网下载地址&#xff1a;http://boundingboxsoftware.com/materialize/ github源码地址&#xff1a;https://github.com/BoundingBoxSoftware/Materialize 下载地址&#xff1a;http://boundingboxsoftware.com/materialize/getkey.php 下载后解压运行exe即可 …

带徒实训项目实战讲义分享:ApiFirst文档对比功能页面开发

亲爱的学员朋友&#xff0c;前面咱一起实现了入参列表对比的部分功能&#xff0c;本节在此基础上继续开发和重构代码&#xff0c;go&#xff01; 文章目录 已实现的功能实现API入参列表的增删对比合并参数列表杜绝内部变量暴露提取modifiedType枚举 已实现的功能 基于0.0.6和…

算术操作符/和*、while、for循环

上一次我们讲到float等浮点型的数据范围和数据类型长度&#xff0c;以及sizeof可以查看变量、表达式、数据类型的字节数即所占内存。 除法/和乘法* 我们继续用计算器这个例子来学习其他语法。先来看最初我们写成的代码&#xff1a; #include<stdio.h> int Add(int a, …

基于YOLOv4和DeepSORT的车牌识别与跟踪系统

1. 项目简介 本项目旨在开发一个基于深度学习的自动车牌识别&#xff08;Automatic License Plate Recognition, ALPR&#xff09;系统&#xff0c;以实现对车辆牌照的实时检测、识别和追踪。自动车牌识别技术广泛应用于智慧交通、停车管理、电子收费和执法监控等领域&#xf…

Golang | Leetcode Golang题解之第440题字典序的第K小数字

题目&#xff1a; 题解&#xff1a; func getSteps(cur, n int) (steps int) {first, last : cur, curfor first < n {steps min(last, n) - first 1first * 10last last*10 9}return }func findKthNumber(n, k int) int {cur : 1k--for k > 0 {steps : getSteps(cu…

c++11新特性-下

c11的线程库可以跨平台使用。 原子性操作库(atomic) 不需要对原子类型变量进行加锁解锁操作&#xff0c;线程能够对原子类型变量互斥的访问。 atmoic<T> t; // 声明一个类型为T的原子类型变量t 在C11中&#xff0c;原子类 型只能从其模板参数中进行构造&#xff0c;不…

【规控+slam】探索建图方案及代码分享

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言背景建图描述SLAM定位+感知数据标记构建地图自动探索建图规划方法一:手动遥控探索建图算法步骤方法二:手动给定目标点探索建图算法原理方法三:f…

VMware虚拟机连接公网,和WindTerm

一、项目名称 vmware虚拟机连接公网和windterm 二、项目背景 需求1&#xff1a;windows物理机&#xff0c;安装了vmware虚拟机&#xff0c;需要访问公网资源&#xff0c;比如云服务商的yum仓库&#xff0c;国内镜像加速站的容器镜像&#xff0c;http/https资源。 需求2&#xf…

Hive数仓操作(八)

一、Hive中的分桶表 1. 分桶表的概念 分桶表是Hive中一种用于提升查询效率的表类型。分桶指的是根据指定列的哈希值将数据划分到不同的文件&#xff08;桶&#xff09;中。 2. 分桶表的原理 哈希分桶&#xff1a;根据分桶列计算哈希值&#xff0c;对哈希值取模&#xff0c;将…

【漏洞复现】JeecgBoot 积木报表 queryFieldBySql sql注入漏洞

》》》产品描述《《《 积木报表&#xff0c;是一款免费的企业级Web报表工具&#xff0c;像搭建积木一样在线设计报表!功能涵盖&#xff0c;数据报表、打印设计、图表报表、大屏设计等! 》》》漏洞描述《《《 JeecgBoot 积木报表 queryFieldBySq| 接口存在一个 SQL 注入漏洞&…

Web和UE5像素流送、通信教程

一、web端配置 首先打开Github地址&#xff1a;https://github.com/EpicGamesExt/PixelStreamingInfrastructure 找到自己虚幻引擎对应版本的项目并下载下来&#xff0c;我这里用的是5.3。 打开项目找到PixelStreamingInfrastructure-master > Frontend > implementat…

NodeJS下载、安装及环境配置教程,内容详实

文章目录 概述关于本文NodeJS介绍 安装步骤 概述 关于本文 本文讲解如何在Windows系统中安装NodeJS并配置相关环境。 NodeJS介绍 Node.js&#xff08;通常简称为Node&#xff09;是一个开源、跨平台的JavaScript运行时环境&#xff0c;它允许开发者在服务器端运行JavaScrip…

【PyTorch】图像分割

图像分割是什么 Image Segmentation 将图像每一个像素分类 图像分割分类 超像素分割&#xff1a;少量超像素代替大量像素&#xff0c;常用于图像预处理语义分割&#xff1a;逐像素分类&#xff0c;无法区分个体实例分割&#xff1a;对个体目标进行分割全景分割&#xff1a;…

Simulink仿真中get_param函数用法

目录 语法 说明 示例 获取模块参数值和模型参数值 获取根参数名称和值 获取模型参数名称和值 获取模块列表和参数值 使用模块句柄获取模块参数值 显示模型中所有模块的模块类型 获取封装参数、Simulink 对象、模块图或注释的选项列表 获取封装参数的计算值 get_para…

如何用TorchAO优化PyTorch模型:看得见的性能提升

你有没有在训练PyTorch模型时,遇到过速度慢、内存占用高的问题?不管你是研究模型优化,还是追求性能极致的开发者,TorchAO可能正是你需要的工具。今天我们来聊聊这个PyTorch原生的架构优化工具,看看它是如何帮助你优化模型的,并且提升整体性能。 TorchAO是什么? Tor…

基于JAVA+SpringBoot+Vue的社区养老服务平台

基于JAVASpringBootVue的社区养老服务平台 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末附源码下载链接&#x1f345; 哈…

脸爱云管理系统存在任意文件上传漏洞

漏洞描述 脸爱云一脸通智慧管理平台是一套功能强大、运行稳定、操作简单方便、用户界面美观的一脸通系统。该平台整合了人脸识别技术和智能化解决方案&#xff0c;可以实现识别和管理个体身份&#xff0c;为各种场景提供便捷的身份验证和管理功能。其存在任意文件上传漏洞&…

数值计算的程序设计问题举例

### 数值计算的程序设计问题 #### 1. 结构静力分析计算 **涉及领域**&#xff1a;工程力学、建筑工程 **主要问题**&#xff1a;线性代数方程组&#xff08;Linear Algebraic Equations&#xff09; **解释说明**&#xff1a; 在结构静力分析中&#xff0c;我们需要解决复杂的…

C++第五讲(2):STL--string--string的模拟实现+知识加餐

C第五讲&#xff08;2&#xff09;&#xff1a;STL--string--string的模拟实现知识加餐 1.string的模拟实现1.1string.h头文件 -- string类的声明1.2string.cpp源文件 -- string的具体实现1.3test.cpp源文件 -- string模拟实现的测试 2.知识补充1&#xff1a;swap3.知识补充2&a…

IDEA几大常用AI插件

文章目录 前言列表GPT中文版TalkXBito AIIDEA自带的AI 前言 最近AI、GPT特别火&#xff0c;IDEA里面又有一堆插件支持GPT&#xff0c;所以做个专题比较一下各个GPT插件 列表 先看idea的plugins里支持哪些&#xff0c;搜索“GPT”之后得到的&#xff0c;我用下来感觉第一第二和…