【高阶数据结构】跳表

文章目录

  • 跳表 skiplist
    • 跳表的结构特点
  • 跳表的具体实现

跳表 skiplist

跳表本质也是一个用于快速查找的概率型数据结构,通过在有序链表上增加多级索引来实现。有了这些索引,快表查询的效率接近于二分,在一些场景上可以代替平衡二叉树如AVL树、红黑树等。
为什么一个有序的链表查找效率会这么高呢?不同于数组查找,链表查找是不能直接用左右边界求mid来二分的。下面我们先分析其原因。

跳表的结构特点

  • 多级索引:跳表在最底层是一个有序链表,底层的链表包含所有数据元素。每一层索引是下层索引的子集。通常每个元素以一定概率 p 选取是否出现在上一层索引中。
    在这里插入图片描述
    对于跳表中的每一个节点,都会有多个且数目不相同的指针指向后面的元素。越高层的指针指向的数据更远也更大,这样一来,查找某一个数据时就不用遍历整个链表了,而是通过指针(也称为索引)越级查询

  • 随机层数:每个节点的多个指针指向的值从大到小竖直排列,有效指针的数量就是节点的层数。插入一个新元素时,从最低层开始插入,然后以概率 p 决定是否在上一层也插入该元素。如果决定插入,则继续在上一层进行,直至不再插入或达到最高层

  • 平衡性:随机化层数使得节点在每一层索引上的分布大致均匀,保证了多级索引的有效性,确保大部分操作的时间复杂度保持在 O(logn)。

为什么新节点的层数要是随机的呢?

如果新节点的层数是固定的,跳表的结构就退化成了一个简单的有序链表,假设每个节点的层数是2,这样的跳表的时间复杂度查找、删除、添加的时间复杂度都是O(N)的。同样的,如果每个节点的层数
都很大,那么遍历一个节点的所有下级索引的代价也就越大,同样时间复杂度还是会退化成O(N)。所以,我们需要一种方案,使得有序链表中的层数不是固定的,且高层数的节点不能太多。这样一来,就可以通过设计一个随机层数的概率来大概控制整个有序链表的效率。
具体的,高层索引节点进行大跨度的跳跃,快速接近目标节点,然后在底层进行细致查找。这种多级索引结构使得查找、插入和删除操作的时间复杂度为O(logn)。当然,由于是随机产生层数,最坏情况就是每个节点只有一层或者每个节点的层数都是节点的总数,这样查找等操作时间复杂度就退化到了O(N).
想要更具体的性能分析,可以去看大佬的博客:铁蕾大佬

跳表的具体实现

参考题目:leetcode1206. 设计跳表

代码实现:

#define _CRT_SECURE_NO_WARNINGS 1
struct SkilpListNode {int _val;vector<SkilpListNode*> _nextv;SkilpListNode(int val, int level):_val(val), _nextv(level, nullptr){}
};
class Skiplist {
public:typedef SkilpListNode Node;Skiplist() {srand(time(NULL));//设置随机数种子_head = new Node(-1, 1);//头节点,层数为1}bool search(int target) {Node* cur = _head;int level = _head->_nextv.size() - 1;while (level >= 0) {//层数从高往低开始if (cur->_nextv[level] && target > cur->_nextv[level]->_val) {cur = cur->_nextv[level];//如果目标值大于当前节点的第level层索引的值,可以跳过去,更新cur}else if (!cur->_nextv[level] || target < cur->_nextv[level]->_val) {level--;//下一个索引节点是空//如果目标值小于当前节点的第level层索引的值,往下层移动,也就是再去比较值更小的下级索引}else {return true;//找到目标值}}return false;}vector<Node*> FindPrevNode(int num) {Node* cur = _head;int level = _head->_nextv.size() - 1;vector<Node*> prev(level + 1, _head);//用一个数组存下新节点的所有层的前一个节点while (level >= 0) {//层数从高往低开始if (cur->_nextv[level] && num > cur->_nextv[level]->_val) {cur = cur->_nextv[level];}else if (!cur->_nextv[level] || num <= cur->_nextv[level]->_val) {prev[level] = cur;level--;}}return prev;}void add(int num) {vector<Node*> prev = FindPrevNode(num);int n = GetRandomLevel();Node* newnode = new Node(num, n);if (n > _head->_nextv.size()) {_head->_nextv.resize(n, nullptr);prev.resize(n, _head);}for (int i = 0; i < n; i++) {newnode->_nextv[i] = prev[i]->_nextv[i];prev[i]->_nextv[i] = newnode;}}bool erase(int num) {vector<Node*> prev = FindPrevNode(num);if (prev[0]->_nextv[0] == nullptr || prev[0]->_nextv[0]->_val != num) {return false;}Node* delnode = prev[0]->_nextv[0];int n = delnode->_nextv.size();for (int i = 0; i < n; i++) {prev[i]->_nextv[i] = delnode->_nextv[i];}delete delnode;//如果删除的节点是最高层数int i = _head->_nextv.size() - 1;while (i >= 0) {if (_head->_nextv[i] == nullptr) {--i;}else break;}_head->_nextv.resize(i + 1);return true;}int GetRandomLevel() {size_t level = 1;while (rand() <= RAND_MAX * _p && level < _maxlevel) {level++;}return level;}private:Node* _head;size_t _maxlevel = 32;double _p = 0.25;//增加层数的概率};/*** Your Skiplist object will be instantiated and called as such:* Skiplist* obj = new Skiplist();* bool param_1 = obj->search(target);* obj->add(num);* bool param_3 = obj->erase(num);*/

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

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

相关文章

Avalonia开发实践(二)——开发带边框的Grid

一、开发背景 在实际开发工作中&#xff0c;常常会用到Grid进行布局。为了美观考虑&#xff0c;会给每个格子加上边框&#xff0c;如下图&#xff1a; 原生的Grid虽然有ShowGridLines属性可以控制显示格子之间的线&#xff0c;但线的样式不能定义&#xff0c;可以说此功能非常…

Java面试八股之MySQL中int(10)和bigint(10)能存储读的数据大小一样吗

MySQL中int(10)和bigint(10)能存储读的数据大小一样吗 在MySQL中&#xff0c;int(10)和bigint(10)的数据存储能力并不相同&#xff0c;尽管括号内的数字&#xff08;如10&#xff09;看起来似乎暗示着某种关联&#xff0c;但实际上这个数字代表的是显示宽度&#xff0c;而不是…

初创企业:如何执行OKR周期?

对于早期创业公司&#xff0c;Tita的OKR教练关于执行OKR周期推荐不是“季度年度”&#xff0c;而是一下三个执行周期&#xff1a; 一个月&#xff1a;”这个月我们在做什么 “是关键问题 团队负责人在月末前的周一上午聚在一起&#xff0c;记录下一个月的功能发布。这是一个自…

探索 Apache Paimon 在阿里智能引擎的应用场景

摘要&#xff1a;本文整理自Apache Yarn && Flink Contributor&#xff0c;阿里巴巴智能引擎事业部技术专家王伟骏&#xff08;鸿历&#xff09;老师在 5月16日 Streaming Lakehouse Meetup Online 上的分享。内容主要分为以下三个部分&#xff1a; 一、 阿里智能引擎…

Pytorch(笔记7损失函数类型)

前言 损失函数&#xff08;Loss Function&#xff09;&#xff1a;是定义在单个样本上的&#xff0c;是指一个样本的误差&#xff0c;度量模型一次预测的好坏。 代价函数&#xff08;Cost Function&#xff09;成本函数经验风险&#xff1a;是定义在整个训练集上的&#xff0c…

LNMP搭建Discuz和Wordpress

1、LNMP L:linux操作系统 N&#xff1a;nginx展示前端页面web服务 M&#xff1a;mysql数据库&#xff0c;保存用户和密码&#xff0c;以及论坛相关的内容 P&#xff1a;php动态请求转发的中间件 数据库的作用&#xff1a; 登录时验证用户名和密码 创建用户和密码 发布和…

RightFont 8.7.0 Mac专业字体管理工具

RightFont 适用于 macOS 的终极字体管理器应用程序&#xff0c;提供无缝的字体管理体验。它结合了速度、直观的功能和专业的功能&#xff0c;使用户能够轻松预览、安装、组织和共享字体。 RightFont 8.7.0 Mac下载 RightFont 8.0的新增功能 RightFont 8.0 带来了全新的智能选…

软件架构之系统性能评价

软件架构之系统性能评价 第 5 章 系统性能评价5.1 性能指标5.1.1 计算机 5.1.2 网络5.3 性能设计5.3.1 阿姆达尔解决方案5.3.2 负载均衡 5.4 性能评估5.4.1 基准测试程序5.4.2 Web 服务器的性能评估5.4.3 系统监视 第 5 章 系统性能评价 系统性能是一个系统提供给用户的众多性…

互联网3.0时代的变革者:华贝甄选大模型创新之道

在当今竞争激烈的商业世界中&#xff0c;华贝甄选犹如一颗璀璨的明星&#xff0c;闪耀着独特的光芒。 华贝甄选始终将技术创新与研发视为发展的核心驱动力。拥有先进的研发团队和一流设施&#xff0c;积极探索人工智能、大数据、区块链等前沿技术&#xff0c;为用户提供高性能…

PostgreSQL 如何解决数据迁移过程中的数据类型不匹配问题?

文章目录 一、了解常见的数据类型不匹配情况1. 整数类型差异2. 浮点数类型差异3. 字符类型差异4. 日期和时间类型差异 二、解决数据类型不匹配的一般策略1. 数据转换2. 调整数据库表结构3. 数据清洗和预处理 三、PostgreSQL 中的数据类型转换函数1. 数值类型转换2. 字符类型转换…

Mysql数据库两表连接进行各种操作

一&#xff0c;创建两个表emp和dept&#xff0c;并给它们插入数据 1.创建表emp create table dept (dept1 int ,dept_name varchar(11)) charsetutf8; 2.创建表dept create table emp (sid int ,name varchar(11),age int,worktime_start date,incoming int,dept2 int) cha…

CSS技巧专栏:一日一例 2.纯CSS实现 多彩边框按钮特效

大家好,今天是 CSS技巧一日一例 专栏的第二篇《纯CSS实现多彩边框按钮特效》 先看图: 开工前的准备工作 正如昨日所讲,为了案例的表现,也处于书写的习惯,在今天的案例开工前,先把昨天的准备工作重做一遍。 清除浏览器的默认样式定义页面基本颜色设定body的样式清除butt…

同步时钟系统支持多种校时方式

在当今数字化、信息化高速发展的时代&#xff0c;时间的准确性和同步性变得至关重要。无论是金融交易、通信网络、交通运输&#xff0c;还是工业生产、科学研究等领域&#xff0c;都离不开一个精确且同步的时钟系统。而同步时钟系统之所以能够在众多领域发挥关键作用&#xff0…

【网络安全】Host碰撞漏洞原理+工具+脚本

文章目录 漏洞原理虚拟主机配置Host头部字段Host碰撞漏洞漏洞场景工具漏洞原理 Host 碰撞漏洞,也称为主机名冲突漏洞,是一种网络攻击手段。常见危害有:绕过访问控制,通过公网访问一些未经授权的资源等。 虚拟主机配置 在Web服务器(如Nginx或Apache)上,多个网站可以共…

论文阅读 - Intriguing properties of neural networks

Intriguing properties of neural networks 经典论文、对抗样本领域的开山之作 发布时间&#xff1a;2014 论文链接: https://arxiv.org/pdf/1312.6199.pdf 作者&#xff1a;Christian Szegedy, Wojciech Zaremba, Ilya Sutskever, Joan Bruna, Dumitru Erhan, Ian Goodfellow,…

AI会取代建筑设计师们的工作吗?

随着人工智能技术的不断进步和革新&#xff0c;几乎每一个行业都在经历深刻的变革和重新定义&#xff0c;建筑可视化也不例外。无论是通过智能算法生成高度逼真的三维模型&#xff0c;还是利用机器学习优化渲染过程&#xff0c;AI都在为建筑可视化注入新的活力&#xff0c;改变…

Redis配置主从服务器报错:Error condition on socket for SYNC: No route to host

Redis配置主从服务器报错&#xff1a;Error condition on socket for SYNC: No route to host 问题方法开放防火墙端口策略额外的检查 这个问题时常出现在配置Redis的主从服务器时出现&#xff0c;无法建立TCP连接。如果需要建立多个主从服务器&#xff0c;并且有 主 -> 从…

数据结构 —— Dijkstra算法

数据结构 —— Dijkstra算法 Dijkstra算法划分集合模拟过程打印路径 在上次的博客中&#xff0c;我们解决了使用最小的边让各个顶点连通&#xff08;最小生成树&#xff09; 这次我们要解决的问题是现在有一个图&#xff0c;我们要找到一条路&#xff0c;使得从一个顶点到另一个…

【Linux】网络新兵连

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 引言 在上一篇博客中&#xff0c;我们简单的介绍了一些Linux网络一些比较基本的概念。本篇博客我们将开始正式学习Linux网络套接字的内容&#xff0c;那么我们开始吧&#xff01; 1.网络中的地址管理 大家一…

2024年 春秋杯 网络安全联赛夏季赛 Web方向 题解WirteUp 部分

brother 题目描述&#xff1a;web哥&#xff0c;打点容易提权难。 打点就是最简单的SSTI。 执行下find / -user root -perm -4000 -print 2>/dev/null找一下具备suid权限的命令 /usr/lib/dbus-1.0/dbus-daemon-launch-helper /usr/bin/chsh /usr/bin/gpasswd /usr/bin/n…