跳跃表(跳表)是什么

news2025/1/6 15:27:28

为什么要有跳表

正常链表只能一个一个往下走但是如果我直到我的目标位置就在链表的中部但是我还得一步一步走过去很浪费时间,所以跳表就是在正常链表的基础上添加了多步跳跃的指针。

什么是跳表

跳表(Skip List)是一种概率型的数据结构,它是基于链表的,通过创建多个层次的链表来加快搜索速度。每个节点不仅有指向下一节点的指针,还可能有指向更高层次节点的指针,从而实现快速跳跃。跳表的时间复杂度为 O(log n) 级别,适用于插入、删除和查找操作。

演示图只是为了方便,实际跳表并不一定是二分的,一个节点最初始在最底层(L0),他有75%的概率不增长层数有25%的概率往上增长一层,后续也是如此25%概率增长一层,我们的层数基本控制在log n。

以下源码来自 redis7.0
​
#define ZSKIPLIST_MAXLEVEL 32 /* Should be enough for 2^64 elements */
#define ZSKIPLIST_P 0.25   /* Skiplist P = 1/4 */
​
/* Returns a random level for the new skiplist node we are going to create.
 * The return value of this function is between 1 and ZSKIPLIST_MAXLEVEL
 * (both inclusive), with a powerlaw-alike distribution where higher
 * levels are less likely to be returned. */
int zslRandomLevel(void) {
    static const int threshold = ZSKIPLIST_P*RAND_MAX;
    int level = 1;
    while (random() < threshold)
        level += 1;
    return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
}

跳表的基本结构

跳表由以下几个部分组成:

  1. 表头(head):负责维护跳跃表的节点指针。

  2. 跳跃表节点:保存着元素值,以及多个层。

  3. :保存着指向其他元素的指针。高层的指针越过的元素数量大于等于低层的指针,为了提高查找的效率,程序总是从高层先开始访问,然后随着元素值范围的缩小,慢慢降低层次。

  4. 表尾:全部由 NULL 组成,表示跳跃表的末尾。

跳表的实现

在Redis中,跳表由 zskiplistNodezskiplist 两个结构定义。其中 zskiplistNode 结构用于表示跳跃表节点,而 zskiplist 结构则用于保存跳跃表节点的相关信息,比如节点的数量,以及指向表头节点和表尾节点的指针等等。

zskiplistNode 结构
  • 后退指针(backward):指向当前节点的前一个节点。

  • 分值(score):用于排序,跳跃表中的所有节点都按分值大小进行排序。

  • 成员对象(ele):即真正要往链表中存放的对象。

  • 层(level):每个节点都包含很多层,每一层指向的都是同一个对象。每一层包含一个前进指针和一个跨度(span),前进指针指向同一层的下一个节点,跨度表示两个节点之间的距离。

typedef struct zskiplistNode {
    //Zset 对象的元素值
    sds ele;
    //元素权重值
    double score;
    //后退指针
    struct zskiplistNode *backward;
  
    //节点的level数组,保存每层上的前向指针和跨度
    struct zskiplistLevel {
        struct zskiplistNode *forward;
        unsigned long span;
    } level[];
} zskiplistNode;
zskiplist 结构
  • header:指向跳跃表的表头节点。

  • tail:指向跳跃表的表尾节点。

  • level:记录目前跳跃表内,层数最大的那个节点的层数(表头节点的层数不计算在内)。

  • length:记录跳跃表的长度,也即是,跳跃表目前包含节点的数量(表头节点不计算在内)。

跳表的操作

跳表支持以下基本操作:

  1. 插入(Insert):插入一个元素时,从最高层开始,查找到当前节点的目标插入位置,随机生成它的层数(25%概率增长一层),然后将元素插入到跳表中并更新指针。需要使用一个数组记录该节点在各层的上一节点,用于跟新指针。

  2. 删除(Delete):删除元素时,需要最高层级开始找到对应的节点,删除并更新相关层级指针。

  3. 查找(Search):查找元素时,从高层开始向下查找,直到找到元素或到达底层。

跳表是一种以空间换时间的方案,它通过增加索引层数来提高查找效率,但同时也会占用更多的内存。在Redis中,跳表主要用于实现有序集合(Sorted Set),它能够保证元素的快速查找和有序存储。

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

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

相关文章

如何逐步操作vCenter修改DNS服务器?

在vSphere 7中有一个新功能&#xff0c;它允许管理员更改vCenter Server Appliance的FQDN和IP。因此本文将介绍如何轻松让vCenter修改DNS服务器。 vCenter修改DNS以及修改vCenter IP地址 与在部署 vCenter Server Appliance 后&#xff0c;您可以根据需要修改其 DNS 设置和 IP…

支持图片生成、语音转文本和文本转语音节点,支持导出和导入应用,MaxKB知识库问答系统v1.9版本发布

2025年1月3日&#xff0c;MaxKB开源知识库问答系统正式发布v1.9版本。 在v1.9社区版中&#xff0c;应用方面&#xff0c;MaxKB新增图片生成节点、文本转语音节点、语音转文本节点&#xff0c;支持用户提问时上传音频文件&#xff0c;支持导出和导入应用&#xff1b;知识库方面…

WebGL 实践(一)开发环境搭建

WebGL 是一种基于 JavaScript 的 API&#xff0c;用于在浏览器中渲染 2D和3D 图形&#xff0c;很多场景都能用&#xff0c;例如游戏开发、数据可视化、在线教育和虚拟现实等应用领域。 零、基础知识 相关基础知识很重要&#xff0c;如果会html、JavaScript等技术掌握起来会更…

商米电子秤服务插件

概述 SunmiScaleUTS封装商米电子秤服务模块&#xff0c;支持商米旗下S2, S2CC, S2L CC等设备&#xff0c;设备应用于超市、菜市场、水果店等,用于测量商品的重量,帮助实现快捷、准确、公正的交易等一系列商业场景。 功能说明 SDK插件下载 一. 电子秤参数 型号:S2, S2CC, …

【开源监控工具】Uptime Kuma:几分钟设置实时监控你的网站性能

文章目录 前言1.关于Uptime Kuma2.安装Docker3.本地部署Uptime Kuma4.使用Uptime Kuma5.cpolar内网穿透工具安装6.创建远程连接公网地址7.固定Uptime Kuma公网地址 前言 大家好&#xff01;如果你是网站运维人员或者管理着多个站点&#xff0c;那么今天我要介绍的一款工具绝对…

ubuntu操作系统安装SSH服务

1、更新仓库 sudo apt-get update 2、安装SSH服务 #安装SSH服务 apt-get install openssh-server#启用SSH服务 service ssh start#查看SSH服务运行状态 service ssh status 3、修改SSH配置文件 sudo vi /etc/ssh/sshd_config 4、开启ssh端口 sudo ufw allow ssh 5、重启SSH…

二、github基础

Github基础 备用github.com网站一、用户界面-Overview&#xff08;概览&#xff09;1用户信息2 导航栏3 热门仓库4 贡献设置5贡献活动6搜索和筛选7自定义收藏8贡献统计9最近活动10其他链接 二、用户界面-Repositories&#xff08;仓库&#xff09;1 libusb_stm322 savedata3 Fi…

Flink源码解析之:如何根据JobGraph生成ExecutionGraph

Flink源码解析之&#xff1a;如何根据JobGraph生成ExecutionGraph 在上一篇Flink源码解析中&#xff0c;我们介绍了Flink如何根据StreamGraph生成JobGraph的流程&#xff0c;并着重分析了其算子链的合并过程和JobGraph的构造流程。 对于StreamGraph和JobGraph的生成来说&…

mysqll连接用时太长解决方法

1、连接用时太长分析 从客户端连接mysql服务器&#xff0c;时间长达10几秒&#xff0c;此为mysql的dns的反向解析造成&#xff0c;在局域网内如果都是用ip连接&#xff0c;可以通过在配置文件中添加skip-name-resolve&#xff0c;取消此功能&#xff0c;取消后&#xff0c;就不…

LLM(十二)| DeepSeek-V3 技术报告深度解读——开源模型的巅峰之作

近年来&#xff0c;大型语言模型&#xff08;LLMs&#xff09;的发展突飞猛进&#xff0c;逐步缩小了与通用人工智能&#xff08;AGI&#xff09;的差距。DeepSeek-AI 团队最新发布的 DeepSeek-V3&#xff0c;作为一款强大的混合专家模型&#xff08;Mixture-of-Experts, MoE&a…

办公 三之 Excel 数据限定录入与格式变换

开始-----条件格式------管理规则 IF($A4"永久",1,0) //如果A4包含永久&#xff0c;条件格式如下&#xff1a; OR($D5<60,$E5<60,$F5<60) 求取任意科目不及格数据 AND($D5<60,$E5<60,$F5<60) 若所有科目都不及格 显示为红色 IF($H4<EDATE…

【深度学习】多目标融合算法—样本Loss提权

目录 一、引言 二、样本Loss提权 2.1 技术原理 2.2 技术优缺点 三、总结 一、引言 在朴素的深度学习ctr预估模型中&#xff08;如DNN&#xff09;&#xff0c;通常以一个行为为预估目标&#xff0c;比如通过ctr预估点击率。但实际推荐系统业务场景中&#xff0c;更多是多…

mapbox进阶,添加路径规划控件

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️MapboxDirections 控件二、🍀添加路径规划控件1. ☘️实现思路2. ☘️…

日志聚类算法 Drain 的实践与改良

在现实场景中&#xff0c;业务程序输出的日志往往规模庞大并且类型纷繁复杂。我们在查询和查看这些日志时&#xff0c;平铺的日志列表会让我们目不暇接&#xff0c;难以快速聚焦找到重要的日志条目。 在观测云中&#xff0c;我们在日志页面提供了聚类分析功能&#xff0c;可以…

uniapp--HBuilder开发

提示&#xff1a;本文为学习内容&#xff0c;若有错误&#xff0c;请联系作者&#xff0c;谦虚受教。 文章目录 前言一、下载HBuilder二、添加modbus相关库1.下载nodejs2.下载modbus库3.项目添加modbus库 三、HBuilder相关功能语句1.文件夹说明2.消息信息框3.开关按钮4.选中按钮…

Unity 3D柱状图效果

1.单个柱状效果展示 2.从上到下渐变透明材质Shader Shader "Unlit/NewUnlitShader" {Properties{_MainTex ("Texture", 2D) "white" {}_Color("Color",Color) (1,1,1,1)_Alpha("Alpha",Range(0,1) ) 0.2_Alpha2("…

JavaScript的数据类型及检测方式

目录 一、JS数据类型 1.基本数据类型 2.引用数据类型 二、堆和栈 三、数据类型检测 1.typeof 2.instanceof 3.constructor 4.Object.prototype.toString.call() JavaScript 中的数据类型主要分为两大类&#xff1a;原始数据类型(也称基本数据类型)和引用数据类型。 一…

电脑中缺失的nvrtc64_90.dll文件如何修复?

一、文件丢失问题 案例&#xff1a;nvrtc64_90.dll文件缺失 问题分析&#xff1a; nvrtc64_90.dll是NVIDIA CUDA Runtime Compilation库的一部分&#xff0c;通常与NVIDIA的CUDA Toolkit或相关驱动程序一起安装。如果该文件丢失&#xff0c;可能会导致基于CUDA的应用程序&…

GIT 企业级开发学习 1

本节主要命令&#xff1a; git init ls 不能列出 .git ls -a 列出 .git 1. 初始化 Git 仓库 git init • 初始化一个新的 Git 仓库&#xff0c;在当前目录下生成一个 .git 隐藏文件夹&#xff0c;用于存储版本控制信息。 2. 查看隐藏文件 ls -a • 使用 ls -a 显示隐藏文件…

用Tkinter制作一个用于合并PDF文件的小程序

需要安装PyPDF2库&#xff0c;具体原代码如下&#xff1a; # -*- coding: utf-8 -*- """ Created on Sun Dec 29 14:44:20 2024author: YBK """import PyPDF2 import os import tkinter as tk import windndpdf_files [] def dragged_files(f…