Redis数据结构:深入解析跳跃表(Skiplist)

   感谢您阅读本文,欢迎“一键三连”。作者定会不负众望,按时按量创作出更优质的内容。
❤️ 1. 毕业设计专栏,毕业季咱们不慌,上千款毕业设计等你来选。

引言

Redis是一款广泛使用的内存数据结构存储系统,支持多种数据结构,如字符串、哈希、列表、集合和有序集合等。跳跃表(Skiplist)作为Redis中实现有序集合的核心数据结构,凭借其高效的插入、删除和查找性能,在数据存储和检索中扮演着重要角色。本文将详细介绍跳跃表的原理、特点、应用场景、Java实现代码以及在Redis中的使用方法。

跳跃表的原理

跳跃表是一种基于链表的分层数据结构,通过在不同层次间建立跳跃连接,实现对元素的快速查找。跳跃表的每一层都是一个有序链表,且上层链表是下层链表的子集,最底层链表包含所有元素。

跳跃表的查找过程类似于二分查找,通过逐层向下查找,跳跃越过大量元素,从而实现对数级别的查找效率。插入和删除操作也通过更新相关层次的链接,实现高效操作。

跳跃表的特点

  1. 时间复杂度:跳跃表的平均时间复杂度为O(log n),最坏情况下为O(n)。
  2. 空间复杂度:跳跃表的空间复杂度为O(n log n)。
  3. 实现简单:相对于平衡树,跳跃表的实现更为简单。
  4. 动态性好:跳跃表能够动态调整结构,适应数据的插入和删除。

跳跃表的应用场景

跳跃表在Redis中的主要应用场景包括:

  1. 有序集合(Sorted Set):通过跳跃表实现有序集合的数据存储,支持快速的范围查找和排名操作。
  2. Leaderboard:实现排行榜功能,快速插入、删除和查找用户排名。
  3. 时间序列数据:存储和检索时间序列数据,支持高效的范围查询。

Java实现跳跃表

下面是跳跃表的Java实现代码及其测试方法:

import java.util.Random;// 跳跃表节点类
class SkipListNode {int value;SkipListNode[] forward;public SkipListNode(int level, int value) {this.value = value;this.forward = new SkipListNode[level + 1];}
}// 跳跃表类
class SkipList {private static final int MAX_LEVEL = 16; // 最大层数private SkipListNode head; // 头节点private int level; // 当前最大层数private Random random;public SkipList() {this.head = new SkipListNode(MAX_LEVEL, Integer.MIN_VALUE);this.level = 0;this.random = new Random();}// 插入元素public void insert(int value) {SkipListNode[] update = new SkipListNode[MAX_LEVEL + 1];SkipListNode x = head;for (int i = level; i >= 0; i--) {while (x.forward[i] != null && x.forward[i].value < value) {x = x.forward[i];}update[i] = x;}x = new SkipListNode(randomLevel(), value);for (int i = 0; i <= x.forward.length - 1; i++) {x.forward[i] = update[i].forward[i];update[i].forward[i] = x;}if (x.forward.length - 1 > level) {level = x.forward.length - 1;}}// 查找元素public boolean search(int value) {SkipListNode x = head;for (int i = level; i >= 0; i--) {while (x.forward[i] != null && x.forward[i].value < value) {x = x.forward[i];}}x = x.forward[0];return x != null && x.value == value;}// 删除元素public void delete(int value) {SkipListNode[] update = new SkipListNode[MAX_LEVEL + 1];SkipListNode x = head;for (int i = level; i >= 0; i--) {while (x.forward[i] != null && x.forward[i].value < value) {x = x.forward[i];}update[i] = x;}x = x.forward[0];if (x != null && x.value == value) {for (int i = 0; i <= x.forward.length - 1; i++) {update[i].forward[i] = x.forward[i];}while (level > 0 && head.forward[level] == null) {level--;}}}// 随机生成层数private int randomLevel() {int level = 0;while (random.nextDouble() < 0.5 && level < MAX_LEVEL) {level++;}return level;}// 打印跳跃表public void printSkipList() {for (int i = level; i >= 0; i--) {SkipListNode x = head.forward[i];while (x != null) {System.out.print(x.value + " ");x = x.forward[i];}System.out.println();}}// 测试跳跃表public static void main(String[] args) {SkipList skipList = new SkipList();skipList.insert(1);skipList.insert(2);skipList.insert(3);skipList.insert(4);skipList.insert(5);System.out.println("Skip List after inserts:");skipList.printSkipList();System.out.println("Search 3: " + skipList.search(3));System.out.println("Search 6: " + skipList.search(6));skipList.delete(3);System.out.println("Skip List after deleting 3:");skipList.printSkipList();}
}

Redis中跳跃表的使用

在Redis中,跳跃表主要用于实现有序集合(Sorted Set)。下面是一些基本的有序集合命令及其使用示例:

添加元素
# 将一个带有分数的元素添加到有序集合中
zadd myzset 1 "one"
zadd myzset 2 "two"
zadd myzset 3 "three"
获取元素
# 按照分数从低到高获取所有元素
zrange myzset 0 -1# 按照分数从高到低获取所有元素
zrevrange myzset 0 -1
删除元素
# 删除指定元素
zrem myzset "two"
获取元素的排名
# 获取元素的排名(从0开始)
zrank myzset "three"
获取元素的分数
# 获取元素的分数
zscore myzset "one"

总结

跳跃表作为Redis实现有序集合的核心数据结构,具备高效的查找、插入和删除性能,适用于多种应用场景。通过本文对跳跃表原理、特点、应用场景的详细介绍,以及Java实现代码和Redis使用方法的展示,希望读者能够深入理解跳跃表这一重要数据结构,并在实际应用中灵活运用。

   感谢您阅读本文,欢迎“一键三连”。作者定会不负众望,按时按量创作出更优质的内容。
❤️ 1. 毕业设计专栏,毕业季咱们不慌,上千款毕业设计等你来选。

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

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

相关文章

Java医院绩效考核系统源码 :3分钟带你了解(医院绩效考核系统有哪些应用场景)三级公立医院绩效考核系统源码

Java医院绩效考核系统源码 &#xff1a;3分钟带你了解&#xff08;医院绩效考核系统有哪些应用场景&#xff09;三级公立医院绩效考核系统源码 作为医院用综合绩效核算系统&#xff0c;系统需要和his系统进行对接&#xff0c;按照设定周期&#xff0c;从his系统获取医院科室和…

可持续性是 Elastic: 进步与新机遇的一年

作者&#xff1a;来自 Elastic Keith Littlejohns 我们最新的可持续发展报告&#xff08;Sustainability Report&#xff09;总结了 Elastic 又一个令人兴奋的进步年&#xff0c;我们的项目继续揭示新的机遇。过去的一年对于我们与主要利益相关者群体合作以更好地了解他们的目标…

[解决方案]使用微软拼音打中文卡顿到离谱

去这里看&#xff0c;发现有65535个文件&#xff0c;基本都是临时文件。删除后测试了一下&#xff0c;不会卡顿了但是只要打中文还是会疯狂生成tmp临时文件。 问题&#xff1a;输入法不兼容 解决方案 先把上面那个文件夹里的tmp文件全删了 直接点是&#xff0c;其他的文件会…

【ajax实战02】数据管理网站—验证码登录

一&#xff1a;数据提交&#xff08;提交手机验证码&#xff09; 核心思路整理 利用form-serialize插件&#xff0c;收集对象形式的表单数据后&#xff0c;一并提交给服务器。后得到返回值&#xff0c;进一步操作 基地址&#xff1a; axios.defaults.baseURL http://geek.…

制作一个智能体:抖音热点话题文案制作助手

文章目录 第一步&#xff0c;添加助手第二步&#xff0c;选择语聚GPT第三步&#xff0c;填写相关信息第四步&#xff0c;工具中选择抖音(普通号)第五步&#xff0c;选择“查询热门视频数据”第六步&#xff0c;测试总结 这篇文章&#xff0c;我们手把手的演示开发一个智能体&am…

Dxf库中的DL_Codes类

在 DXF 文件格式中&#xff0c;DL_Codes 通常是一个用于表示不同类型数据的枚举类或常量集合。这些代码用于标识 DXF 文件中各种数据元素的类型&#xff0c;例如实体类型、属性类型、颜色值等。通过使用 DL_Codes&#xff0c;您可以更轻松地解析和处理 DXF 文件中的数据。 以下…

leetcode119 杨辉三角②

给定一个非负索引 rowIndex&#xff0c;返回「杨辉三角」的第 rowIndex 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: rowIndex 3 输出: [1,3,3,1]示例 2: 输入: rowIndex 0 输出: [1]示例 3: 输入: rowIndex 1 输出: [1,1] pub…

宠物空气净化器热卖爆款,希喂、小米、352猫用空气净化器真实PK

相信大漫天多数养猫家庭都会有一个烦恼&#xff1a;猫咪们的猫实在是太多了&#xff0c;无法忍受家里面漫天飞舞的浮毛和难闻的猫猫便臭。作为养猫多年的过来人我尝试过很多种方法清理这些猫浮毛和异味&#xff0c;但都以失败告终。 直到后面看到一个宠物博主推荐的宠物空气净…

ffmpeg截取视频

用格式工厂截取视频不知道为啥还是原长度&#xff0c;不过只能播放截取的部分&#xff0c;其他部分不能播放&#xff0c;但是总时长不对就不想用了。 参考 https://blog.csdn.net/m0_60259116/article/details/127017324https://cloud.tencent.com/developer/article/2410818ht…

tensorrt动态batch推理注意事项

一、背景&#xff1a;使用pytorch进行训练得到pt模型&#xff0c; 然后使用torch.onnx把pt模型转化为onnx模型。然后再使用tensorrt自带的trtexec.exe文件把onnx模型转化为engine文件。 &#xff08;1&#xff09;在使用C进行推理的时候发现一个batch的数据&#xff0c;值推理…

筛斗数据:数据提取技术,让数据说话的力量

在当今这个信息爆炸的时代&#xff0c;数据已经渗透到我们生活的方方面面。从商业决策到科学研究&#xff0c;从社会治理到个人生活&#xff0c;数据都扮演着至关重要的角色。而要让这些数据真正发挥其价值&#xff0c;就需要依赖数据提取技术&#xff0c;让数据“开口说话”&a…

环路滤波器

块效应产生的原因 块效应指视频边界不连续的变化,我们在观看视频的时候,在运动剧烈的场景常能观察到图像出现小方块,小方块在边界处呈现不连续的效果(如下图),这种现象被称为块效应(blocking artifact)。 造成这种现象的主要原因有两点: DCT量化误差导致运动补偿导致…

深入理解Java多线程中的 wait() 和 notify():为何要与 synchronized 手牵手

在Java中&#xff0c;wait、notify方法通常与synchronized关键字一起使用&#xff0c;这样做有几个重要的原因&#xff0c;主要涉及线程的协调和正确的并发控制。以下是一些关键点&#xff1a; 监视器锁&#xff08;Monitor Lock&#xff09;&#xff1a; 每个对象在Java中都可…

二叉树 遍历迭代法

二叉树 遍历迭代法 Leetcode 94 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), rig…

一个产品需求工程师繁忙的一天

早晨&#xff1a;开启新的一天 7:00 AM - 起床 早晨七点准时起床。洗漱、早餐后&#xff0c;查看手机上的邮件和消息&#xff0c;提前了解今天的工作安排和优先事项。 8:00 AM - 前往公司 坐地铁前往公司。在地铁上&#xff0c;习惯性地阅读一些行业资讯和市场报告&#xff0…

使用SpringBoot整合Servlet

一、SpringBoot和Servlet的整合 1、用注解WebServlet配置Servlet映射 创建一个SpringBoot的web工程&#xff0c;在工程用创建一个Servlet 2、在SpringBoot的启动类上加注解ServletComponentScan 二、额外的方式 1、不使用WebServlet配置Servlet映射 创建一个SpringBoot工…

RabbitMQ延时队列(实现定时任务)

消息的TTL(Time To Live)就是消息的存活时间。 RabbitMQ可以对队列和消息分别设置TTL。 对队列设置存活时间&#xff0c;就是队列没有消费者连着的保留时间。 对每一个单独的消息单独的设置存活时间。超过了这个时间&#xff0c;我们认为这个消息就死了&#xff0c;称之为死…

代码随想录算法训练营:19/60

非科班学习算法day19 | LeetCode530:二叉搜索树的最小绝对差 &#xff0c;Leetcode501:二叉搜索树的众数 &#xff0c;Leetcode236:二叉树的最近公共祖先 目录 介绍 一、LeetCode题目 1.LeetCode530:二叉搜索树的最小绝对差 题目解析 2.Leetcode501: 二叉搜索树的众数 …

软设之加工逻辑之结构化语言

结构化语言是一种介于自然语言和形式化语言之间的半形式语言&#xff0c;是自然语言的一个受限子集 外层&#xff1a;用来描述控制结构&#xff0c;采用顺序&#xff0c;选择和重复3种基本结构 1.顺序结构&#xff1a;一组祈使语句&#xff0c;选择语句&#xff0c;重复语句的…

个人对JVM的一点理解

JVM&#xff08;Java 虚拟机&#xff09;是 Java 程序能够跨平台运行的关键。它负责将 Java 字节码转换为机器码并执行。 JVM 主要由类加载器、运行时数据区、执行引擎和本地方法接口等部分组成。运行时数据区包括方法区、堆、虚拟机栈、本地方法栈和程序计数器等。 GC&#xf…