C++中的关联容器

文章目录

  • 使用关联容器
  • 定义关联容器
    • 关键字类型的要求
    • pair类型
    • 用作返回类型
  • 关联容器上的操作
    • 关联容器的迭代器
    • 关联容器和算法
    • 添加元素
    • 删除元素
    • map的下标操作
    • 访问元素
  • 无序容器
    • 对关键字的要求

关联容器支持高效的关键字查找和访问。两个主要的关联容器的类型是map和set。其中map中的元素是一些关键字-值(key-value)对。set中每个元素只包含一个关键字。

标准库中提供8个关联容器。分别体现在3个维度上:

  • 每种容器要么是map,要么是set;
  • 是否允许存在重复的关键字,允许重复通常以multi开头;
  • 是否有序,无序通常以unordered开头;

因此unorderd_multiset是一个允许重复的无序集合。set则是一个要求不重复的有序集合。
在这里插入图片描述

使用关联容器

统计输入的单词出现次数,并剔除一些不重要的词汇。

map<string, size_t> wordCount;
set<string> exclude = {"the", "but", "and", "or", "an", "a"};string word;
while(cin >> word)
{if(exclude.find(word) == exclude.end())map[word]++;
}

定义关联容器

map<string, string> authors = {{"key", "value"}, {{"key", "value"}, {{"key", "value"}}; //初始化一个map时,必须提供key, value并包含在花括号中。//定义一个包含20个元素的vec,保持0-9每个整数的两个拷贝
vector<int> ivec;
for(vector<int>::size_type i = 0; i < 10; ++i)
{ivec.push_back(i);ivec.push_back(i);
}set<int> iset(ivec.begin(), ivec.end()); //size = 10;
multiset<int> miset(ivec.begin(), ivec.end()); //size = 20;

关键字类型的要求

对于有序容器,关键字的类型必须定义元素比较的方法。默认情况下关键字类型的<运算符来比较两个关键字。也可以提供自定义的比较操作:

bool compareIsbn(const Sales_data & lhs, const Sales_data &rhs)
{return lhs.isbn() < rhs.isbn();
}multiset<Sales_data, decltype(compareIsbn)*> bookstore(compareIsbn);

为了定义自己的操作,在定义multiset的时候,必须提供两个类型:关键字类型以及比较操作类型(函数指针类型)。这里使用decltype来获得函数指针类型。对象初始化的时候还得传入比较函数指针。

pair类型

pair的默认构造函数对数据成员进行值初始化。map的元素是pair。
在这里插入图片描述

用作返回类型

pair<string, int> process(vector<string> &v)
{if(!v.empty()){return {v.back(), v.back().size()}; //列表初始化}else{return pair<string, int>(); //隐式构造返回值,make_pair("", 0);}
}

关联容器上的操作

在这里插入图片描述

set<string>::key_type v1; //string
set<string>::value_type v2; //string
map<string, int>::key_type v3; //string
map<string, int>::mapped_type v4; //int
map<string, int>::value_type v5; //pair<const string, int>

关联容器的迭代器

解引用一个关联容器的迭代器时,会得到一个类型为容器的value_type的值的引用。*

  • map对应一个pair类型,其first保存const关键字,second保存值;
  • set虽然同时定义了iterator和const_iterator,但两种类型都只允许读set中的元素,都是const属性的。
auto map_it = word_count.cbegin();
while(map_it != word_count.cend())
{cout << map_it->first << map_it->second << endl;++map_it;
}

因为其实有序的,因此这里打印输出也是有序的。

关联容器和算法

通常不对关联容器使用泛型算法。键的const的属性不适用于大多数泛型算法。

添加元素

在这里插入图片描述
有序容器中,insert(p, v)其中p只是一个hint,不一定有效。
insert或emplace的返回值依赖于容器类型何参数。对于不包含重复关键字的容器,添加单一元素会返回一个pair,其first成员是一个迭代器,指向给定关键字的元素;second成员是一个bool,表示元素是否插入(若关键字已经存在,则不插入)。

  • set:对于一个给定的关键字,只有第一个带此关键字的元素被插入到容器中
vector<int> ivec = {2, 4, 6, 8, 2, 4, 6, 8};
set<int> set2;
set2.insert(ivec.begin(), ivec.end()); //4个元素
set2.insert({2, 4, 6, 8}); //4个元素
  • map
word_count.insert({word, 1});
word_count.insert(make_pair(word, 1));
word_count.insert(pair<string, int>(word, 1));
word_count.insert(map<string, int>::value_type(word, 1));
  • multimap、multiset:关键字允许重复,因此插入操作总会插入元素。即时接受单个元素的插入操作,也只会返回一个指向该元素的迭代器。

删除元素

在这里插入图片描述

map的下标操作

在这里插入图片描述

访问元素

在这里插入图片描述
其中lower_bound、upper_bound、equal_range只适用于有序容器。

有这么一个应用场景,打印输出一个作者的所有书籍,数据存储在一个multimap中。可以通过以下三种方式实现:

string search_item("Alain de Botton");
//1
auto entries = authors.count(search_item);
auto iter = authors.find(search_item);
while(entries)
{cout << iter->second << endl;entries--;iter++;
}//2
for(auto beg = author.lower_bound(search_item), end = author.upper_bound(search_item); beg != end; beg++)cout << iter->second << endl;//3
for(auto pos = authors.equal_range(search_item); pos.first != pos.second; pos.first++)cout << pos.first->second << endl;

无序容器

无序容器使用hash函数和关键字类型的==来组织元素。其在存储上组织为一组桶,使用hash函数将元素映射到桶。为了访问一个元素,容器首先计算元素的hash值,它指出该搜索哪个桶。当一个桶中包含多个元素时,需要顺序搜索这些元素值来找到我们想要的那个。

无序容器提供了一组管理桶的函数:
在这里插入图片描述

对关键字的要求

对于内置类型、string、智能指针等可以直接当作关键字。当要把自定义类型作为关键字时,需要提供自定义的hash、和==函数。

size_t hasher(const Sales_data &sd)
{return hash<string>()(sd.isbn());
}
bool eqOp(const Sales_data &lhs, const Sales_data &rhs)
{return lhs.isbn() == rhs.isbn();
}using SD_multiset = unordered_multiset<Sales_data, decltype(hasher)*, decltype(eqOp)*>;//参数桶大小,hash,==
SD_multiset bookstore(42, hasher, eqOp);

如果类定义了==运算符,则可以只重载hash函数:

#include <iostream>
#include <unordered_map>struct Point {int x;int y;// 相等比较:unordered_map 要求bool operator==(const Point& other) const {return x == other.x && y == other.y;}
};// 自定义哈希函数
struct PointHash {std::size_t operator()(const Point& p) const {return std::hash<int>()(p.x) ^ (std::hash<int>()(p.y) << 1);}
};int main() {std::unordered_map<Point, std::string, PointHash> umap;umap[{1, 2}] = "A";umap[{3, 4}] = "B";umap[{1, 2}] = "C"; // 会覆盖前面的 "A"for (const auto& pair : umap) {std::cout << "(" << pair.first.x << "," << pair.first.y << ") = "<< pair.second << '\n';}
}

其中std::hash<int>()创建一个临时对象,std::hash<int>()()调用该对象。

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

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

相关文章

【Git】git提交代码报错Git: husky > pre-commit

git提交代码报错原因 这个问题是因为当你在终端输入git commit -m “XXX”,提交代码的时候,pre-commit(客户端)钩子&#xff0c;它会在Git键入提交信息前运行做代码风格检查。如果代码不符合相应规则&#xff0c;则报错&#xff0c;而它的检测规则就是根据.git/hooks/pre-commi…

Unity开发者快速认识Unreal 的C++(六)GameMode之PlayerController

继承关系&#xff1a;Aactor&#xff0c;INavAgentInterface <--- AController<--- PlayerController &#xff0c;PlayerController也是一个Actor,继承了Actor的一些通用的属性和工具函数下图是PlayerController初始化组件的一个子阶段从图中可以得到的信息是&#xf…

Vue 3 服务端渲染(SSR)与客户端渲染(CSR)的区别及解决方案

1. SSR与CSR的区别1.1. SSR的原理服务端渲染&#xff08;SSR&#xff09;是在服务器端将 Vue 组件渲染为 HTML 字符串&#xff0c;并将其发送给客户端。这种方式与客户端渲染&#xff08;CSR&#xff09;不同&#xff0c;后者是在浏览器中执行 JavaScript 来生成 HTML。在 SSR …

Matlab快速回顾

一1.数值 显示 格式format style 设置eg: pi format longE;or2.清除指令clc 清除命令行窗口clear 清除工作区cls3.搜索路径设置path(path,E:\ads\)oraddpath4.M文件用户把要实现的命令写在一个以.m为扩展的文件中&#xff0c;然后由matlab系统进行解读&#xff0c;最后运行结果…

开源低代码+AI引擎:百特搭企业级开发平台的演进

在数字化转型进入深水区的今天&#xff0c;企业应用开发面临前所未有的复杂挑战&#xff1a;既要快速响应业务需求&#xff0c;又要确保系统灵活可控&#xff1b;既要降低技术门槛&#xff0c;又要保障核心安全。传统开发模式与单一形态的低代码工具已难以满足多层次需求。融合…

学习 Android(十五)NDK进阶及性能优化

学习 Android&#xff08;十五&#xff09;NDK进阶及性能优化 对 NDK 相关知识有了初步的了解之后&#xff0c;我们可以更加深入的去学习 NDK 相关知识&#xff0c;接下来&#xff0c;我们将按照以下步骤进行深入学习&#xff1a; 深入理解JNI调用过程和性能消耗常见 JNI 坑&am…

QT5.12.8 QTabWidget 透明样式QSS

/* 设置QTabWidget本身 :不加也行*/ QTabWidget#aaa_tabwdt {background: transparent;border: none; /* 移除边框可能有助于透明效果 */ }/* 标签页内的容器部件 :必须加&#xff0c;标签也才会透明 */ QTabWidget#aaa_tabwdt QWidget, QTabWidget#aaa_tabwdt QFrame {backgro…

【FAQ】Script导出SharePoint 目录文件列表并统计大小

一、只导出文件列表的方法 1) 保存脚本&#xff08;建议名&#xff1a;D:\tmp\Export-SharePoint-FileList.ps1&#xff09; <# 导出 SharePoint 指定文件夹&#xff08;含子文件夹&#xff09;的文件列表到 CSV&#xff08;不统计大小&#xff09; 前提&#xff1a;已安…

《Thinking in Java》读书笔记---控制执行流程

就像有感知的生物一样&#xff0c;程序必须在执行过程中控制它的世界&#xff0c;并做出选择。在Java中&#xff0c;你要使用执行控制语句来作出选择。一、流程控制基础概念1.1 流程控制的重要性流程控制结构决定了程序执行的顺序和逻辑分支&#xff0c;是编程语言中最基础也是…

极验 G-star 人才特训营:为业务安全领域培养下一代新兴力量

本文导读 极验为什么要启动 G-star 实习生培养计划&#xff1f;50多位来自多所高校的同学&#xff0c;在极验经历了一场怎样的“非典型”实习&#xff1f;技术大咖亲授&#xff0c;先培训再实战&#xff0c;极验打造的是怎样的人才体系&#xff1f;同学有话说&#xff1a;培养计…

攻防世界-web-csaw-mfw

一.题目分析这边提示使用了Git&#xff0c;试着访问.git看是否存在.git泄露浏览了一下&#xff0c;很多都是乱码&#xff0c;想着用githack将git库克隆下看一下二.操作python2 GitHack.py http://url/.git访问了一下flag.php&#xff0c;没啥发现&#xff0c;在看一下index.php…

202506 电子学会青少年等级考试机器人四级实际操作真题

更多内容和历年真题请查看网站&#xff1a;【试卷中心 -----> 电子学会 ----> 机器人技术 ----> 四级】 网站链接 青少年软件编程历年真题模拟题实时更新 2025年6月 青少年等级考试机器人实操真题四级 实际操作 主题&#xff1a;感应节能灯&#xff08;四级&am…

DLT645电表数据 保存到MySQL数据库项目案例

目录 1 案例说明 2 VFBOX网关工作原理 3 准备工作 4 配置VFBOX网关采集DLT645电表数据 5 网关写数据到MYSQL数据库 6 安装MYSQL数据库 7 其他说明 8 案例总结 1 案例说明 设置网关采集DLT645电表数据数据把采集的数据保存到MySQL数据库。 2 VFBOX网关工作原理 VFBOX网关…

Redux与React - 异步状态操作(React快速上手4)

异步操作样板代码1. 创建store的写法保持不变&#xff0c;配置好同步修改状态的方法 2. 单独封装一个函数&#xff0c;在函数内部return一个新函数&#xff0c;在新函数中 2.1 封装异步请求获取数据 2.2 调用同步actionCreater传入异步数据生成一个action对象&#xff0c;并使用…

win10桌面右键没有新建word

win10右键新建word不见解决方法1、点击开始&#xff0c;找到运行命令行&#xff0c;输入regedit&#xff0c;打开注册表。2、在左侧找到HKEY_CLASSES_ROOT目录&#xff0c;并展开。3.找到.docx 双击&#xff08;默认&#xff09;一项&#xff0c;将其改为 Word.Document.12。关…

Docker国内可用镜像(2025.08.06测试)

Docker渡渡鸟镜像可用&#xff08;测试时间2025.08.06&#xff09;https://docker.aityp.com/使用渡渡鸟镜像pull ollama latest 例子&#xff1a;docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/ollama/ollama:0.10.1毫秒镜像和轩辕镜像也可用&#xff0c;但…

决策树的实际案例

决策树作为一种直观、易解释的机器学习算法&#xff0c;在金融、医疗、电商、风控等多个领域都有广泛的实际应用。以下将讲解1个典型案例&#xff1a;贷款违约预测。对于贷款违约预测&#xff0c;即在贷款人员在贷款之前对其进行预测&#xff0c;通过他的众多特征情况判别是否可…

bool 类型转换运算符重载

以下是一个极简且聚焦核心知识点的示例代码&#xff0c;用最直观的方式演示 bool 类型转换运算符重载的触发逻辑、使用场景和避坑点&#xff0c;帮你快速掌握&#xff1a;cpp运行#include <iostream> using namespace std;// 核心类&#xff1a;演示 bool 转换运算符 cla…

LVGL代码框架简介

LVGL代码框架介绍LVGL&#xff08;Light and Versatile Graphics Library&#xff09;是一个轻量级、功能强大的嵌入式图形库。其代码架构设计清晰&#xff0c;模块化程度高。1. 整体架构层次LVGL采用分层架构设计&#xff0c;主要包含以下几个层次&#xff1a;┌───────…

【云计算】云主机的亲和性策略(三):云主机 宿主机

《云主机的亲和性策略》系列&#xff0c;共包含以下文章&#xff1a; 1️⃣ 云主机的亲和性策略&#xff08;一&#xff09;&#xff1a;快乐旅行团2️⃣ 云主机的亲和性策略&#xff08;二&#xff09;&#xff1a;集群节点组3️⃣ 云主机的亲和性策略&#xff08;三&#xf…