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;
}
案例②:统计一句话中每个字母出现的次数
#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中的元素