数据结构(四) B树/跳表
目录
1. LRU
2. B树
3. 跳表
1. LRU:
1.1 概念:
最近最少使用算法, 就是cache缓存的算法. 因为cache(位于内存和cpu之间的存储设备)是一种容量有限的缓存, 有新的数据进入就需要将原本的数据进行排出.
1.2 LRU cache实现:
#include <iostream>
#include <list>
#include <unordered_map>using namespace std;class LRUCache
{
public:LRUCache(int capacity){_capacity = capacity;}//获取数据.int get(int key){//找到数据key的值.auto hashit = _hashmap.find(key);if(hashit != _hashmap.end()){//找到对应关键词auto listit = hashit->second;pair<int, int> kv = *listit;//删除原来对应关键词数据;_list.erase(listit);//现在头插关键词数据._list.push_front(kv);//然后改变一下hashmap的key的值.._hashmap[key] = _list.begin();return kv.second;}else{return -1;}}//插入新的数据.key,value类型的.void put(int key, int value){auto hashit = _hashmap.find(key);if(hashit == _hashmap.end()){//找不到对应的数据;if(_list.size() >= _capacity){//大于容量._hashmap.erase(_list.back().first);//删除最后一个数据.(这个数据很久没访问过的);_list.pop_back();}_list.push_front(make_pair(key, value));_hashmap[key] = _list.begin();}else{auto listit = hashit->second;pair<int, int> kv = *listit;kv.second = value;_list.erase(listit);_list.push_front(kv);_hashmap[key] = _list.begin();}}private://链表保存各个cache里的数据.list<pair<int, int>> _list;size_t _capacity;//使用下标和cache数据指针进行映射.unordered_map<int, list<pair<int, int>>::iterator> _hashmap;
};
2. B树:
2.1 常见的搜索结构:
顺序查找O(N), 二分查找O(logN), 二叉搜索树O(N), 二叉平衡树O(logN), 哈希O(1);
这些查找算法只能在数据量比较少, 以及内存可以一次进行寻找的, 如果数据量很大, 那么数据一次无法放到内存只能在磁盘中. 那么内存和磁盘进行交互的话时间就比较慢.
2.2 B树的概念:
一种平衡多叉树, 可以进行外查找的. 一棵M阶多叉树, 是一个平衡M路的平衡多叉树.满足性质:
(1) 根结点至少有两个孩子;
(2) 每个分支结点都包含k-1个关键字和k个孩子. 其中k的取值在[m/2, m]之间.
(3) 每个叶子结点都包含k-1个关键词; k的取值[m/2, m];
(4) 叶子结点都在一层, (5) 每个结点从小到大排序.
2.3 B树的插入分析:
下面拿三叉树来举例, M = 3, 那么每个结点可以最多存储2个数据(k范围[1, 3), k-1个关键词; 孩子的话永远比数据多一个, 就是3个孩子.
插入数据74, 49, 139, 145, 36, 53的过程. 如果结点满就需要分裂.
2.4 B树的实现:
(1) 结构:
采用一个关键词数组以及存放关键词的孩子结点, 还有一个保存关键词的父亲结点.
//类型为k, 数量为M.
//M层数.
template<class K, size_t M>
struct BTreeNode
{//创建关键词数组; 以及相对应的孩子结点.K _keys[M];//孩子结点的指针.BTreeNode<K, M>* _subs[M+1];BTreeNode<K, M>* _parent;//记录存储关键字数.size_t _n;BTreeNode(){for(size_t i = 0; i < M; i++){_keys[i] = K();_subs[i] = nullptr;}_subs[M] = nullptr;_parent = nullptr;_n = 0;}
};template<class K, size_t M>
class BTree
{typedef BTreeNode<K, M> Node;private:Node* _root = nullptr;
};
(2) 查找:
//查找数据:pair<Node*, int> Find(const K& key){Node* parent = nullptr;Node* cur = _root;//遍历B树结点.while(cur){size_t i = 0;while(i < cur->_n){//小于关键词不存在.if(key < cur->_keys[i]){break;}//大于就在右边.else if(key > cur->_keys[i]){i++;}else{//相等返回cur结点以及下标位置.return make_pair(cur, i);}}//本关键词找不到就到另外一个关键词查看.parent = cur;cur = cur->subs[i];}//找不到就返回空.return make_pair(parent, -1);}
(3) 插入关键字:
如果满了首先找到中间结点, 中间结点的后面结点移动新结点, 然后中间结点放到parent数组中.
//
(4) 遍历关键词:
遍历每个结点的孩子结点, 先左子树, 再根, 后右子树即可.
void _InOrder(Node* cur){if(cur == nullptr)return;size_t i = 0;for(; i < cur->_n; i++){//先遍历左子树._InOrder(cur->_subs[i]);//打印根子树.cout << cur->_keys[i] << " ";}//再去遍历右子树._InOrder(cur->_subs[i]);}
(5) B树性能分析:
查找效率大概就是O(logM-1)到O(logm/2); 查询到结点就再使用二分查找很快就可以找到. l例如620亿个数据, 树的度是1024的话, 最多需要查询4次. 这样就可以减少磁盘io次数.
2.5 B+树:
在B树上做了些修改: (1) 分支节点的子树指针和关键字个数相同;
(2) 叶子结点增加一个连接指针将叶子结点连接在一起.
(3) 分支节点的子树指针p[i]指向关键字值大小在[k[i],k[i+1])区间之间
(4) 所有关键字及其映射数据都在叶子节点出现
所有的关键字都出现在叶子结点的链表中, 并且有序;
不可能在分支结点命中, 分支结点相当与是叶子结点的索引, 叶子结点才是真正存储数据的.
B+树的增加只会改变原结点以及父结点, 因为将一半结点给兄弟结点, 源节点给父亲结点即可.
2.6 B*树:
B+树的变形, 增加非叶子结点和非根结点的链表指针.
B*树增加数据就要将看兄弟结点没满就将数据插入到兄弟结点中, 其次就是满的话将数据创建一个新的结点, 然后将1/3数据给新结点, 重新修改一下父结点的指向孩子的指针.
2.6 总结:
(1) B树: 有序数组和平衡多叉树;
(2) B+树: 有序数组链表和平衡多叉树;
(3) B*树: 一个饱满, 均匀, 空间利用率高的B+树.
2.7 B树的运用:
在MySQL中使用到索引, 高效获取数据的数据结构, 索引在于表, 而不是数据库.
(1) MyISAM: (非聚簇索引)
不支持事务, 支持全文索引, 叶子结点存放的是数据的地址. 包含主索引和辅助索引, 主索引的key不能重复, 辅助索引可以. 这种数据和索引不在一起的就是非聚簇索引.
(2) Innodb:
支持事务, 支持B+树索引、全文索引、哈希索引。它是将数据和索引存放在一起; 数据存储的是值不是地址, 这种就是聚簇索引.
3. 跳表:
3.1 概念:
相关文章:

数据结构(四) B树/跳表
目录 1. LRU 2. B树 3. 跳表 1. LRU: 1.1 概念: 最近最少使用算法, 就是cache缓存的算法. 因为cache(位于内存和cpu之间的存储设备)是一种容量有限的缓存, 有新的数据进入就需要将原本的数据进行排出. 1.2 LRU cache实现: #include <iostream> #include <list>…...

Arcgis国产化替代:Bigemap Pro正式发布
在数字化时代,数据如同新时代的石油,蕴含着巨大的价值。从商业决策到科研探索,从城市规划到环境监测,海量数据的高效处理、精准分析与直观可视化,已成为各行业突破发展瓶颈、实现转型升级的关键所在。历经十年精心打磨…...

LBS 开发微课堂|AI向导接口服务:重塑用户的出行体验
为了让广大开发者 更深入地了解 百度地图开放平台的 技术能力 轻松掌握满满的 技术干货 更加简单地接入 位置服务 我们特别推出了 “位置服务(LBS)开发微课堂” 系列技术案例 第六期的主题是 《AI向导接口服务的能力与接入方案》 随着地图应…...

AI导航工具我开源了利用node爬取了几百条数据
序言 别因今天的懒惰,让明天的您后悔。输出文章的本意并不是为了得到赞美,而是为了让自己能够学会总结思考;当然,如果有幸能够给到你一点点灵感或者思考,那么我这篇文章的意义将无限放大。 背景 随着AI的发展市面上…...

openstack单机安装
openstack单机安装 网卡配置安装依赖开启虚拟环境修改配置文件 部署openstack部署openstack客户端访问可视化界面Horizon补充 本篇主要讲述Ubuntu2204单机安装openstackstable/2024.2。其他版本的Linux系统或者openstack版本,请参考openstack官网。 网卡配置 需要配…...

Vue3实现小红书瀑布流布局任意组件动态更新页面方法实践
思路 1.首先定义一个瀑布流容器,它的高度暂定(后面会更新)。把需要布局的组件(这里叫做waterfall-item)放在瀑布流容器里面渲染出来。使用绝对定位(position: absolute),把它移到屏幕…...

深度学习项目--基于LSTM的糖尿病预测探究(pytorch实现)
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 前言 LSTM模型一直是一个很经典的模型,一般用于序列数据预测,这个可以很好的挖掘数据上下文信息,本文将使用LSTM进行糖尿病…...
Next.js 实战 (十):中间件的魅力,打造更快更安全的应用
什么是中间件? 在 Next.js 中,中间件(Middleware)是一种用于处理每个传入请求的功能。它允许你在请求到达页面之前对其进行修改或响应。 通过中间件,你可以实现诸如日志记录、身份验证、重定向、CORS配置、压缩等任务…...
python+playwright自动化测试(四):元素操作(键盘鼠标事件)、文件上传
目录 鼠标事件 悬停 移动 按键 点击 滚轮操作 拖拽 键盘事件 输入文本内容 type输入内容 fill输入内容 按键操作press 文件上传 下拉选/单选框/复选框 滚动条操作 鼠标事件 悬停 page.get_by_text(设置,exactTrue).nth(1).hover() 移动 page.mouse.move(x33…...

【论文+源码】Diffusion-LM 改进了可控文本生成
这篇论文探讨了如何在不重新训练的情况下控制语言模型(LM)的行为,这是自然语言生成中的一个重大开放问题。尽管近期一些研究在控制简单句子属性(如情感)方面取得了成功,但在复杂的细粒度控制(如…...

双目立体校正和Q矩阵
立体校正 对两个摄像机的图像平面重投影,使二者位于同一平面,而且左右图像的行对准。 Bouguet 该算法需要用到双目标定后外参(R,T) 从上图中可以看出,该算法主要分为两步: 使成像平面共面 这个办法很直观ÿ…...
vscode 自用插件
vscode按住ctrl鼠标左键无法跟踪跳转方法名,装这些插件就可以 vscode-elm-jump:常规的代码跳转定义 Vue CSS Peek:跳转css定义 vue-helper:变量函数只跳转定义 Vetur 代码提示 Baidu Comate 自动帮你写console.log Turbo Console Log: ctrl alt l 选中变量之后&am…...

OpenCV:在图像中添加高斯噪声、胡椒噪声
目录 在图像中添加高斯噪声 高斯噪声的特性 添加高斯噪声的实现 给图像添加胡椒噪声 实现胡椒噪声的步骤 相关阅读 OpenCV:图像处理中的低通滤波-CSDN博客 OpenCV:高通滤波之索贝尔、沙尔和拉普拉斯-CSDN博客 OpenCV:图像滤波、卷积与…...

DuckDB:Golang操作DuckDB实战案例
DuckDB是一个嵌入式SQL数据库引擎。它与众所周知的SQLite非常相似,但它是为olap风格的工作负载设计的。DuckDB支持各种数据类型和SQL特性。凭借其在以内存为中心的环境中处理高速分析的能力,它迅速受到数据科学家和分析师的欢迎。在这篇博文中࿰…...
MySQL入门(数据库、数据表、数据、字段的操作以及查询相关sql语法)
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...
kotlin的协程的基础概念
Kotlin的协程是一种用于简化异步编程的强大工具。 理解协程的基础概念可以帮助开发者有效地利用其能力。 以下是Kotlin协程的一些关键基础概念: 协程(Coroutines) : 协程是一种用于处理并发任务的编程模型,它可以在单…...

Spring--SpringMVC使用(接收和响应数据、RESTFul风格设计、其他扩展)
SpringMVC使用 二.SpringMVC接收数据2.1访问路径设置2.2接收参数1.param和json2.param接收数据3 路径 参数接收4.json参数接收 2.3接收cookie数据2.4接收请求头数据2.5原生api获取2.6共享域对象 三.SringMVC响应数据3.1返回json数据ResponseBodyRestController 3.2返回静态资源…...

隐藏php版本信息x-powered-by
在生产环境中,并不想让别人知道用的是什么版本的php,可以把x-powered-by隐藏掉 在nginx配置文件加上fastcgi_hide_header X-Powered-By; 如下图所示 配置修改后平滑重启nginx...

哈夫曼树(构建、编码、译码)(详细分析+C++代码实现)
D 哈夫曼树 题目要求 编写一个哈夫曼编码译码程序。针对一段文本,根据文本中字符出现频率构造哈夫曼树,给出每个字符的哈夫曼编码,并进行译码,计算编码前后文本大小。 为确保构建的哈夫曼树唯一,本题做如下限定&…...

C++ 二叉搜索树
目录 概念 性能分析 二叉搜索树的插入 二叉树的查找 二叉树的前序遍历 二叉搜索树的删除(重点) 完整代码 key与value的使用 概念 对于一个二叉搜索树 若它的左子树不为空,则左子树上所有的节点的值都小于等于根节点的值若它的右子树不为空…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...