Map和multimap将key/value pair(键值/实值 队组)当作元素,进行管理。他们根据key的排序准则将元素排序。multimap允许重复元素,map不允许。
元素要求:
- key/value必须具有assigned(可赋值)和copyable(可复制的)性质。
- 对于排序而言,key必须具是comparable(可比较的)。
典型情况下,set,multisets,map,multimap使用相同的内部结构,因此可以将set和multiset当成特殊的map和multimap,只不过set的value和key指向的是同一元素。
map和multimap会根据key对元素进行自动排序,所以根据key值搜寻某个元素具有良好的性能,但是如果根据value来搜寻效率就很低了。
同样,自动排序使得你不能直接改变元素的key,因为这样会破坏正确次序,要修改元素的key,必须先移除拥有key的元素,然后插入拥有新的key/value的元素,从迭代器的观点来看,元素的key是常数,元素的value是可以直接修改的。
Map由红黑树实现,其元素都是“键值/实值”所形成的一个对组(key/value pairs)。每个元素有一个键,是排序准则的基础。每一个键只能出现一次,不允许重复。Map主要用于资料一对一映射(one-to-one)的情况,map内部自建一颗红黑树(平衡二叉树中的一种),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的。比如一个班级中,每个学生的学号跟他的姓名就存在着一对一映射的关系。
头文件 # include <map>
1、构造函数
map<int, string> a; //定义一个int类型的映射a
//map<int, string> a(10); //error,未定义这种构造函数
//map<int, string> a(10, 1); //error,未定义这种构造函数
map<int, string> b(a); //定义并用映射a初始化映射b
//map<int, string> b(a.begin(), a.end()); //error,未定义这种构造函数
代码
# include <iostream>
# include <map>
using namespace std;
template <class container>
void print(container con)
{
for (typename container::iterator it = con.begin(); it != con.end(); ++it)
{
cout << (*it).first << " " << (*it).second;
}
cout << endl;
}
int main()
{
map<int, string> a; //定义一个int类型的映射a
a.insert({ 1, "张三" });
a.insert({ 2, "李四" });
print(a);
//map<int, string> a(10); //error,未定义这种构造函数
//map<int, string> a(10, 1); //error,未定义这种构造函数
map<int, string> b(a); //定义并用映射a初始化映射b
print(b);
map<int, string> c(a.rbegin(), a.rend());//默认升序
print(c);
multimap<int, string> d; //定义一个int类型的映射a
d.insert({ 1, "张三" });
d.insert({ 1, "李四" });
print(d);
//multimap<int, string> d(10); //error,未定义这种构造函数
//multimap<int, string> d(10, 1); //error,未定义这种构造函数
multimap<int, string> e(d); //定义并用映射a初始化映射b
print(e);
multimap<int, string> f(e.rbegin(), e.rend());
print(f);
}
运行结果
2.增加函数
- 在容器中插入元素:mp.insert(const T& x);
- 任意位置插入一个元素: mp.insert(iterator it, const T& x);
代码
# include <iostream>
# include <string>
# include <map>
using namespace std;
template <class container>
int main()
{
map<char, int> mymap;
// 第一个插入功能版本(单个参数):
mymap.insert(pair<char, int>('a', 100));
mymap.insert(pair<char, int>('z', 200));
pair<map<char, int>::iterator, bool> ret;
ret = mymap.insert(pair<char, int>('z', 500));
if (ret.second == false)
{
cout << "element 'z' already existed";
cout << " with a value of " << ret.first->second << '\n';
}
// 第二个插入函数版本(带提示位置):
map<char, int>::iterator it = mymap.begin();
mymap.insert(it, pair<char, int>('b', 300)); // max efficiency inserting
mymap.insert(it, pair<char, int>('c', 400)); // no max efficiency inserting
// 第三个插入功能版本(范围插入):
map<char, int> anothermap;
anothermap.insert(mymap.begin(), mymap.find('c'));
// showing contents:
cout << "mymap contains:\n";
for (it = mymap.begin(); it != mymap.end(); ++it)
cout << it->first << " => " << it->second << '\n';
cout << "anothermap contains:\n";
for (it = anothermap.begin(); it != anothermap.end(); ++it)
cout << it->first << " => " << it->second << '\n';
}
运行结果
代码2
# include <iostream>
# include <map>
# include <string>
using namespace std;
int main()
{
map<int, string> mp;
//在容器中插入元素
mp.insert({ 1, "张三" });
mp.insert({ 2, "李四" });
//任意位置插入一个元素
map<int, string>::iterator it = mp.begin();
mp.insert(it, pair<int, string>{ 3, "隔壁老王" }); //会自动排序
for (it = mp.begin(); it != mp.end(); it++)
cout << it->first << " " << it->second << endl;
cout << endl;
return 0;
}
运行结果2
3.删除函数
- 删除键值为keyValue的元素: mp.pop_back(const T& keyValue);
- 删除迭代器所指的元素: mp.erase(iterator it);
- 删除区间[first,last]之间的所有元素: mp.erase(iterator first, iterator last);
- 清空所有元素: mp.clear();
代码
// erasing from map
#include <iostream>
#include <map>
using namespace std;
int main()
{
map<char, int> mymap;
map<char, int>::iterator it;
// insert some values:
mymap['a'] = 10;
mymap['b'] = 20;
mymap['c'] = 30;
mymap['d'] = 40;
mymap['e'] = 50;
mymap['f'] = 60;
it = mymap.find('b');
mymap.erase(it); // erasing by iterator
mymap.erase('c'); // erasing by key
it = mymap.find('e');
mymap.erase(it, mymap.end()); // erasing by range
// show content:
for (it = mymap.begin(); it != mymap.end(); ++it)
cout << it->first << " => " << it->second << '\n';
return 0;
}
运行结果
代码2
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
map<int, string> mp;
//在容器中插入元素
mp.insert({ 1, "张三" });
mp.insert({ 2, "李四" });
mp.insert({ 4, "王五" });
mp.insert({ 5, "小明" });
//任意位置插入一个元素
mp.insert(mp.begin(), pair<int, string>{ 3, "隔壁老王" }); //会自动排序
//删除键值为keyValue的元素
mp.erase(2);
//删除迭代器所指的元素
mp.erase(mp.begin());
//删除区间[first,last]之间的所有元素
mp.erase(mp.begin(), ++mp.begin());
//display map
map<int, string>::iterator it = mp.begin();
for (it = mp.begin(); it != mp.end(); it++)
cout << it->first << " " << it->second << endl;
//清空容器内的所有元素
mp.clear();
//display map
cout << "mp:";
for (it = mp.begin(); it != mp.end(); it++)
cout << it->first << " " << it->second << endl;
cout << endl;
return 0;
}
运行结果2
4. 迭代器
- 开始迭代器指针:mp.begin();
- 末尾迭代器指针:mp.end(); //指向最后一个元素的下一个位置
- 指向常量的开始迭代器指针: mp.cbegin(); //意思就是不能通过这个指针来修改所指的内容,但还是可以通过其他方式修改的,而且指针也是可以移动的。
- 指向常量的末尾迭代器指针: mp.cend();
- 反向迭代器指针,指向最后一个元素: mp.rbegin();
- 反向迭代器指针,指向第一个元素的前一个元素: mp.rend();
- 返回键值大于等于key的迭代指针,否则返回end() : mp.lower_bound(keyElem);
- 返回键值大于key的迭代指针,否则返回end() : mp.upper_bound(keyElem);
- 返回容器中键值等于key的迭代指针[first,last) : mp.equal_range(keyElem);
代码
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
map<int, string> mp;
//在容器中插入元素
mp[1] = "张三";
mp[2] = "李四";
mp[3] = "隔壁老王";
cout << "mp.begin()->first): " << mp.begin()->first << endl;
cout << "(--mp.end())->first: " << (--mp.end())->first << endl;
cout << "mp.cbegin()->first: " << mp.cbegin()->first << endl;
cout << "(--mp.cend())->first : " << (--mp.cend())->first << endl;
cout << "mp.rbegin()->first: " << mp.rbegin()->first << endl;
cout << "(--mp.rend())->first: " << (--mp.rend())->first << endl;
cout << "mp.lower_bound(2)->first: " << mp.lower_bound(2)->first << endl;
cout << "mp.upper_bound(2)->first: " << mp.upper_bound(2)->first << endl;
pair<map<int, string>::iterator, map<int, string>::iterator> t_pair = mp.equal_range(2);
cout << "t_pair.first->first: " << t_pair.first->first << endl;
cout << "t_pair.second->first: " << t_pair.second->first << endl;
cout << endl;
return 0;
}
运行结果
5.访问函数
可以使用at()函数和[]进行赋值运算
代码
// map::at
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
map<string, int> mymap = { { "alpha", 0 }, { "beta", 0 },{ "gamma", 0 } };
mymap.at("alpha") = 10;
mymap.at("beta") = 20;
mymap.at("gamma") = 30;
mymap.emplace("alpha", 100);
mymap.emplace("y", 100);
mymap.emplace("z", 200);
pair< map<string, int>::iterator, bool> ret;
ret = mymap.emplace("alpha", 100);
cout << "mymap.emplace(\"alpha\", 100) = " << ret.second<<endl;
for (auto& x : mymap) {
cout << x.first << ": " << x.second << '\n';
}
map<char, int> mymap_1;
map<char, int>::iterator it;
char c;
mymap_1['a'] = 50;
mymap_1['b'] = 100;
mymap_1['c'] = 150;
mymap_1['d'] = 200;
it = mymap_1.find('b');
if (it != mymap_1.end())
mymap_1.erase(it);
// print content:
cout << "elements in mymap:" << '\n';
cout << "a => " << mymap_1.find('a')->second << '\n';
cout << "c => " << mymap_1.find('c')->second << '\n';
cout << "d => " << mymap_1.find('d')->second << '\n';
for (c = 'a'; c < 'h'; c++)
{
cout << "mymap_1.count( " << c << " ) = " << mymap_1.count(c) << endl;
}
return 0;
}
运行结果
6.容量函数
- 容器大小: mp.size();
- 容器最大容量: mp.max_size();
- 容器判空: mp.empty();
- 查找键key的元素个数: mp.count(key);
代码
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
map<int, string> mp;
mp.insert({ 1, "张三" });
mp.insert({ 2, "李四" });
mp.insert(pair<int, string>{ 3, "隔壁老王" });
cout << "元素大小: " << mp.size() << endl;
cout << "元素最大容量: " << mp.max_size() << endl;
cout << "键2的元素个数: " << mp.count(2) << endl;
if (mp.empty())
cout << "元素为空" << endl;
return 0;
}
运行结果
7.其他函数
- 交换两个同类型容器的元素: swap(map&, map&); 或 mp.swap(map&);
代码
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
std::map<char, int> foo, bar;
foo['x'] = 100;
foo['y'] = 200;
bar['a'] = 11;
bar['b'] = 22;
bar['c'] = 33;
//swap(mp1,mp2); //ok
foo.swap(bar);
cout << "foo contains:\n";
for (map<char, int>::iterator it = foo.begin(); it != foo.end(); ++it)
cout << it->first << " => " << it->second << '\n';
cout << "bar contains:\n";
for (map<char, int>::iterator it = bar.begin(); it != bar.end(); ++it)
cout << it->first << " => " << it->second << '\n';
return 0;
}
运行结果