【C++】map和set深度讲解(上) https://developer.aliyun.com/article/1565606
🌙C++的multiset
介绍:
multiset容器与set容器实现和接口基本一致,唯一区别就是,multiset允许键值冗余,即multiset容器当中存储的元素是可以重复的
注意:
对于find来说multiset返回底层搜索树中序的第一个键值为key的元素的迭代器
举个栗子:
int main() { set<int> s; // 不会去重 s.insert(1); s.insert(3); s.insert(4); s.insert(2); s.insert(2); cout << "set 结果 :"; for (auto e : s) { cout << e << " "; } cout << endl; multiset<int> ms; // 会去重 ms.insert(1); ms.insert(3); ms.insert(4); ms.insert(2); ms.insert(2); cout << "multiset 结果 :"; for (auto e : ms) { cout << e << " "; } cout << endl; }
运行结果:
🌙C++的map
💫map的介绍
概念:
- map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素
- 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair:typedef pair value_type;
- 在内部map中的元素总是按照键值key进行比较排序以及查找
- map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)
- map支持下标访问符,即在[]中放入key,就可以找到与key对应的value(这里是在insert上的一个封装)
- map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树)
注意:
set和map基本差不多,但是set是k模型,而map是kv模型,这导致在部分地方又有些不一样
💫map的使用
分析:
- key: 键值对中key的类型
- T: 键值对中value的类型
- Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)
- Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器
1.map构造函数
举个栗子:
int main() { map<int, double> m1; //构造一个key为int类型,value为double类型的空容器 map<int, double> m2(m1); //拷贝构造 map<int, double> m3(m2.begin(), m2.end()); //利用迭代器拷贝构造 map<int, double, greater<int>> m4; //按int降序排序 return 0; }
2.map的迭代器
举个栗子:
int main() { map<int, string> m; m.insert(make_pair(2, "two")); m.insert(make_pair(1, "one")); m.insert(make_pair(3, "three")); // 正向迭代器遍历 map<int, string>::iterator it = m.begin(); while (it != m.end()) { cout << it->first << "-" << it->second << endl; it++; } cout << endl; // 反向迭代器遍历 map<int, string>::reverse_iterator it2 = m.rbegin(); while (it2 != m.rend()) { cout << it2->first << "-" << it2->second << endl; it2++; } cout << endl; return 0; }
运行结果:
3.map其他常用成员函数
举个栗子:
int main() { map<int, string> m; m.insert(make_pair(2, "two")); m.insert(make_pair(1, "one")); m.insert(make_pair(3, "three")); m.insert(make_pair(4, "four")); //根据key值进行删除 m.erase(3); //根据迭代器进行删除 map<int, string>::iterator pos = m.find(4); if (pos != m.end()) { m.erase(pos); } // 获取元素为2的迭代器 pos = m.find(2); if (pos != m.end()) { cout << pos->first << "-" << pos->second << endl; } //获取容器中元素的个数 cout << m.size() << endl; //容器中key值为2的元素个数 cout << m.count(2) << endl; //清空容器 m.clear(); //容器判空 cout << m.empty() << endl; //交换两个容器中的数据 map<int, string> tmp; m.swap(tmp); return 0; }
运行结果:
4.map的插入(重点)
原型模板:
pair<iterator,bool> insert (const value_type& val); //value_type是pair的重命名value_type是pair的重命名: typedef pair<const Key, T> value_type;
方式一:构造匿名对象插入
举个栗子:
int main() { map<int, string> m; // 构造一个匿名对象插入 m.insert(pair<int, string>(2, "two")); m.insert(pair<int, string>(1, "one")); m.insert(pair<int, string>(3, "three")); for (auto e : m) { cout << e.first << "-" << e.second << endl; } cout << endl; return 0; }
运行结果:
方式二:调用make_pair函数模板
举个栗子:
int main() { map<int, string> m; // 构造一个匿名对象插入 m.insert(make_pair(2, "two")); m.insert(make_pair(1, "one")); m.insert(make_pair(3, "three")); for (auto e : m) { cout << e.first << "-" << e.second << endl; } cout << endl; return 0; }
运行结果:
注意事项:
- 若待插入元素的键值key在map当中不存在,则insert函数插入成功,并返回插入后元素的迭代器和true。
- 若待插入元素的键值key在map当中已经存在,则insert函数插入失败,并返回map当中键值为key的元素的迭代器和false。
🌙C++的multimap
介绍:
multimap容器和map容器的区别与multiset容器和set容器的区别一样,multimap允许键值冗余,即multimap容器当中存储的元素是可以重复的。
举个栗子:
int main() { multimap<int, string> mt; //插入元素(允许重复) mt.insert(make_pair(2, "two")); mt.insert(make_pair(2, "two")); mt.insert(make_pair(1, "one")); mt.insert(make_pair(3, "three")); for (auto e : mt) { cout << e.first << "-" << e.second << endl; } cout << endl; return 0; }
运行结果:
🌟结束语
今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。