C++ map容器总结
map基本概念
简介:
-
map中所有元素都是pair
-
pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
-
所有元素都会根据元素的键值自动排序
底层实现:
-
基于红黑树实现,红黑树是一种自平衡的二叉搜索树。
-
元素按照键的顺序存储,键是有序的。
-
插入、删除和查找操作的时间复杂度为O(log n),其中
n是容器中元素的数量。
查找性能:
-
std::map:查找效率为O(log n),适合对查找性能要求不高,但需要按键值有序存储的场景。
插入和删除性能:
-
std::map:插入和删除操作的时间复杂度为O(log n)。
键的有序性
-
键是有序的,元素会按照键的顺序存储和遍历。
-
遍历时可以保证按键的升序(或自定义的比较顺序)
内存使用
-
内存使用相对较为紧凑,因为红黑树的节点结构相对简单。
-
但红黑树的指针结构会占用一定的内存。
使用场景
-
适用于需要按键值有序存储的场景,例如:
-
按键值排序输出。
-
实现有序的映射关系。
-
需要频繁的范围查找(如
lower_bound、upper_bound)。
-
优点:
-
可以根据key值快速找到value值
map和multimap区别:
-
map不允许容器中有重复key值元素
-
multimap允许容器中有重复key值元素
map构造和赋值
功能描述:
-
对map容器进行构造和赋值操作
函数原型:
-
map<T1 T2> mp; //map默认构造函数
-
map(const map &mp); //拷贝构造函数
赋值:
-
map& operator=(const map &mp); //重载等号操作符
map大小和交换
功能描述:
-
统计map容器大小以及交换map容器
函数原型:
-
size(); //返回容器中元素的数目
cout << "Size: " << myMap.size() << endl;
-
empty(); //判断容器是否为空
if (myMap.empty()) {
cout << "Map is empty" << endl;
}
-
swap(st); //交换两个集合容器
map<int, string> anotherMap;
myMap.swap(anotherMap); // 交换两个map的内容
map访问元素
operator[]
myMap[4] = "four"; // 插入或修改键为4的元素
cout << myMap[4] << endl; // 输出 "four"
注意:如果键不存在,则会插入一个默认值。 请谨慎使用该方法访问不存在的元素!!!
当调用 mp[key] 时:
情况 1:key 已存在
map<string, int> mp;
mp["a"] = 1;
int &u = mp["a"]; // 返回已存在元素的引用,u = 1
情况 2:key 不存在
map<string, int> mp; // mp 是空的
int &u = mp["b"];
// 1. 自动插入 {key, value},value 是 int 的默认值
// 2. int 的默认值是 0
// 3. 所以 mp 变为 {"b": 0}
// 4. 返回 value 的引用,u = 0
为什么默认是 0?
C++ 标准规定:map::operator[] 对于不存在的 key,会执行值初始化(value-initialization)。
// map<T1, T2> 中,如果 T2 是:
map<string, int> // int 的默认值:0
map<string, double> // double 的默认值:0.0
map<string, bool> // bool 的默认值:false
map<string, string> // string 的默认值:"" (空字符串)
map<string, int*> // 指针的默认值:nullptr
at()
string value = myMap.at(4); // 安全访问,如果键不存在会抛出异常
map插入和删除
功能描述:
-
map容器进行插入数据和删除数据
函数原型:
-
insert(elem);// 在容器中插入元素。
//四种插入方法
map<int,int>m;
//第一种
m.insert(pair<int,int>(1,10));
//第二种
m.insert(make_pair(2,20));
//第三种
m.insert(map<int,int>::value_type(3,30));
//第四种,不建议使用[]插入,但可以使用[]访问
//当错误的使用 [] 赋值时,会在map中额外的插入一个元素
m[4] = 40;
- emplace() 原地构造一个键值对并插入,效率更高。
myMap.emplace(3, "three");
-
clear();// 清除所有元素
myMap.clear(); // 清空所有元素
-
erase(pos);// 删除pos迭代器所指的元素,返回下一个元素的迭代器。 -
erase(beg, end);// 删除区间[beg, end)的所有元素,返回下一个元素的迭代器。 -
erase(key);// 删除容器中值为key的元素。
myMap.erase(1); // 删除键为1的元素
myMap.erase(it); // 删除迭代器指向的元素
map查找和统计
功能描述:
-
对map容器进行查找数据以及统计数据
函数原型:
-
find(key);// 查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
auto it = myMap.find(2);
if (it != myMap.end()) {
std::cout << "Found: " << it->second << std::endl;
}
-
count(key);// 统计key的元素个数,返回1表示存在,0表示不存在。
int count = myMap.count(2); // 返回1或0
-
查找 --- find (返回的是迭代器)
-
统计 --- count (对于map,结果为0或者1)
int main() {
std::map<int, std::string> myMap;
myMap[1] = "one";
myMap[2] = "two";
int key = 3;
// count() 返回键出现的次数(map中只能是0或1)
if (myMap.count(key) > 0) {
std::cout << "键 " << key << " 存在" << std::endl;
} else {
std::cout << "键 " << key << " 不存在" << std::endl;
}
// 或者更简洁
if (myMap.count(key)) {
std::cout << "键存在" << std::endl;
}
return 0;
}
map容器自定义排序
-
map容器默认排序规则为按照key值进行从小到大排序
主要技术点:
-
利用仿函数可以指定map容器的排序规则
-
对于自定义数据类型,map必须要指定排序规则,同set容器
内置数据类型定义仿函数调整map排序方法
#include<iostream>
#include<string>
#include<map>
using namespace std;
class myCompare{
public:
//定义仿函数
bool operator()(int a, int b)const{
return a > b;
}
};
int main(){
map<int,string> m1;
m1.insert(pair<int,string>(10,"a"));
m1.insert(pair<int,string>(20,"b"));
m1.insert(pair<int,string>(30,"c"));
m1.insert(pair<int,string>(40,"d"));
for(map<int,string>::iterator it = m1.begin(); it != m1.end(); it++){
cout << it->first << " " << it ->second << endl;
}
cout << "--------------------------------" << endl;
map<int,string,myCompare> m2;
m2.insert(pair<int,string>(10,"a"));
m2.insert(pair<int,string>(20,"b"));
m2.insert(pair<int,string>(30,"c"));
m2.insert(pair<int,string>(40,"d"));
for(map<int,string,myCompare>::iterator it = m2.begin(); it != m2.end(); it++){
cout << it->first << " " << it ->second << endl;
}
}
输出结果如下:

自定义数据类型定义仿函数调整map排序方法
如果不定义仿函数,则无法直接按键插入自定义数据类型
#include<iostream>
#include<set>
#include<iostream>
#include<string>
#include<map>
using namespace std;
class Person{
public:
Person(string name, int age){
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
class comparePerson{
public:
// 定义仿函数
bool operator()(const Person&p1,const Person&p2)const{
return p1.m_Age > p2.m_Age;
}
};
int main(){
Person p1("张三",20);
Person p2("李四",21);
Person p3("王五",22);
Person p4("赵六",23);
map<Person,string,comparePerson> m1;
m1.insert(pair<Person,string>(p1,"a"));
m1.insert(pair<Person,string>(p2,"b"));
m1.insert(pair<Person,string>(p3,"c"));
m1.insert(pair<Person,string>(p4,"d"));
for(map<Person,string,comparePerson>::iterator it = m1.begin(); it != m1.end(); it++){
cout << " 姓名:" << it->first.m_Name << " 年龄:" << it->first.m_Age << " 等级:" << it ->second << endl;
}
}
输出结果如下:

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)