map 和 set 使用及模拟实现
1.关联式容器之前接触的STL中的部分容器比如vectorlistdequeforward_list(C11)等这些统称为序列式容器因为其底层为线性序列的数据结构里面存储的是元素本身。关联式容器也是用来存储数据的与序列式容器不同的是其里面存储的是keyvalue结构的键值对在数据检索时比序列式容器效率更高。2.键值对用来表示具有一一对应关系的一种结构该结构中一般只包含两个成员变量key和valuekey代表键值value表示与key对应的信息。3.树形结构的关联式容器STL总共实现了两种不同的关联式容器树形结构与哈希结构。树形结构的关联式容器主要有四种mapsetmultimapmultiset。这四种容器的共同点是使用平衡搜索树(即红黑树)作为其底层结果容器中的元素是一个有序的列。3.1 setset 中只存放 value 值且每个 value 必须唯一。set 中元素不能修改(元素是const)只可以插入删除。插入元素时只需要插入 value不需要构造键值对。set 中元素不可以重复可以使用它进行去重按小于来比较遍历即可得到有序序列。3.2 mapmap 是关联式容器它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。在元素访问时与operator[]类似的操作at()(该函数不常用)函数都是通过key找到与key对应的value然后返回其引用不同的是当key不存在时operator[]用默认value与key构造键值对然后插入返回该默认valueat()函数直接抛异常。3.3 multiset multiset是按照特定顺序的容器其中元素可以重复的。在 multiset 中元素的value也会识别它(因为 multiset 中本身存储的就是value, value组成的键值对因此 value 本身就是 keykey 就是 value类型为 T)multiset 元素的值不能在容器中修改(因为元素总是 const)可以插入删除。set 与 multiset 的接口相同不作展示唯一区别就是可存储重复元素。3.4 multimap同上 multimap 和 map 的唯一不同是map 中 key 值唯一multimap 中 key 是可以重复的。4.底层结构map/multimap/set/multiset 其底层结构都是二叉搜索树实现的但是二叉搜索树有其缺陷假如往树中插入的元素有序便会退化为单支树时间复杂度便会退化为O(N)因此对其进行了平衡处理即二叉平衡树(AVL)。4.1 AVL树一棵AVL树或者是空树或者是左右都是AVL树、左右子树高度差(简称平衡因子)的绝对值不超过1(-1/0/1)的二叉搜索树。AVL树的旋转1新结点插入较高左子树的左侧——左左右单旋2新结点插入较高右子树的右侧——右右左单旋3新结点插入较高左子树右侧——左右先左单旋在右单旋(先旋转再考虑平衡因子更新)4新结点插入较高右子树左侧——右左先右单旋再左单旋AVL树实现#pragma once #include iostream #include assert.h using namespace std; templateclass K, class V struct AVLTreeNode { pairK, V _kv; AVLTreeNodeK, V* _pleft; AVLTreeNodeK, V* _pright; AVLTreeNodeK, V* _parent; int _bf;//平衡因子 AVLTreeNode(const pairK, V kv) :_kv(kv) ,_pleft(nullptr) ,_pright(nullptr) ,_parent(nullptr) ,_bf(0) {} }; templateclass K, class V class AVLTree { typedef AVLTreeNodeK, V Node; public: bool Insert(const pairK, V kv) { if (_root nullptr) { _root new Node(kv); return true; } Node* parent _root; Node* cur _root; while (cur) { if (cur-_kv.first kv.first) { parent cur; cur cur-_pright; } else if (cur-_kv.first kv.first) { parent cur; cur cur-_pleft; } else { return false; } } cur new Node(kv); if (parent-_kv.first kv.first) { parent-_pleft cur; } else { parent-_pright cur; } cur-_parent parent; //控制平衡 //1.新增在左parent平衡因子减减 //2.新增在右parent平衡因子加加 //3.更新后parent平衡因子 0说明parent所在子树高度不变不会影响祖先 //4.更新后parent平衡因子 -1 or 1说明parent所在子树高度变化会影响祖先需继续沿着到root的路径往上更新 //5.更新后parent平衡因子 -2 or 2说明parent所在子树高度变化且不平衡对parent所在子树进行旋转让它平衡 //更新平衡因子 while (parent)//更新到根节点结束 { if (cur parent-_pleft) { parent-_bf--; } else { parent-_bf; } if (parent-_bf 0) { break;//结束 } else if (parent-_bf -1 || parent-_bf 1) { //继续往上更新 cur parent; parent parent-_parent; } else if (parent-_bf -2 || parent-_bf 2) { //子树不平衡了需要旋转 if (parent-_bf 2 cur-_bf 1)//左单旋 { RotateL(parent); } else if (parent-_bf -2 cur-_bf -1) { RotateR(parent); } else if (parent-_bf 2 cur-_bf -1) { RotateRL(parent); } else if (parent-_bf -2 cur-_bf 1) { RotateLR(parent); } break; } else { assert(false); } } return true; } void RotateL(Node* parent) { Node* cur parent-_pright; Node* curleft cur-_pleft; Node* pparent parent-_parent; parent-_pright curleft; if (curleft) { curleft-_parent parent; } cur-_pleft parent; parent-_parent cur; if (parent _root) { _root cur; cur-_parent nullptr; } else { if (pparent-_pleft parent) { pparent-_pleft cur; } else { pparent-_pright cur; } cur-_parent pparent; } parent-_bf cur-_bf 0; } void RotateR(Node* parent) { Node* cur parent-_pleft; Node* curright cur-_pright; Node* pparent parent-_parent; parent-_pleft curright; if (curright) { curright-_parent parent; } cur-_pright parent; parent-_parent cur; if (parent _root) { cur-_parent nullptr; _root cur; } else { if (pparent-_pleft parent) { pparent-_pleft cur; } else { pparent-_pright cur; } cur-_parent pparent; } parent-_bf cur-_bf 0; } void RotateRL(Node* parent) { Node* cur parent-_pright; Node* curleft cur-_pleft; int bf curleft-_bf; RotateR(cur); RotateL(parent); //右左双旋本质是 孙子结点左子树给祖父结点做右子树右子树给父节点做左子树自己变为根节点 if (bf 0) { parent-_bf 0; cur-_bf 0; curleft-_bf 0; } else if (bf -1) { parent-_bf 0; cur-_bf 1; curleft-_bf 0; } else if (bf 1) { parent-_bf -1; cur-_bf 0; curleft-_bf 0; } else { assert(false); } } void RotateLR(Node* parent) { Node* cur parent-_pleft; Node* curright cur-_pright; int bf curright-_bf; RotateL(cur); RotateR(parent); //左右双旋是 孙子节点左子树给父节点做右子树右子树给祖父节点做左子树自己变成根节点 if (bf 0) { parent-_bf 0; cur-_bf 0; curright-_bf 0; } else if (bf -1) { parent-_bf 1; cur-_bf 0; curright-_bf 0; } else if (bf 1) { parent-_bf 0; cur-_bf -1; curright-_bf 0; } } bool IsBalance() { return _IsBalance(_root); } bool _IsBalance(Node* root) { if (root nullptr) return true; int leftHight Height(root-_pleft); int rightHight Height(root-_pright); return abs(rightHight - leftHight) 2 _IsBalance(root-_pleft) _IsBalance(root-_pright); } int Height(Node* root) { if (root nullptr) { return 0; } int leftHight Height(root-_pleft); int rightHight Height(root-_pright); if (rightHight - leftHight ! root-_bf) { cout 平衡因子异常 root-_kv.first - root-_bf endl; return false; } return leftHight rightHight ? leftHight 1 : rightHight 1; } private: Node* _root nullptr; };4.2红黑树是一种二叉搜索树但每个结点上增加一个存储位表示结点的颜色可以是Red或Black。通过对任何一条从根到叶子的路径上各个结点着色方式的限制红黑树确保没有一条路径会比其他路径长出两倍因为是接近平衡的。红黑树的性质1每个结点不是黑色就是红色2根结点是黑色3如果一个结点是红色的则它两个孩子都是黑色的4对于每个结点从该结点到其所有后代叶结点的简单路径均包含相同数目的黑色结点5每个叶子结点都是黑色的(此处叶子节点指的空结点)红黑树的插入操作1按照二叉搜素树规则插入新结点2检测新结点插入后红黑树的性质是否遭到破坏因为新结点的默认颜色是红色因此如果其双亲结点的颜色是黑色没有违反红黑树任何性质则不需要调整但当新插入结点的双亲结点颜色为红色时就违反了性质三不能有连续红色结点需分情况讨论。(cur 为当前结点p为父结点g为祖父结点u为叔叔结点)1cur 为红p 为红g 为黑u 存在且为红解决方式将p、u 改为黑g 改为红然后把 g 当成 cur继续向上调整。2cur 为红p 为红g 为黑u 不存在/u存在且为黑解决方式p 为 g 的左孩子cur 为 p 的左孩子则进行右单旋转相反p 为 g 的右孩子cur 为 p 的右孩子则进行左单旋最后 p、g 变色——p 变黑g 变红。3cur 为红p 为红g 为黑u 不存在/u存在且为黑解决方式p 为 g 的左孩子cur 为 p 的右孩子则针对 p 做左单旋转相反p 为g 的右孩子cur 为 p 的左孩子则针对 p 做右单旋转最后则转换成了情况2(双旋)。红黑树模拟实现 STL 中的 map 与 set(暂略)

相关新闻

ViGEmBus虚拟手柄驱动终极教程:让任何控制器都能畅玩PC游戏

ViGEmBus虚拟手柄驱动终极教程:让任何控制器都能畅玩PC游戏

ViGEmBus虚拟手柄驱动终极教程:让任何控制器都能畅玩PC游戏 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus 你是否遇到过这样的尴尬时刻&#xf…

2026/10/20 14:03:49 阅读更多 →
怎样高效使用FunClip:本地AI视频剪辑完整教程

怎样高效使用FunClip:本地AI视频剪辑完整教程

怎样高效使用FunClip:本地AI视频剪辑完整教程 【免费下载链接】FunClip FunASR-powered video transcription, subtitle generation, and LLM-assisted clipping tool with a local Gradio UI. 项目地址: https://gitcode.com/GitHub_Trending/fu/FunClip Fu…

2026/10/20 14:24:59 阅读更多 →
黄瓜病害识别数据集

黄瓜病害识别数据集

摘要:黄瓜病害识别数据集(Cucumber Disease Recognition Dataset)是一个用于黄瓜病害分类和检测的图像数据集。数据集简介数据集概述黄瓜病害识别数据集(Cucumber Disease Recognition Dataset)是一个用于黄瓜病害分类…

2026/10/20 7:26:08 阅读更多 →

最新新闻

MCP Server 集群化部署:从 Docker 到 Kubernetes 的完整实践

MCP Server 集群化部署:从 Docker 到 Kubernetes 的完整实践

我在团队里负责 AI 基础服务,前几个月被 MCP Server 折腾得够呛。MCP 是模型上下文协议,说白了就是让大语言模型能通过标准化接口调用外部工具和数据源。最开始我们每个人在本机起一个 MCP Server,工具定义各改各的,代码一更新就要…

2026/10/20 14:49:35 阅读更多 →
从零搭建SpringBoot+Vue商城系统:核心设计与部署全攻略

从零搭建SpringBoot+Vue商城系统:核心设计与部署全攻略

自己动手把一套网上商城从零搭到能上线,这事听起来工程量大,实际上踩完一轮坑之后回头看,最值钱的不是那几万行代码,而是整个链路里每个环节你都知道它为什么这么设计。这个项目用的是Java后端技术栈里最经典的组合:Sp…

2026/10/20 14:49:34 阅读更多 →
innodb_flush_log_at_trx_commit全解析:性能与数据安全如何取舍

innodb_flush_log_at_trx_commit全解析:性能与数据安全如何取舍

做MySQL维护和调优的朋友,十有八九都听过innodb_flush_log_at_trx_commit这个参数。有人叫它“安全开关”,有人说它是“性能与数据安全的天平”,其实都不过分。很多压测报告里,把这个参数从1改成2,TPS能肉眼可见地涨一…

2026/10/20 14:49:34 阅读更多 →
MCP Server云原生集群化实战:Docker与K8s弹性伸缩指南

MCP Server云原生集群化实战:Docker与K8s弹性伸缩指南

MCP(Model Context Protocol)这两年火得很快,身边搞 AI 应用的同学几乎都在接。但大部分人把 MCP Server 部署得比较随意——一台机器,一个进程,能跑就行。直到流量上来、工具越接越多,才发现单机模式处处碰…

2026/10/20 14:49:34 阅读更多 →
MySQL参数详解:innodb_flush_log_at_trx_commit的性能与安全取舍

MySQL参数详解:innodb_flush_log_at_trx_commit的性能与安全取舍

我处理过不少数据库卡顿和“丢了几秒数据”的现场,最后基本都绕回到一个老参数上: innodb_flush_log_at_trx_commit 。它字面意思很简单,就是控制事务提交时InnoDB怎么刷redo log,可真正把它讲透、用对的人并不多。很多后端开发…

2026/10/20 14:49:34 阅读更多 →
Frida动态插桩实战:从Hook到内存扫描的完整指南

Frida动态插桩实战:从Hook到内存扫描的完整指南

做移动端安全测试这些年,我见过太多人把大量时间花在反编译和读汇编上,遇到加了壳的应用就只能干瞪眼。后来我开始把 Frida 动态插桩作为主要分析手段,很多原本要折腾半天的任务,现在几分钟就能拿到结果。这篇文章我会从最基础的 …

2026/10/20 14:48:08 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →