当前位置: 首页 > news >正文

《C++ Primer》 第十一章 关联容器

《C++ Primer》 第十一章 关联容器

11.1 使用关联容器

在这里插入图片描述

使用map:

//统计每个单词在输入中出现的次数
map<string, size_t> word_count;//string到size_t的空map
string word;
while(cin>>word)++word_count[word];//提取word的计数器并将其加1
for(const auto &w: word_count)cout<<w.first<<"occurs "<<((w.second>1)?"times":"time")<<endl;

使用set:

//统计每个单词在输入中出现的次数
map<string, size_t> word_count;//string到size_t的空map
set<string> exclude = {"The","But","And","Or","An","A","the","but","and","or","an","a"};
string word;
while(cin>>word)//只统计不在exclude中的单词if(exclude.find(word)==exclude.end())++word_count[word];//获取并递增word的计数器

11.2 关联容器概述

关联容器的迭代器都是双向的,且不支持push_front或push_back。

定义关联容器:

//三个元素,authors将姓映射成名
map<string,string> authors = { {"Joyce", "James"},{"Austen", "Jane"},{"Dickens","Charles"}};

初始化multimap或multiset:允许多个元素具有相同的关键字

//定义一个有20个元素的vector,保存0~9的每个整数的两个拷贝
vector<int> ivec;
for(vector<int>::size_type i=0; i!=10; ++i){ivec.push_back(i);ivec.push_back(u);
}
//iset包含来自ivec的不重复的元素;miset包含所有20个元素
set<int> iset(ivec.cbegin(), ivec.cend());
multiset<int> miset(ivec.cbegin(), ivec.cend());
cout<<ivec.size()<<endl;//20
cout<<iset.size()<<endl;//10
cout<<miset.size()<<endl;//20

pair类型:定义在utility中,两个成员分别是first和second。

pair<string,string> anon;   //保存两个string
pair<string, size_t> word_count;  //保存一个string和一个size_t
pair<string,vector<int>> line;  //保存string和vector<int>
//为每个成员提供初始化器
pair<string,string> author{"James", "Joyce"};

在这里插入图片描述

创建pair对象的函数:可以对返回值进行列表初始化

pair<string, int> process(vector<string> &v)
{//处理vif(!v.empty())return {v.back(), v.back().size()};//列表初始化elsereturn pair<string, int>();//隐式构造返回值
}

11.3 关联容器操作

在这里插入图片描述

由于不能改变一个元素的关键字,因此pair的关键字部分是const的。

关联容器迭代器:

//获得指向word_count中一个元素的迭代器
auto map_it = word_count.begin();
//*map_it是指向一个pair<const string, size_t>对象的引用
cout<<map_it->first;//打印此元素的关键字
cout<<" "<<map_it->second;//打印此元素的值
map_it->first = "new key";//错误:关键字是const的
++map_it->second;//正确:可以通过迭代器改变元素

set的迭代器是const的:可以用一个set迭代器来读取元素的值,但不能修改

set<int> iset = {0,1,2,3,4,5,6,7,8,9};
set<int>::iterator set_it = iset.begin();
if(set_it!=iset.end()){*set_it=42;//错误:set中的关键字是只读的cout<<*set_it<<endl;//正确:可以读关键字
}

遍历关联容器:

//获得一个指向首元素的迭代器
auto map_it = word_count.cbegin();
//比较当前迭代器和尾后迭代器
while(map_it!=word_count.cend()){//解引用迭代器,打印关键字-值对cout<<map_it->first<<" occurs "<<map_it->second << " times "<<endl;++map_it;//递增迭代器,移动到下一元素
}

添加元素:

vector<int> ivec = {2,4,6,8,2,4,6,8};
set<int> set2;
set2.insert(ivec.begin(), ivec.cend());//有4个元素
set2.insert({1,3,5,7,1,3,5,7});//set2现在有8个元素

向map添加元素:对一个map进行insert操作时,必须记住元素类型是pair。

//向word_count插入word的4种方法
word_count.insert({word,1});
word_count.insert(make_pair(word,1));
word_count.insert(pair<string, size_t>(word,1));
word_count.insert(map<string,size_t>::value_type(word,1));

在这里插入图片描述

检测insert的返回值:

//统计每个单词在输入中出现次数的一种更繁琐的方法
map<string, size_t> word_count;//从string到size_t的空map
string word;
while(cin>>word){//插入一个元素,关键字等于word,值为1//若word已在word_count中,insert什么也不做auto ret = word_count.insert({word,1});if(!ret.second)//word已在word_count中++ret.first->second;
}

向multiset或multimap添加元素

multimap<string,string> authors;
//插入第一个元素,关键字为Barth,John
authors.insert({"Barth,John", "Sot-Weed Factor"});
//正确:添加第二个元素,关键字也是Barth,John
authors.insert({"Barth,John","Lost in Funhouse"});

删除元素:

//删除一个关键字,返回删除的元素数量
if(word_count.serase(removal_word))cout<<"ok: "<<removal_word<<" removed\n"
elsecout<<"oops: "<<removal_word<<" not found\n";

在这里插入图片描述

map的下标操作:由于下标运算符可能插入一个新元素,所以只对非const的map使用下标操作

在这里插入图片描述

访问元素:

set<int> iset={0,1,2,3,4,5,6,7,8};
iset.find(1);//返回一个迭代器,指向key==1的元素
iset.find(11);//返回一个迭代器,其值等于iset.end()
iset.count(1);//返回1
iset.count(11);//返回0

在这里插入图片描述

在这里插入图片描述

对map可以使用find代替下标操作:

if(word_count.find("foolbar") == word_count.end())cout<<"foolbar is not in the map"<<endl;

在multimap或multiset中查找元素

string search_item("Alain de Botton");//要查找的作者
auto entries = authors.count(search_item);//元素的数量
auto iter = authors.find(search_item);//此作者的第一本书
//用一个循环查找此作者的所有著作
while(entries){cout<<iter->second<<endl;++iter;//前进到下一本书--entries;//记录已经打印了多少本书
}

一种不同的,面向迭代器的解决方法:

for(auto beg = authors.lower_bound(search_item),end = authors.upper_bound(search_item);beg!=end;++beg)cout<<beg->second<<endl;

equal_range函数:

//pos保存迭代器对,表示与关键字匹配的元素范围
for(auto pos = authors.equal_range(search_item);pos.first!=pos.second;++pos.first)cout<<pos.first->second<<endl;//打印每个题目

一个单词转换的map

void word_transform(ifstream &map_file, ifstream &input)
{auto trans_map = buildMap(map_file);//保持转换规则string text;//保存输入中的每一行while(getline(input,text)){//读取一行输入istringstream stream(text);//读取每个单词string word;bool firstword = true;//控制是否打印空格while(stream>>word){if(firstword)firstword = false;elsecout<<" ";//在单词间打印一个空格//transform返回它的第一个参数或其转换之后的形式cout<<transform(word,trans_map);//打印输出}cout<<endl;}
}//函数buildMap读入给定文件,建立起转换映射
map<string,string> buildMap(ifstream &map_file)
{map<string,string> trans_map;//保存转换规则string key;//要转换的单词string value;//转换后的内容//读取第一个单词存入key中,行中剩余内容存入valuewhile(map_file>>key&&getline(map_file,value))if(value.size()>1) //检查是否有转换规则trans_map[key]=value.substr(1);//跳过前导空格elsethrow runtime_error("no rule for "+key);return trans_map;
}//生成转换文本
const string & transform(const string &s, const map<string,string> &m)
{auto map_it=m.find(s);//如果单词在转换规则中if(map_it!=m.cend())return map_it->second;//使用替换短语elsereturn s;//否则返回原string
}

11.4 无序容器

使用无序容器:

//统计出现次数,但单词不会按字典序排列
unordered_map<string,size_t> word_count;
string word;
while(cin>>word)++word_count[word];//提取并递增word的计数器
for(const auto &w: word_count)//对map中的每个元素cout<<w.first<<" occurs "<<w.second<<((w.second>1)?"times":"time")<<endl; 

管理桶:

在这里插入图片描述

概念总结

在这里插入图片描述

vector和map的区别:
在这里插入图片描述

在这里插入图片描述

http://www.lryc.cn/news/27471.html

相关文章:

  • WebRTC标准与框架解读(1)
  • 数据结构的一些基础概念
  • 【Python每日一练】总目录(不断更新中...)
  • latex插入图片(自用)
  • 【微信小程序】-- 网络数据请求(十九)
  • K8S 实用工具之一 - 如何合并多个 kubeconfig?
  • 阿里云ECS服务器的6大功能组件
  • 外贸建站多少钱?不同预算对应的建站方案!
  • Vue3中hook的使用及使用中遇到的坑
  • 数据库-差集交集并集
  • spark性能调优(四):网络
  • 高性能 WPF 图表控件LightningChart.NET:支持从 Web 服务器获取数据 | 附最新版试用下载
  • 文科女生月入14k背后:转行IT软件测试不是谁都学得来!
  • GB28181监控视频统一汇聚平台LiveGBS将海康大华华为宇视等厂家监控设备统一接入后如何生成固定播放链接或者固定的流地址可以直接无插件播放或者拉取
  • 认识BUG
  • C++string类型内置的搜索函数
  • Disruptor 消费线程丢失、写入无限阻塞问题
  • 【禅道测试环境搭建及安装】Linux上的禅道安装教程,从环境搭建开始
  • spring-boot rabbitmq整合
  • CentOS7安装redis redis常用命令
  • 世界文明的脉络
  • map和set 的封装
  • Springboot集成kafka(环境搭建+演示)|超级详细,建议收藏
  • Qt 绘制图表 - Qt Charts版
  • Java学习笔记 --- JavaScript
  • AP5216 平均电流型LED 降压恒流驱动器
  • B站的多个视频教程,怎样生成一个二维码?
  • 深入底层源码的Listener内存马(内存马系列篇三)
  • 云端需求助力跑赢周期,金山办公有望借助ChatGPT加速腾飞
  • Vulnhub靶场----8、DC-8