map/multimap的简介
map是标准的关联式容器,一个map里存储的元素是一个键值对序列,叫做(key,value)键值对。它提供基于key快速检索数据的能力。
#include
multimap与map的区别:
map支持唯一键值,每个键只能出现一次;而multimap中相同键可以出现多次。multimap不支持[]操作符。
map/multimap容器 和 set/multiset容器都是差不多的,只是map/mulitmap比他们多了一个键值!
如果不懂set/multiset容器的可以点下面链接:
https://blog.csdn.net/cpp_learner/article/details/104751672
当然,map/multimap容器也有仿函数,因为在之前的文章中,已经详细讲过了,所以这里就不在讲了,如果不懂的可以点下面链接去学习:
https://blog.csdn.net/cpp_learner/article/details/104730577
定义
// 无参
map<int, string> m1;
map<int, int> m2;
map<string, float> m3;
map<char, string> m4;
// 带参
map<int, string> m5(m1.begin(), m1.end()); // 迭代器
map<string, float> m6(m3); // 调用拷贝构造函数
map<char, string> m7 = m4; // 调用了赋值构造函数
还可以用各种指针类型或自定义类型
插入
// 方式一 构造一个pair,然后插入,如果键存在,则插入失败
m1.insert(pair
// 方式二 使用make_pair
m1.insert(make_pair(2, “李四”));
// 方式三 使用value_type,相当于pair
m1.insert(map
// 方式四 使用 [] 重载,如果键值对已经存在,则覆盖原值
m1[4] = “赵六”;
m1[4] = “韩七”;
注意:
方式一 至 方式三的返回值类型都是一样的,都是
pair
第四种方法非常直观,但碰到相同的键时会进行覆盖操作。比如插入key 为4的键值时,先在mapStu中查找主键为4的项,若不存在,则将一个键为4,值为默认初始化值的对组插入到mapStu中,然后再将值修改成“赵六”。若发现已存在4这个键,则修改这个键对应的value。
string strName = mapStu[8]; //取值操作或插入操作
只有当mapStu存在8这个键时才是正确的取操作,否则会自动插入一个实例,键为8,值为默认构造时的初始化值。
下面测试代码 函数 test1 中会有详细案例
迭代器
// 返回容器中第一个数据的迭代器
m1.begin();
// 返回容器中最后一个数据之后的迭代器
m1.end();
// 返回容器中倒数第一个元素的迭代器
m1.rbegin();
// 返回容器中倒数最后一个元素的后面的迭代器
m1.rend();
// 使用迭代器方式输出容器里的值
for (map<int, string>::iterator it = m1.begin(); it != m1.end(); it++) {
cout << "key:" << (*it).first << " value:" << (*it).second << endl;
}
排序
map 和 multimap 容器默认存储时是顺序存储的,即
map
也可以使用greater定义一个容器,使其默认逆序存储,即
map
在此条链接中会有详细解析:
https://blog.csdn.net/cpp_learner/article/details/104730577
// 交换容器中的元素
m3.swap(m2);
// 返回容器中元素的个数
m1.size();
// 判断容器是否为空
m1.empty(); // 为空返回真,不为空返回假
//删除迭代器所指的元素,返回下一个元素的迭代器
m1.erase(m1.begin());
//删除区间[beg,end)的所有元素,返回下一个元素的迭代器
m1.erase(beg, end);
//删除容器中key为key的对组,返回删除的对组个数
m1.erase(8);
// 删除容器中所有的元素
m1.clear();
查找
map方式
// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
/*---map---*/
// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
map<int, string>::iterator it = m1.find(5);
if (it != m1.end()) {
cout << "m1.find(5) = " << (*it).second << endl;
} else {
cout << "没找到!!!" << endl;
}
multimap方式
// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
/*---multimap---*/
// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
multimap<int, string>::iterator mit = m2.find(111);
if (mit != m2.end()) {
for (; mit != m2.end(); mit++) {
if ((*mit).first == 111) {
cout << "m2.find(111) = " << (*mit).second << endl;
} else {
break;
}
}
}
// 返回容器中键值为key的对组个数。对map来说,要么是0,要么是1;对multimap来说,值>=0
m1.count(222);
// 返回第一个 >= key 元素的迭代器
m1.lower_bound(2);
// 返回第一个 > key 元素的迭代器
m1.upper_bound(2);
//返回容器中key与keyElem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如[beg,end)
//m1.equal_range(keyElem);
m1.equal_range(7);
返回值是: pair
在下面测试代码函数 test7 中会有详细案例。
测试代码:
#include
#include
#include
#include
using namespace std;
// 定义
void test1(void) {
// 无参
map<int, string> m1;
map<int, int> m2;
map<string, float> m3;
map<char, string> m4;
m1.insert(pair<int, string>(1, "张三"));
m1.insert(pair<int, string>(2, "李四"));
// 带参
map<int, string> m5(m1.begin(), m1.end()); // 迭代器
map<string, float> m6(m3); // 调用拷贝构造函数
map<char, string> m7 = m4; // 调用了赋值构造函数
for (map<int, string>::iterator it = m1.begin(); it != m1.end(); it++) {
cout << "key:" << (*it).first << " value:" << (*it).second << endl;
}
}
// insert插入
void test2(void) {
map<int, string> m1;
// 方式一 构造一个pair,然后插入,如果键存在,则插入失败
m1.insert(pair<int, string>(1, "张三"));
// 方式二 使用make_pair
m1.insert(make_pair(2, "李四"));
// 方式三 使用value_type,相当于pair
m1.insert(map<int, string>::value_type(3, "王五"));
// 方式四 使用 [] 重载,如果键值对已经存在,则覆盖原值
m1[4] = "赵六";
m1[4] = "韩七";
m1[5] = m1[6]; // 应为两个都是新值,所以他们创建键后,值默认为空
m1[7] = m1[4]; // 将键值为4里的值赋值给键值为7的值
m1[0] = m1[8]; // 新键赋值给旧键,它两的值都为空
// 方式一 至 方式三的返回值类型都是一样的
pair<map<int, string>::iterator, bool> ret1 = m1.insert(pair<int, string>(9, "刘八"));
pair<map<int, string>::iterator, bool> ret2 = m1.insert(make_pair(10, "杨九"));
pair<map<int, string>::iterator, bool> ret3 = m1.insert(map<int, string>::value_type(11, "吴十"));
if (ret1.second == true) {
cout << "插入成功!value:" << (*(ret1.first)).second << endl;
} else {
cout << "插入失败!" << endl;
}
for (map<int, string>::iterator it = m1.begin(); it != m1.end(); it++) {
cout << "key:" << (*it).first << " value:" << (*it).second << endl;
}
}
// 迭代器
void test3(void) {
map<int, int> m1;
m1.begin(); // 返回容器中第一个数据的迭代器。
m1.end(); // 返回容器中最后一个数据之后的迭代器。
m1.rbegin(); // 返回容器中倒数第一个元素的迭代器。
m1.rend(); // 返回容器中倒数最后一个元素的后面的迭代器。
}
// 排序
void test4(void) {
map<int, string> m1; // 默认是less顺序排序
//map> m1;
m1.insert(pair<int, string>(1, "张三"));
m1.insert(pair<int, string>(2, "李四"));
m1.insert(pair<int, string>(3, "王五"));
m1.insert(pair<int, string>(4, "赵六"));
// 可以使用greater逆序排序
map<int, string, greater<int>> m2;
m2.insert(pair<int, string>(1, "韩七"));
m2.insert(pair<int, string>(2, "刘八"));
m2.insert(pair<int, string>(3, "杨九"));
map<int, string, greater<int>> m3;
// 交换容器中的元素
m3.swap(m2);
cout << "m1 ==> less:" << endl;
for (map<int, string>::iterator it = m1.begin(); it != m1.end(); it++) {
cout << "key:" << (*it).first << " value:" << (*it).second << endl;
}
cout << "m3 ==> greater:" << endl;
for (map<int, string>::iterator it = m3.begin(); it != m3.end(); it++) {
cout << "key:" << (*it).first << " value:" << (*it).second << endl;
}
}
// 大小
void test5(void) {
map<int, string> m1;
m1.insert(pair<int, string>(1, "张三"));
m1.insert(pair<int, string>(2, "李四"));
m1.insert(pair<int, string>(3, "王五"));
m1.insert(pair<int, string>(4, "赵六"));
// 返回容器中元素的个数
m1.size();
// 判断容器是否为空
m1.empty(); // 为空返回真,不为空返回假
if (!m1.empty()) {
cout << "容器元素个数为:" << m1.size() << endl;
} else {
cout << "容器为空!" << endl;
}
}
// 删除
void test6(void) {
map<int, string> m1;
m1.insert(pair<int, string>(1, "张三"));
m1.insert(pair<int, string>(2, "李四"));
m1.insert(pair<int, string>(3, "王五"));
m1.insert(pair<int, string>(4, "赵六"));
m1.insert(pair<int, string>(5, "韩七"));
m1.insert(pair<int, string>(6, "刘八"));
m1.insert(pair<int, string>(7, "杨九"));
m1.insert(pair<int, string>(8, "吴十"));
//删除迭代器所指的元素,返回下一个元素的迭代器
m1.erase(m1.begin()); // 李四,王五,赵六,韩七,刘八,杨九,吴十
map<int, string>::iterator beg = m1.begin();
beg++;
map<int, string>::iterator end = m1.begin();
end++;
end++;
end++;
//删除区间[beg,end)的所有元素,返回下一个元素的迭代器
m1.erase(beg, end); // 李四,韩七,刘八,杨九,吴十
//删除容器中key为key的对组,返回删除的对组个数
m1.erase(8); // 李四,韩七,刘八,杨九
for (map<int, string>::iterator it = m1.begin(); it != m1.end(); it++) {
cout << "key:" << (*it).first << " value:" << (*it).second << endl;
}
// 删除容器中所有的元素
m1.clear();
}
// 查找
void test7(void) {
map<int, string> m1;
multimap<int, string> m2;
m1.insert(pair<int, string>(1, "张三"));
m1.insert(pair<int, string>(2, "李四"));
m1.insert(pair<int, string>(3, "王五"));
m1.insert(pair<int, string>(4, "赵六"));
m1.insert(pair<int, string>(5, "韩七"));
m1.insert(pair<int, string>(6, "刘八"));
m1.insert(pair<int, string>(7, "杨九"));
m1.insert(pair<int, string>(8, "吴十"));
m2.insert(pair<int, string>(111, "张三"));
m2.insert(pair<int, string>(111, "李四"));
m2.insert(pair<int, string>(222, "王五"));
m2.insert(pair<int, string>(222, "赵六"));
/*---map---*/
// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
map<int, string>::iterator it = m1.find(5);
if (it != m1.end()) {
cout << "m1.find(5) = " << (*it).second << endl;
} else {
cout << "没找到!!!" << endl;
}
/*---multimap---*/
// 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
multimap<int, string>::iterator mit = m2.find(111);
if (mit != m2.end()) {
for (; mit != m2.end(); mit++) {
if ((*mit).first == 111) {
cout << "m2.find(111) = " << (*mit).second << endl;
} else {
break;
}
}
}
//返回容器中键值为key的对组个数。对map来说,要么是0,要么是1;对multimap来说,值>=0
m1.count(222);
//返回第一个 >= key 元素的迭代器
it = m1.lower_bound(2);
if (it != m1.end()) {
cout << "找到啦!==> " << (*it).second << endl;
} else {
cout << "没找到!" << endl;
}
// 返回第一个 > key 元素的迭代器
it = m1.upper_bound(2);
if (it != m1.end()) {
cout << "找到啦!==> " << (*it).second << endl;
} else {
cout << "没找到!" << endl;
}
//返回容器中key与keyElem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如[beg,end)
//m1.equal_range(keyElem);
pair<map<int, string>::iterator, map<int, string>::iterator> iit = m1.equal_range(7);
// 第一个迭代器
if (iit.first != m1.end()) {
cout << "begin ==> " << (*iit.first).second << endl;
} else {
cout << "没找到!" << endl;
}
// 第二个迭代器
if (iit.second != m1.end()) {
cout << "end ==> " << (*iit.second).second << endl;
}
else {
cout << "没找到!" << endl;
}
}
int main(void) {
//test1();
//test2();
//test3();
//test4();
//test5();
//test6();
//test7();
system("pause");
return 0;
}
总结:
STL容器中,所有容器的接口用法都是差不多的,所以说其实并不难,只要理解了一种,其他的容器用法都全会了。