C++11STL容器map和set简单介绍

一、引言

        map和set底层结构比较复杂,我认为我们先谈基本介绍再谈C++11,最后再谈map和set底层以及map和set封装。

二、简单介绍一下map和set

        map和set底层都是红黑树,是二叉搜索树的一种,查找非常快。不像数组、链表一样一个一个对比,可以理解为创建一个非常适合使用二分查找的结构,每次查找都可以排除掉上一次排除元素的一半。

        下面小编来介绍一个非常有意思的二叉树结构——二叉搜索树

小讲、map和set的底层红黑树的祖先——二叉搜索树

        二叉搜索树其实很简单,就是确定一个顺序,那一边(左边还是右边)大于根结点(我们将一棵子树的顶点称为根结点,任意一棵子树(只有一个点也可以被称为子树,子树是一个小单元,不是一个数量单位。)都有它的根结点)。那我们可以假设右子树(子树的右子树)的所有结点都大于子树的根节点。那左子树的结点肯定小于根结点。那我们以此作图就是这样。红黑树呢,也只是增加了几条规则保证二叉搜索树的平衡,改变根结点使二叉树像天平,这样就可以每次查找到下一层就可以排除掉一半的结点。

        2.1        map和set各自具有的特点。

                首先还是说说使用map和set所要包含的头文件时<map>、<set>头文件。

                先来说说map,这个主要是用来做映射的,映射大家可以想到什么?对应关系,例如说函数x带入到表达式中求出y的值(x,y)用坐标x通过数学图像可以指向坐标y点,通过给一个人或者一个事物取外号从而起到指代某个东西某个人,翻译过程中通过一个单词翻译出中文含义。这些都是映射。简单来说就是通过一个东西指代另一个东西。但是它不允许重复数据插入。

                set就更好说了,set并没有映射功能,所以它就是一个普通的红黑树,可以把它看成一个集合,它不允许有相同的数据插入,至于要看是否插入进去那要看插入时的返回值了,返回值为一个结构体,可以根据结构体来判断是否插入成功。

        2.2        map和set如何插入数据

                set插入很简单。考虑到map插入时,要交代映射关系就有点复杂了。我们先来说说map的插入吧。

#include <iostream>
#include <map>
#include <string>int main()
{// map显示化模版传递类型std::map<std::string,std::string> dic;// 判断是否插入成功std::pair<std::map<std::string, std::string>::iterator, bool> is_insert;// 插入数据// map中存在一个pair<模版1,模版2>类型// 需要make_pair<>转化。// 为什么不像函数一样让编译器自己推导出类型呢?// 因为推出来的类型可能和map中显示传递的类型出现偏差。// 一般这种对返回值类型有精密要求都会要求模版显示化传递。is_insert = dic.insert(std::make_pair<std::string,std::string>("apple","苹果"));std::cout << is_insert.second << std::endl;is_insert = dic.insert(std::make_pair<std::string, std::string>("funny", "滑稽"));std::cout << is_insert.second << std::endl;is_insert = dic.insert(std::make_pair<std::string, std::string>("food", "食物"));std::cout << is_insert.second << std::endl;// 打印出map中存储的数据。std::map<std::string,std::string>::iterator it = dic.begin();while (it != dic.end()){std::cout << it->first << ":" << it->second << std::endl;++it;}return 0;
}

                set插入直接将数据往insert上甩就行了。

#include <iostream>
#include <set>int main()
{std::set<int> gather;std::pair<std::set<int>::iterator, bool> is_insert;is_insert = gather.insert(0);is_insert = gather.insert(1);is_insert = gather.insert(2);is_insert = gather.insert(3);std::set<int>::iterator it = gather.begin();while (it != gather.end()){std::cout << *it << std::endl;++it;}return 0;
}

        2.3        size()函数

                毫无疑问这就是返回插入数据的个数,相信大家都能做好这里就不演示。

        2.4        find函数

                查找函数,set和map查找,都会得到一个迭代器。如果没找到迭代器就返回end()。值的一提的是map和set的迭代器都是双向迭代器(只能++或--)。

#include <iostream>
#include <set>int main()
{std::set<int> gather;std::pair<std::set<int>::iterator, bool> is_insert;is_insert = gather.insert(0);is_insert = gather.insert(1);is_insert = gather.insert(2);is_insert = gather.insert(3);// 查找元素std::set<int>::iterator it = gather.find(3);// 判断是否存在,存在则打印,不存在不打印。if(it != gather.end()){std::cout << it << std::endl;}return 0;
}
#include <iostream>
#include <map>
#include <string>int main()
{std::map<std::string,std::string> dic;std::pair<std::map<std::string, std::string>::iterator, bool> is_insert;is_insert = dic.insert(std::make_pair<std::string,std::string>("apple","苹果"));std::cout << is_insert.second << std::endl;is_insert = dic.insert(std::make_pair<std::string, std::string>("funny", "滑稽"));std::cout << is_insert.second << std::endl;is_insert = dic.insert(std::make_pair<std::string, std::string>("food", "食物"));std::cout << is_insert.second << std::endl;// 查找map中的数据。std::map<std::string,std::string>::iterator it = dic.find("apple");if(it != dic.end()){std::cout << it->first << ":" << it->second << std::endl;}return 0;
}

        2.5        map中的count()函数和operator [] (模版)重载

                虽然find()函数很方便。但是我们很少用它,因为使用operator[]可以返回它的迭代器而且不管写起来,用起来,还是看起来都很方便、简洁。而且find()函数因为不知道里面有没有该函数还要写一老长串的判断是否等于end()。非常不方便!

                所以我们用count()和operator[]的结合。从count英文单词来看,是数数的意思,返回的是查找元素的个数,为零肯定就不存在。自然可以用operator[]访问(如果访问不存在的数据的话会报错。)。

                set虽然也有count,但是并没有operator[]的改值运算符重载,如果改值,意味着要删除重新插入。

#include <iostream>
#include <map>
#include <string>int main()
{std::map<std::string,std::string> dic;std::pair<std::map<std::string, std::string>::iterator, bool> is_insert;is_insert = dic.insert(std::make_pair<std::string,std::string>("apple","苹果"));std::cout << is_insert.second << std::endl;is_insert = dic.insert(std::make_pair<std::string, std::string>("funny", "滑稽"));std::cout << is_insert.second << std::endl;is_insert = dic.insert(std::make_pair<std::string, std::string>("food", "食物"));std::cout << is_insert.second << std::endl;// 查看是否存在值if(dic.count("apple")){// 其实返回的是映射也就是pair中的second。std::cout << dic["apple"] << std::endl;}return 0;
}

        2.6      lower_bond和upper_bond函数

                lower_bond返回的是大于等于该值的起始数据的迭代器。

                upper_bond返回的是小于等于该值的起始数据的迭代器。

// set::lower_bound/upper_bound
#include <iostream>
#include <set>int main()
{std::set<int> myset;std::set<int>::iterator itlow, itup;for (int i = 1; i < 10; i++) myset.insert(i * 10); // 10 20 30 40 50 60 70 80 90itlow = myset.lower_bound(30);                //       ^itup = myset.upper_bound(60);                 //                   ^// 删除一段区间,从A位置删除到B位置。myset.erase(itlow, itup);                     // 10 20 70 80 90// 打印set中存储的值。std::cout << "myset contains:";for (std::set<int>::iterator it = myset.begin(); it != myset.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}

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

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

相关文章

Java线程基础面试复习笔记

1. 线程与进程的区别进程是正在运行程序的实例&#xff0c;线程是进程中的执行单元。主要区别&#xff1a; 内存空间&#xff1a;不同进程使用不同的内存空间&#xff0c;同一进程下的线程共享内存空间资源开销&#xff1a;线程更轻量&#xff0c;线程上下文切换成本比进程上下…

面试题(技术面+hr面)

面试技术面HR面后端HR面常见问题*稳定性&#xff0c;上进心&#xff0c;目标感&#xff0c;抗压能力&#xff0c;学习能力*回答问题时注意体现上面五点&#xff0c;即使瞎扯也尽量往上靠。面经项目相关介绍一下你收获最大的一个项目你们团队有多少人&#xff0c;怎么分工的开发…

本地部署Dify教程

克隆 Dify 代码仓库克隆 Dify 源代码至本地。git clone hts://github.com/langgenius/dify.git启动 Dify进入 Dify 源代码的 docker 目录&#xff0c;执行一键启动命令:cd dify/docker #切换到指定目录 cp .env.example .env #修改文件名 docker compose up -d #启动

Android Kotlin 协程全面指南

协程是 Kotlin 提供的一套简化异步编程的轻量级线程操作框架&#xff0c;特别适合 Android 开发中的异步任务处理。以下是 Android 开发中需要掌握的协程核心知识点&#xff1a;1. 协程基础概念1.1 协程是什么轻量级线程&#xff1a;比线程更高效&#xff0c;可以在单个线程中运…

【Linux】进程切换与优先级

前言&#xff1a; 上文我们讲到了操作系统与Linux中进程的状态【Linux】进程状态-CSDN博客 本文我们来讲进程的优先级、以及进程的切换 进程优先级 什么是优先级&#xff1f; CPU中资源是有限的&#xff0c;而进程的数量一定是远大于CPU资源的&#xff0c;所以优先级是进程得…

首发即开源!DAWorkBench数据可视化分析软件正式发布!(附源码下载网址)

1 系统介绍DAWorkBench是一款面向科研实验和工程测试场景的数据可视化分析开源软件&#xff0c;支持实现数据清洗、信号处理和交互式可视化等功能。系统集成文件IO、数据处理以及可视化交互三大模块&#xff0c;支持多维数据分析与高质量图表生成&#xff0c;助力用户高效完成从…

Android Studio历史版本快速下载(二次修改记录)

原版&#xff1a;Android Studio历史版本快速下载_android studio 历史版本下载-CSDN博客 一. 最新版本 https://developer.android.com/studio?hlzh-cn 二. 历史版本 中国官网的历史版本为何不能下载&#xff1f;&#xff08;https://developer.android.com/studio/archi…

The Missing Semester of Your CS Education 学习笔记以及一些拓展知识(六)

文章目录The Missing Semester of Your CS Education 学习笔记以及一些拓展知识版本控制Git笔记部分Git的基本工作原理Git 的核心工作原理&#xff1a;快照而非差异Git 的三大工作区域Git的核心对象Git的四个对象对象之间的关系与工作流程&#xff1a;对象的引用Git的安装和基础…

嵌入式与 Linux 系统中的核心图形库全解析

嵌入式与 Linux 系统中的核心图形库全解析 图形库在嵌入式系统与 Linux 桌面系统中扮演着重要角色。从最底层的 GPU 驱动接口&#xff0c;到上层的图形渲染与 GUI 工具包&#xff0c;共同构成了完整的图形显示栈。本文将系统整理图形相关的核心组件&#xff0c;按功能分层分类&…

深度学习模块实践手册(第十二期)

56、Ghost 模块论文《GhostNet: More Features from Cheap Operations》1、作用&#xff1a; Ghost 模块是一种轻量级的特征提取模块&#xff0c;旨在通过廉价操作生成更多特征图&#xff0c;减少计算量的同时保持模型性能。传统卷积神经网络在生成特征图时存在大量冗余计算&am…

自己动手造轮子:如何创建JAR并通过Maven在Spring Boot中引用

让代码复用变得简单优雅——3分钟学会封装专属工具库作为Java开发者&#xff0c;你是否遇到过这些痛点&#xff1f;多个项目重复编写相同工具类工具代码分散难以统一维护团队协作缺乏标准化工具库本文将手把手教你创建自己的JAR包&#xff0c;并优雅地集成到Spring Boot项目中&…

使用dea工具 给vue 里面的ts打断点

在 Vue 项目中使用 TypeScript 时&#xff0c;我们通常会在 IDE&#xff08;如 JetBrains 的 IntelliJ IDEA 或 WebStorm&#xff09;中设置断点进行调试。以下是详细步骤&#xff1a; 准备工作 确保项目已配置 source maps&#xff08;Vue CLI 创建的项目默认已配置&#xff0…

Zabbix 企业级分布式监控

目录 简介 一、监控系统基础 1.1 监控的价值 1.2 监控的 5 大类型与 5 大层次 1.3 监控系统的实现原理 二、Zabbix&#xff1a;企业级监控方案 2.1 Zabbix 简介 2.2 Zabbix 核心功能特性 2.3 Zabbix 角色与架构 三、Zabbix 部署案例 3.1 资源清单 3.2 基础环境配置…

SQL JOIN 全解析:用 `users` 与 `orders` 表彻底掌握内连接、左连接、右连接

SQL JOIN 全解析&#xff1a;用 users 与 orders 表彻底掌握内连接、左连接、右连接 在日常开发中&#xff0c;SQL 的连接&#xff08;JOIN&#xff09;语句是数据库查询的核心技能。尤其在多表联合查询时&#xff0c;不掌握好 INNER JOIN、LEFT JOIN、RIGHT JOIN&#xff0c;…

(一)从零搭建unity3d机械臂仿真-unity3d导入urdf模型

1.新建工程并加载模型 &#xff08;1&#xff09;unity中新建3d工程 &#xff08;2&#xff09;将机器人模型导入到unity3d中 导入开源Unity-Robotics-Hub的机械臂。 详细操作参考视频 ROS Unity URDF Import Testing Robot Motion 使用 URDF Importer工具 在 Unity 中&#x…

Linux之网络部分-应用层自定义协议与序列化

一、应用层 1.1、理解协议 协议是一种 "约定". socket api 的接口, 在读写数据时, 都是按 "字符串" 的方式来发送接收的。如果我们要传输一些 "结构化的数据" 怎么办呢? 其实&#xff0c;协议就是双方约定好的结构化的数据。 1.2、网络版计…

机器学习week3-分类、正则化

1. 逻辑回归1.1. 线性回归 vs 逻辑回归对比维度线性回归逻辑回归任务类型回归&#xff08;预测连续值&#xff09;分类&#xff08;预测离散类别&#xff09;输出范围(−∞,∞)[0,1]&#xff08;概率值&#xff09;损失函数均方误差&#xff08;MSE&#xff09;对数损失&#x…

FastAdmin 中生成插件

在 FastAdmin 中生成一个 OCR 发票识别插件&#xff0c;可以按照以下步骤进行开发。这里假设你已经熟悉 FastAdmin 插件开发的基本流程&#xff0c;并会使用 Composer 和 PHP 扩展。1. 创建插件骨架使用 FastAdmin 命令行工具生成插件基础结构&#xff1a;php think addon -a o…

DevExpress WinForms中文教程:Grouping(分组)- 如何自定义分组算法?

DevExpress WinForms拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜…

PHP 与 Vue.js 结合的前后端分离架构

PHP 与 Vue.js 结合是构建现代 Web 应用的流行技术栈&#xff0c;通常采用 前后端分离架构。以下是关键要点和推荐实现方案&#xff1a; 一、技术栈组合 角色技术选项后端 (PHP)Laravel (推荐)、Symfony、CodeIgniter前端 (Vue)Vue 2/3、Vue Router、Pinia/Vuex、Vite通信协议…