文章目录
- map
- map模板参数
- 默认构造
- 迭代器
- [ ]
- { }
- insert
- erase
- find
- lower_bound && upper_bound
- count
- equal_range
map和set容器,multimap和multiset是树形结构的关联式容器,这四种容器底层原理都是红黑树,容器中的元素是一个有序序列。
map
1.map是关联式容器,它是按照特定的次序(按照key来比较),存储由键key和值value组成的键值对
2.在map中,键值key通常用于排序和唯一的标识元素,而value中存储与此键值key关联的内容。键值key和value的类型可能不同,并且在map内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair:
typedef pair<const key, T> value_type;
3.在内部,map中的元素总是按照键值key进行比较排序的
4.map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
5. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
6. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。
map模板参数
Compare:仿函数,缺省参数为less,默认是以升序(对于string是字典序)排序的,我们可以给该类型传递参数greater,将容器中的顺序改为降序。如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)
默认构造
1.空的map
2.使用区间来初始化
3.拷贝构造
4.移动语义
5.可变参数列表初始化
map<string, string> m1;//空容器
vector<pair<string, string>> v{ {"hello", "你好"}, {"sort", "排序" }};
/*cout << (*v.begin()).first << endl;
cout << (*v.begin()).second << endl;*/
map<string, string> m2(v.begin(), v.end());//区间初始化
map<string, string> m3(m2);
map<string, string> m4{ { "hello", "你好" }, { "sort", "排序" } };//可变参数列表初始化
迭代器
begin:返回容器的第一个元素位置
end:返回容器最后一个元素的下一个位置
rbegin:返回最后一个元素位置------底层其实是返回的end() - 1
rend:返回第一个元素的前一个位置------底层其实是返回的begin()-1
c:返回的是const迭代器,元素不可以被修改
迭代器具体实现请阅读C++迭代器底层实现
[ ]
map允许根据key值直接访问对应的value
int main()
{
map<string, string> dict;
dict.insert(make_pair("string", "字符串"));
dict.insert(make_pair("sort", "排序"));
dict.insert(make_pair("insert", "插入"));
dict["string"]; //查找和读
dict["map"]; //插入
dict["map"] = "地图,映射";//修改
dict["set"] = "集合";//插入 + 修改
return 0;
}
map容器[]的底层是通过insert来实现的
底层
V& operator[](const K& key)
{
pair<iterator, bool> ret = insert(make_pair(key, V()));
return ret.first->second;
}
在使用[],当map中不存在对应的key时,会将该key值插入到map中,value此时传的是value对应类型的匿名对象
operator[]的返回值value
map<string, string> m1{ { "hello", "你好" }, { "sort", "排序" } };
string ret = m1["sort"];//根据[]直接访问元素
cout << ret << endl;
m1["hello"] = "你好!";//修改key值对应的value
cout << m1["hello"] << endl;
map允许通过key对应的修改value
int main()
{
map<string, string> dict;
dict.insert(make_pair("string", "字符串"));
dict.insert(make_pair("sort", "排序"));
dict.insert(make_pair("insert", "插入"));
dict["string"]; //查找和读
dict["map"]; //插入
dict["map"] = "地图,映射";//修改
dict["set"] = "集合";//插入 + 修改
return 0;
}
{ }
map<string, string> m;
m.insert({"insert", "插入"});
C++11支持{ },多参数的构造函数隐式类型转换,在底层会将{}转化为make_pair
insert
map的插入,插入的是键值对
1.插入一个键值对
3.插入一个区间
4.插入一个可变参数列表
map<string, string> m1{ { "hello", "你好" }, { "sort", "排序" } };
m1.insert(make_pair("David", "戴维"));
for (auto& e : m1)
{
cout << e.first << ": " << e.second << endl;
}
return 0;
map<string, string> m1{ { "hello", "你好" }, { "sort", "排序" } };
m1.insert(make_pair("David", "戴维"));//插入单个键值对
for (auto& e : m1)
{
cout << e.first << ": " << e.second << endl;
}
map<string, string> m2;
m2.insert(m1.begin(), m1.end());//插入一个区间
for (auto& e : m2)
{
cout << e.first << ": " << e.second << endl;
}
for (auto& e : m2)
{
cout << e.first << ": " << e.second << endl;
}
map<string, string> m3;
m3.insert({ { "hello", "你好" }, { "sort", "排序" } });//插入一个可变参数列表
for (auto& e : m3)
{
cout << e.first << ": " << e.second << endl;
}
erase
map<string, string> m1{ { "hello", "你好" }, { "sort", "排序" }, {"David", "戴维"}, {"leave", "离开"} };
for (auto& e : m1)
{
cout << e.first << ": " << e.second << endl;
}
map<string, string>::iterator it = m1.begin();
m1.erase(it);//根据迭代器的指向删除对应的键值对
m1.erase("leave");//根据key删除键值对
cout << endl;
for (auto& e : m1)
{
cout << e.first << ": " << e.second << endl;
}
it = m1.begin();
m1.erase(++it, m1.end());//删除某一个区间
cout << endl;
for (auto& e : m1)
{
cout << e.first << ": " << e.second << endl;
}
find
find返回值为指向该键值对的迭代器指针
map<string, string> m1{ { "hello", "你好" }, { "sort", "排序" }, {"David", "戴维"}, {"leave", "离开"} };
map<string, string>::iterator it = m1.find("sort");//通过key找到对应的键值对
cout << (*it).first << ": " << (*it).second << endl;
if (it != m1.end())
{
m1.erase(it);
}
lower_bound && upper_bound
下界
上界:
map<string, string> m1{ {"David", "戴维"}, { "hello", "你好" }, {"leave", "离开"}, { "sort", "排序" } };
map<string, string>::iterator lower_it1 = m1.lower_bound("hello");
map<string, string>::iterator lower_it2 = m1.lower_bound("i");
cout << (*lower_it1).first << " " << (*lower_it1).second << endl;//hello : 你好
cout << (*lower_it2).first << " " << (*lower_it2).second << endl;//leave : 离开
cout << endl;
map<string, string>::iterator upper_it1 = m1.upper_bound("hello");
map<string, string>::iterator upper_it2 = m1.upper_bound("i");
cout << (*upper_it1).first << " " << (*upper_it1).second << endl;//leave : 离开
cout << (*upper_it2).first << " " << (*upper_it2).second << endl;//leave : 离开
map中的数据默认是以字典序进行排序的
map<string, string> m1{ { "hello", "你好" }, { "sort", "排序" }, {"David", "戴维"}, {"leave", "离开"} };
map<string, string, greater<string>> m2{ { "hello", "你好" }, { "sort", "排序" }, {"David", "戴维"}, {"leave", "离开"} };
for (auto& e : m1)
{
cout << e.first << ": " << e.second << endl;
}
cout << endl;
for (auto& e : m2)
{
cout << e.first << ": " << e.second << endl;
}
count
根据key统计它在容器中出现的次数,主要用于multimap中,因为map中不允许出现相同key的数据,对于multimap允许出现同key的数据,即使value也是相同的
map<string, string> m1{ {"David", "戴维"}, { "hello", "你好" }, {"leave", "离开"}, { "sort", "排序" },{"David", "戴维"}, { "hello", "你好" }, {"leave", "离开"}, { "sort", "排序" } };
multimap<string, string> m2{ {"David", "戴维"}, { "hello", "你好" }, {"leave", "离开"}, { "sort", "排序" },{"David", "戴维"}, { "hello", "你好" }, {"leave", "离开"}, { "sort", "排序" } };
cout << m1.count("David") << endl;//1
cout << m2.count("David") << endl;//2
m2.insert({ "David", "阿伟" });
cout << m2.count("David") << endl;//3
equal_range
用于返回一个多个相同key在容器中的区间,这个函数也是主要用于multimap中,对于map某一个key在这个容器中最多只会出现一次因此用处不大
返回值是一个pair对象,first指向该key值在容器中第一次出现的位置指向的仍是一个pair对象,second指向该key值在容器中最后一次出现位置的下一个位置,如果没有该key值,则返回的是一个不存在的区间
下面的it1.first在这里指向的仍是一个pair对象
map<string, string> m1{ {"David", "戴维"}, { "hello", "你好" }, {"leave", "离开"}, { "sort", "排序" }};
multimap<string, string> m2{ {"David", "戴维"}, { "hello", "你好" }, {"leave", "离开"}, { "sort", "排序" },
{"David", "戴维"}, { "hello", "你好" }, {"leave", "离开"}, { "sort", "排序" }, {"David", "戴维"}};
pair<map<string, string>::iterator, map<string, string>::iterator> it1 = m1.equal_range("David");
pair<multimap<string, string>::iterator, multimap<string, string>::iterator> it2 = m2.equal_range("David");
cout << it1.first->first << " " << it1.second->first << endl;
//等价于(*it1.first).second
cout << it2.first->first << " " << it2.second->first << endl;
m2.erase(it2.first, it2.second);
for (auto& e : m2)
{
cout << e.first << ": " << e.second << endl;
}