8.20C++:映射、多重映射、pair、equal_range、顺序容器和关联容器的迭代器区别

1 映射

通过first、second读取数据
在这里插入图片描述
案例①:有五门课程,每门都有相应学分,从中选择三门,输出学分总和

#include <iostream>
#include <map>
#include <string>  //使用string
#include <utility>  //包含make_pair函数
using namespace std;

int main() {
	map<string, int> courses;  //键、值的数据类型
	courses.insert(make_pair("C++", 5));  //map数据结构需要插入pair类型
	courses.insert(make_pair("Python", 4));
	courses.insert(make_pair("C", 3));
	courses.insert(make_pair("Java", 2));
	int n = 3;
	int sum = 0;
	while (n > 0) {
		string name;
		cin >> name;
		map<string, int>::iterator iter = courses.find(name); //find返回匹配数值的迭代器,若无返回end
		if (iter == courses.end())
			cout << name << " is not avalible" << endl;
		else {
			sum += iter->second;
			courses.erase(name);
			n--;
		}		
	}
	cout << "Total credit: " << sum << endl;
	return 0;
}

案例②:统计一句话中每个字母出现的次数

cctype头文件的使用

#include <iostream>
#include <map>
#include <cctype> //包含一些检查的函数
using namespace std;
int main()
{
	map<char, int> s;
	char c; //通过循环可以输入一大串,并读入成字符
	do {   //结束循环条件是还未出现用do-while语句
		cin >> c;
		if (isalpha(c)) { //判断是否为字母
			c = tolower(c); //c转换为小写
			s[c]++; //若映射s中无c,则插入一个c;若有c,则返回引用;并使c这个key的value+1
		}
	} while (c != '.'); //输入.结束
	for (map<char, int>::iterator iter = s.begin(); iter != s.end(); ++iter) {
		cout << iter->first << "  " << iter->second << "  " << endl; //迭代器也可以使用指针的->符号
	}
	return 0;
}

输入一串字符串,该程序通过(cin >> c)可以把其中的字符依次读入,这是与cin >> string不同的地方。

2 多重映射

创建一个多重集合并查找输出关键字对应的值。
利用count函数跳出循环;有三种遍历迭代器的方式,建议用auto来初始化迭代器。
有4种构造pair的方式,{}直接花括号是新特性,更方便。

#include <iostream>
#include <map> //包含multimap
#include <string>
using namespace std;
int main()
{
    multimap<string, string> courses;
    typedef multimap<string, string>::iterator CourseIter; //用CourseIter作为multimap别名
    courses.insert({ "C++", "2-6" }); //直接用花括号{}创建pair
    courses.insert(make_pair("C", "1-3")); //通过make_pair创建
    courses.insert(pair<string, string>("C++", "3-4")); //显示构造pair
    courses.insert(multimap<string, string>::value_type("Java", "4-1")); //value_type是pair类型,且键为常引用,此处为<const string, string>
    courses.insert({ "C", "7-8" });
    string name;
    int count;
    do {
        cin >> name;
        count = courses.count(name); //返回关键字是name的元素的数量
        if (count == 0)
            cout << "找不到这门课" << endl;
    } while (count == 0);
    cout << count << "门该课程:" << endl;
    pair<CourseIter, CourseIter> range = courses.equal_range(name);
    //equal_range()返回一个<首次出现name的迭代器, 最后出现name的后继迭代器>的pair,迭代器类型是courses的迭代器
    //range这个pair的first是首次出现name的迭代器, second是最后出现name的后继迭代器
    for (auto iter = range.first; iter != range.second; iter++) {
    //for (CourseIter iter = range.first; iter != range.second; iter++)
    //for (range.first; range.first != range.second; range.first ++)
        cout << iter->second << "  ";
    }
    return 0;
}

3 pair

pair(P379)可以看做一个类,有 first / second 两个数据成员。

pair<int, string> ret1;
ret1.first;
ret1.second

map.insert()函数返回一个pair,pair的first部分是指向map的迭代器,即指向一个pair类型的迭代器,解引后(->)的first部分为string类型,second为int类型。
map.insert()函数返回的pair第二部分是bool值,如果容器中已存在该关键字,返回false,否则返回true。

//P385
int main()
{
    map<string, int> mymapp;
    pair<map<string, int>::iterator, bool> ret3 = mymapp.insert({ "happy", 100 });
    cout << ret3.first->first << endl;
    cout << ++ret3.first->second << endl;
    if (ret3.second)
        cout << "ret3.second is true" << endl;
    else
        cout << "ret3.second is flase" << endl;
    auto ret4 = mymapp.insert({ "happy", 200 });
    if (ret4.second)
        cout << "ret4.second is true";
    else
        cout << "ret4.second is flase";
    return 0;
}
输出:
happy
101
ret3.second is true
ret4.second is flase

4 equal_range(P389)

equal_range(key)返回一个pair,表示关键字等于key的元素的范围。若key不存在,pair的两个成员均指向可以插入的位置。
equal_range的用法
equal_range是C++ STL中的一种二分查找的算法,试图在已排序的[first,last)中寻找key,它返回一对迭代器i和j,其中i是在不破坏次序的前提下,key可插入的第一个位置(亦即lower_bound,第一个大于等于key的键所在位置的迭代器),j则是在不破坏次序的前提下,key可插入的最后一个位置(亦即upper_bound,第一个大于key的键所在位置的迭代器),因此,[i,j)内的每个元素都等同于key,而且[i,j)是[first,last)之中符合此一性质的最大子区间。
PS:如果在可插入区间插入,该区间元素后移

#include <iostream>
#include <map>
#include <string>
using namespace std;

int main()
{
	multimap<int, string> mymap;
	mymap.insert({ 1, "aaa"});
	mymap.insert({ 2, "bbb" });
	mymap.insert({ 4, "d1"});
	mymap.insert({ 4, "d2" });
	pair<multimap<int, string>::iterator, multimap<int, string>::iterator> ret1, ret2, ret3, ret4;
	ret1 = mymap.equal_range(2);
	cout << "2  lower bound points to: ";
	cout << ret1.first->first << " => " << ret1.first->second << endl;
	cout << "2  upper bound points to: ";
	cout << ret1.second->first << " => " << ret1.second->second << endl;
	ret2 = mymap.equal_range(3);
	cout << "3   lower bound points to: ";
	cout << ret2.first->first << " => " << ret2.first->second << endl;
	cout << "3   upper bound points to: ";
	cout << ret2.second->first << " => " << ret2.second->second << endl;
	ret3 = mymap.equal_range(4);
	cout << "4   lower bound points to: ";
	cout << ret3.first->first << " => " << ret2.first->second << endl;
	cout << "4   upper bound points to: ";
	cout << ret3.second->first << " => " << ret2.second->second << endl;
	return 0;
}
输出:
2  lower bound points to: 2 => bbb
2  upper bound points to: 4 => d1
3   lower bound points to: 4 => d1
3   upper bound points to: 4 => d1
4   lower bound points to: 4 => d1
4   upper bound points to: 报错终止。因为找不到上界

5 顺序容器和关联容器的迭代器区别

①顺序容器的迭代器 (P96、P295)

vector<int>::iterator iter;//iter为迭代器类型,返回iter所指元素的引用,左值
vector<int>::const iterator iter; //iter为只读迭代器类型,返回iter所指元素的常引用,右值

②关联容器的迭代器(P382)

map<string, string>::iterator iter;
iter->first = "a"; //错误,map的value_type是一个pair,不能改变关键字成员的值
//用->first调用关键字成员,用->second调用值成员
//iter->first相当于*iter.first,即该迭代器所指pair的first部分,即map中元素的键部分

set<int> c;
set<int>:: iterator iter = c.begin();
*iter = 42; //错误,虽然定义了iterator和const iterator类型,但这两种迭代器都只允许只读访问set中的元素
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值