C++map和set(二)

1.map的opeator[]

功能:

如果访问对象存在就返回指定键的值的引用,如果指定的键不存在会插入新的键值对,键是传递给operator[]的参数,值是使用该值类型的默认构造函数构造的(对于简单类型通常是0或者空字符)。

代码示例:

int main()
{map<string, string> dict;dict.insert(make_pair("sort", "排序"));//key不存在->插入{"insert","string()"}dict["insert"];//key不存在->插入+修改dict["left"] = "左边";//key存在->修改dict["left"] = "z边";//查找 确定存在key使用,不然就插入了cout << dict["left"] << endl;return 0;
}

2.map的insert

插入成功会返回插入值所咋位置的迭代器,并且bool为true,插入失败说明已经存在,这会返回存在位置的迭代器,并且bool为false

3.operator的内部实现

这里有俩个pair需要注意,第一个是iterator和bool的,it指向的是map的某个元素,而map的元素也有pair键值对,所以it也有second,second是值。

4.例题

题目:

代码讲解:

 首先要把接受的words进行处理,把重复的累计起来,使用map可以得到{”单词名字“,"出现的次数"},然后可以提供排序去找到最多次的前几个,但是map是不能排序,因为map是只能排键值(会按照字典顺序排序好),所以我们可以用vector或者multiset等,pair是可以比较的,它是比较键值和值,先比较键值,然后比较值大小,关系是 ||,前面大就大,只有俩个一样才相等,但是我们只比较值大小,所以要自定义仿函数,只比较值大小(second),这里用sort的函数会导致一部分案例不通过,是因为sort快排是不稳定的排序,在相等值时可能会改变前后顺序,但是题目要求要字典顺序,sort会破坏前面map排序好的字典顺序,所以要用stable_sort,看名字就知道是稳定的快排,最后取出前k个放到vector里面,就完成了。

class Solution {
public:struct Compare{bool operator()(const pair<std::string,int>& left,const pair<std::string,int>& right) const{return left.second > right.second;}};vector<string> topKFrequent(vector<string>& words,int k){map<string,int> m;for(size_t i=0;i<words.size();i++)++(m[words[i]]);vector<pair<string,int>> v(m.begin(),m.end());stable_sort(v.begin(),v.end(),Compare());vector<string> str;for(size_t i=0;i<k;i++){str.push_back(v[i].first);}return str;}
};

 5.AVL树概念

AVL树是最先发明的自平衡树,AVL是空树,或者具备下列性质的二叉搜索树:左右子树都是AV树,且左右子树的高度差绝对值不超过1.AVL树是一颗高度平衡搜索二叉树,通过控制高度差去控制平衡。

AVL树实现引入平衡因子(balance factor)的概念,每个节点都有一个平衡因子,任何节点的平衡因子等于左右子树的高度,也就是说任何节点的平衡因子等于-1/0/1,AVL并不是必须要平衡因子,但是有了平衡因子方便我们去进行观察和控制树是否平衡。

AVL树整体结点数量和分布完全二叉树相似,高度可以控制在logN,那么增删查改的效率可以控制在0(logN).

平衡因子更新

更新原则:

平衡因子=右子树高度-左子树高度

只有子树高度变化才会影响当前结点平衡因子

插入结点,会增加高度,所以新增结点在parent的右子树,parent的平衡因子++,新增结点在parent的左子树,parent平衡因子--。

parent所咋子树高度是否变化决定了是否会继续晚上更新平衡因子

更新停止条件:

更新后parent的平衡因子等于0,更新中的parent的平衡因子变化为-1->0或者1->0,说明更新前parent子树一边高一边底,即新增的结点插入在低的那一边,插入后parent所在的子树高度不变,不会影响parent的父亲结点的平衡因子,更新结束。

更新后的parent的平衡因子等于1/-1,更新前parent的平衡因子变化0->-1或者0->1,说明更新前parent子树俩边一样高,新增结点后,parent所在的子树一边高一边低,parent所在的子树满足平衡要求,但是高度加1,会影响parent的父节点的平衡因子,所以要继续向上更新。

更新后parent的平衡因子等于2/-2,更新前parent的平衡因子变化为1->2或者-1->2,说明更新前parent的子树一边高一边低,新增的插入结点在高的那一边,parent所在的子树高的那边更高了,破坏了平衡,parent所在的子树不符合平衡了,需要旋转处理,旋转目标:1,把parent子树旋转平衡。2,降低parent子树的高度,恢复插入结点之前的高度。所以旋转后也不需要继续往上更新,插入结束。

左单旋

本图展示是10为根的树,有a/b/c抽象为三颗高度为h的子树,a/b/c均符合AVL树的要求。10可能是整棵树的根,也可能是一个整棵树中局部的子树的根。

在a子树插入一个新结点,导致a子树的高度从h变成h+1,不断向上更新平衡因子,导致10的平衡因子从1变到2,10为根的子树左右高度差超过1,违反了平衡。需要旋转。

旋转的核心步骤,因为10<b子树的值<15,将b变为10的右子树,10变为15的左子树,15变成树的新根,符合搜索树的规则,同时这颗树的高度回复到了插入之前的h+2。

右单旋

这里b<10&&b>5,所以把5作为新根,把b旋转到10的左边,高度还是3. 

这里插入新结点后平衡破坏了,所以要旋转,把5作为新根,8到10的左结点,高度不变。

左边插入结点后,根的平衡因子变为2,所以把根10变为结点5的右子树,5为新根。

这里36是x,y和z三种,b和c是其中一种,就是3*3,而插入到a可以为俩个结点的左右俩边就是4种,所以是3*3*4=36。

代码实现

template<class k,class v>
struct AVLTreeNode
{pair<k, v> _kv;AVLTreeNode<k, v>* _left;AVLTreeNode<k, v>* _right;AVLTreeNode<k, v>* _parent;int _bf;//balance factorAVLTreeNode(const pair<k,v>& kv):_kv(kv),_left(nullptr),_right(nullptr),_parent(parent),_bf(0){}};template<class k,class v>
class avltree
{//typedef AVLTreeNode<k, v> Node;using AVLTreeNode < k, v >= Node;
public:bool Insert(const pair<k, v>& kv){if (_root == nullptr){_root = new Node(kv);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node(kv);if (parent->_kv.first < kv.first)parent->_right = cur;elseparent->_left = cur;cur->_parent = parent;while (cur){if (cur == parent->_left)parent->_bf--;elseparent->_bf++;if (parent->_bf == 0)break;else if (parent->_bf == 1 || parent->_bf == -1){//旋转break;}elseassert(false);}}private:Node* _root = nullptr;};

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

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

相关文章

[Linux]多线程详解

多线程 1.线程的概念和理解1.1线程的优点1.2线程的缺点1.3线程的设计1.4线程 VS 进程 2.线程控制2.1线程等待2.2 线程终止2.3 线程分离 3.线程互斥3.1背景3.2抢票代码演示3.3保护公共资源&#xff08;加锁&#xff09;3.3.1创建锁/销毁锁3.3.2申请锁/尝试申请锁/解锁 3.4解决抢…

大学语文教材电子版(第十一版)教学用书PDF及课件

大学语文课件&#xff1a;https://caiyun.139.com/m/i?005CiDusEVWnR 《大学语文》&#xff08;第十一版&#xff09;主编&#xff1a;徐中玉 齐森华 谭帆。 大学语文教材电子版教师用书PDF第一课《齐桓晋文之事》艺术赏析&#xff1a; 孟子四处游说&#xff0c;养成善辩的…

MySQL【七】

字符串函数 数学函数 日期函数 条件控制函数 类型转换函数 系统信息函数 自定义函数 DELIMITER  CREATE FUNCTION 函数名([参数名 参数数据类型[,…]])RETURNS 函数返回值的数据类型BEGIN函数体;RETURN 语句;ENDDELIMITER ;sql ########## 定义一个函数maxofthree()&#x…

第三百二十三节 Java线程教程 - Java同步器

Java线程教程 - Java同步器 同步器对象与一组线程一起使用。 它维护一个状态&#xff0c;根据它的状态&#xff0c;它让一个线程通过或强迫它等待。 本节将讨论四种类型的同步器&#xff1a; SemaphoresBarriersLatchesExchangers 信号量 信号量用于控制可以访问资源的线程…

《Java核心技术 卷I》用户界面AWT事件继承层次

AWT事件继承层次 EventObject类有一个子类AWTEvent&#xff0c;它是所有AWT事件类的父类。 Swing组件会生成更多其他事件对象&#xff0c;都直接拓展自EventObject而不是AWTEvent。 AWT将事件分为底层(low-level)事件和语义事件。 语义事件&#xff1a;表示用户的动作事件&…

Ubuntu从入门到精通(一)系统安装

Ubuntu从入门到精通&#xff08;一&#xff09; 1 Ubuntu镜像选择 下载Ubuntu 20.04系统ISO镜像 安装 Ubuntu 20.04系统,就必须有 Ubuntu 20.04系统软件安装程序可以通过浏览器访问Ubuntu20.04的官方站点&#xff0c; 然后在导舰栏找划 Dowwnloads->Mirrors链接&#xff…

用户自定义IP核——ZYNQ学习笔记6

一、试验任务 通过自定义一个 LED IP 核&#xff0c;通过 PS 端的程序来控制底板上 PL 端 LED1 呈现呼吸 灯的效果&#xff0c;并且 PS 可以通过 AXI 接口来控制呼吸灯的开关和呼吸的频率。 二、创建IP核 三、创建工程&#xff0c;调用IP #include "stdio.h" #includ…

Elasticsearch 8.16.0:革新大数据搜索的新利器

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

python:用 sklearn 构建 K-Means 聚类模型

pip install scikit-learn 或者 直接用 Anaconda3 sklearn 提供了 preprocessing 数据预处理模块、cluster 聚类模型、manifold.TSNE 数据降维模块。 编写 test_sklearn_3.py 如下 # -*- coding: utf-8 -*- """ 使用 sklearn 构建 K-Means 聚类模型 "&…

【大数据学习 | HBASE高级】hive操作hbase

一般在查询hbase的数据的时候我们可以直接使用hbase的命令行或者是api进行查询就行了&#xff0c;但是在日常的计算过程中我们一般都不是为了查询&#xff0c;都是在查询的基础上进行二次计算&#xff0c;所以使用hbase的命令是没有办法进行数据计算的&#xff0c;并且对于hbas…

贴代码框架PasteForm特性介绍之markdown和richtext

简介 PasteForm是贴代码推出的 “新一代CRUD” &#xff0c;基于ABPvNext&#xff0c;目的是通过对Dto的特性的标注&#xff0c;从而实现管理端的统一UI&#xff0c;借助于配套的PasteBuilder代码生成器&#xff0c;你可以快速的为自己的项目构建后台管理端&#xff01;目前管…

ServletConfig、ServletContext、HttpServletRequest与HttpServletResponse常见API

目录 一、ServletConfig 二、ServletContext 三、ServletContext其他重要API (一)获取文件路径和上下文 (二)域对象的相关API 四、HttpServletRequest常见API (一)获取请求行/头信息相关 (二)获得请求参数相关 五、HttpServletResponse常见API 一、ServletConfig Se…

MySQL缓存使用率超过80%的解决方法

MySQL缓存使用率超过80%的解决方法 一、识别缓存使用率过高的问题1.1 使用SHOW GLOBAL STATUS命令监控1.2 监控其他相关指标二、分析缓存使用率过高的原因2.1 数据量增长2.2 查询模式变化2.3 配置不当三、解决缓存使用率过高的方法3.1 调整Buffer Pool大小3.1.1 计算合理的Buff…

新手教学系列——善用 VSCode 工作区,让开发更高效

引言 作为一名开发者,你是否曾经在项目中频繁地切换不同文件夹,打开无数个 VSCode 窗口?特别是当你同时参与多个项目或者处理多个模块时,这种情况更是家常便饭。很快,你的任务栏上挤满了 VSCode 的小图标,切换起来手忙脚乱,工作效率直线下降。这时候,你可能会问:“有…

springboot004基于springboot004网页时装购物系统(源码+包运行+LW+技术指导)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

丹摩征文活动 |【前端开发】HTML+CSS+JavaScript前端三剑客的基础知识体系了解

前言 &#x1f31f;&#x1f31f;本期讲解关于HTMLCSSJavaScript的基础知识&#xff0c;小编带领大家简单过一遍~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 …

进程信号

目录 信号入门 1. 生活角度的信号 2. 技术应用角度的信号 3. 注意 4. 信号概念 5. 用kill -l命令可以察看系统定义的信号列表 6. 信号处理常见方式概览 产生信号 1. 通过终端按键产生信号 Core Dump 2. 调用系统函数向进程发信号 3. 由软件条件产生信号 4. 硬件异…

【链路层】空口数据包详解(4):数据物理通道协议数据单元(PDU)

目录 一、概述 1.1. 头部&#xff08;Header&#xff09;结构 1.2. MIC字段的情况说明 1.3. 有效载荷&#xff08;Payload&#xff09;格式与LLID字段的关联 二、LL Data PDU 2.1. 定义与用途 2.2. 头部字段设置 2.3. 空PDU&#xff08;Empty PDU &#xff09; 2.4. 数…

使用 Web Search 插件扩展 GitHub Copilot 问答

GitHub Copilot 是一个由 GitHub 和 OpenAI 合作开发的人工智能代码提示工具。它可以根据上下文提示代码&#xff0c;还可以回答各种技术相关的问题。但是 Copilot 本身不能回答非技术类型的问题。为了扩展 Copilot 的功能&#xff0c;微软发布了一个名为 Web Search 的插件&am…

24 年第十届数维杯国际数模竞赛赛题浅析

本次万众瞩目的数维杯国际大学生数学建模赛题已正式出炉&#xff0c;无论是赛题难度还是认可度&#xff0c;该比赛都是数模届的独一档&#xff0c;含金量极高&#xff0c;可以用于综测加分、保研、简历添彩等各方面。考虑到大家解题实属不易&#xff0c;为了帮助大家取得好成绩…