Map容器
Posted alexkk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Map容器相关的知识,希望对你有一定的参考价值。
map容器
是关联容器的一种,由键值对象组成,即 map 容器的元素是 pair<const K,T> 类型的对象
map容器的类型
-
map<K,T>容器,保存的是 pair<const K,T> 类型的元素。pair<const K,T> 封装了一对键对象,键的类型是 K,对象的类型是 T。每个键都是唯一的,所以不允许有重复的键;但可以保存重复的对象,只要它们的键不同。map 容器中的元素都是有序的,元素在容器内的顺序是通过比较键确定的。默认使用 less
对象比较。 -
multimap<K,T> 容器和 map<K,T> 容器类似,也会对元素排序。它的键必须是可比较的,元素的顺序是通过比较键确定的。和 map<K,T> 不同的是,multimap<K,T> 允许使用重复的键。因此,一个 multimap 容器可以保存多个具有相同键值的 <const K,T> 元素。
-
unordered_map<K,T> 中 pair< const K,T>元素的顺序并不是直接由键值确定的,而是由键值的哈希值决定的。哈希值是由一个叫作哈希的过程生成的整数,本章后面会解释这一点。unordered_map<K,T>不允许有重复的键。
-
unordered_multimap<K,T> 也可以通过键值生成的哈希值来确定对象的位置,但它允许有重复的键。
区别
- multi前缀表明键不必唯一,但如果没有这个前缀,键必须唯一。
- unordered_prefix 前缀表明容器中元素的位置是通过其键值所产生的哈希值来决定的,而不是通过比较键值决定的。如果没有该前缀,那么元素的位置就由比较键值决定。
头文件
#include<map>
#include<unorderd_map>
map的创建和初始化
1 创建
//map<K,T>
map<string, size_t> people;
map默认构造函数有四个参数,但常常只初始化前两个参数,用于构造pair对象,因为map容器里面的对象都是pair<string,size_t>,string 说明了键的类型,size_t说明了值的类型,可以通关first和second访问第一个值和第二个值
2 初始化
2.1 初始化列表,隐式的转化为pair对象
map<string,size_t> people{{"Anni",12},{"Joe",20},{"Bob",10}};
2.2 make_pair显示的构造pair对象初始化
map<string,size_t> people{make_pair("Ann",25),make_pair("Bill", 46),make_pair("Jack", 32),make_pair("Jill", 32)};
2.3 容器拷贝
map<string,size_t> peopelCopy {people};
//类型必须一致
2.4 迭代器初始化
map<string,size_t>peopleCopy2{people.begin(),people.end()}
代码实例
int main()
{
map<string,size_t> people{{"Anni",12},{"Joe",20},{"Bob",10}};
map<string, size_t> peopleCopy{people.begin(), people.end()};
for(auto &i:peopleCopy)
{
cout << i.first << " "<<i.second<<endl;
}
return 0;
}
3 Insert插入元素
3.1 初始化列表插入
由于map默认是按照less
map<string,size_t> people{{"Anni",12},{"Joe",20},{"Bob",10}};
people.insert({"Hon",3});
3.2 make_pair构造pair对象插入
map<string,size_t> people{{"Anni",12},{"Joe",20},{"Bob",10}};
auto pr = make_pair("Hon",3);
auto ret_pr = people.insert(pr);
说明:
1 make_pair返回值是一个pair对象
2 insert的返回值仍然是一个pair对象, pair 的成员变量 first 是一个指向插入元素或阻止插入的元素的迭代器;成员变量 second 是个布尔值,如果元素插入成功,second 就为 true。
cout<<ret_pr.first->first<<" "<<ret_pr.first->second<<endl;
cout<<ret_pr.second<<endl;
//Hon 3
//True
3.3 直接使用pair对象插入,右值移动
people.insert(pair<string,size_t>{"Hon", 3});
4 emplace构造元素
4.1emplace
emplace和insert的区别在于 emplace可以在适当的位置直接构造新元素,从而避免复制和移动操作,返回值同insert。
map<string,size_t> people{{"Anni",12},{"Joe",20},{"Bob",10}};
auto ret_pr = people.emplace("Kiss",9);
4.2 emplace_hint
emplace_hint() 调用使用一个迭代器作为指示符,指向先前 emplace() 调用返回的 pair 对象。如果容器使用这个提示符,那么新元素会在这个指示符表示的位置之前生成,并尽可能靠近这个位置。提示符后面的参数用来构造新元素。需要注意的是,它和 emplace() 的返回值是不一样的。emplace_hint() 的返回值不是一个 pair 对象,如果新元素被插入,它返回的是指向新元素的迭代器;如果没有插入,返回的是和这个键匹配的现有元素的迭代器,拥有相同的 key 值,如果不是现有元素的话。没有提示可以直接判断是否生成了新元素。唯一的方法是,用 size() 成员函数来获取 map 中对应元素的数量来检查 map 元素增加的数量
auto pr = people.emplace("Kiss",9);
auto iter = people.emplace_hint (pr.first,"Gine", 62);
5 map元素访问
5.1 迭代器
map<string,size_t> people{{"Anni",12},{"Joe",20},{"Bob",10}};
auto it = people.begin();
while (it != people.end())
{
cout << (*it).first << " " << (*it).second << endl;
it++;
}
5.2 at(key)
由于at()一般会检查边界,因此要对key做异常处理
map<string,size_t> people{{"Anni",12},{"Joe",20},{"Bob",10}};
string key;
try
{
key = "Anni";
cout << people.at(key) << endl;
key = "Ai";
cout << people.at(key) << endl;
}
catch (const out_of_range &e)
{
cerr << e.what() << endl;
}
-------------------------------------
12
invalid map<K,T> key
5.3 [key]
下标运算符返回一个和 键关联的对象的引用,如果key指定的对象不存在,创建一个pair对象,值为0
cout<<people["Anni"]<<endl;
cout<<people["Ai"]<<endl;
---------------------------
12
0
由于[key]返回的是引用,因此可以通过=修改key对应的值
people["Ai"]=2;
cout<<people["Ai"]<<endl;
-----------------------
2
6 erase/clear 删除元素
6.1 erase(key)
键作为参数传递,erase 返回值是删除元素的个数,如果没有对应key返回0,否则返回1
map<string,size_t> people{{"Anni",12},{"Joe",20},{"Bob",10}};
string key{"Anni"};
if(people.erase(key))
cout<<"erase success"<<endl;
else
cout<<key<<"was not found"<<endl;
auto it = people.begin();
while (it != people.end())
{
cout << (*it).first << " " << (*it).second << endl;
it++;
}
-----------------------
erase success
Joe 20
Bob 10
6.2 erase(iteration)
迭代器作为参数,返回值为迭代器,返回的迭代器指向被删除元素的下一个位置(注意是排好序的),
如果删除元素是最后一个元素,返回的迭代器指向最后一个元素。
map<string,size_t> people{{"Anni",12},{"Joe",20},{"Bob",10}};
auto it = people.begin();
auto pr = people.erase(it);
cout << (*pr).first <<" " << (*pr).second<< endl;
-----------------------------------------
Bob 10 //注意排序
还可以删除迭代器指定范围内的元素 erase(start_iter,end_iter);
6.3 clear()
删除所有元素
map<string,size_t> people{{"Anni",12},{"Joe",20},{"Bob",10}};
cout<<people.size()<<endl;
people.clear()
cout<<people.size()<<endl;
--------------------------
3
0
Pair
头文件:pair是包含在头文件utility中的,map头文件又包含了utility
#inclue<utility>
或者
#include<map>
part<T1,T2> ,T1,T2可以是任意类型
pair<int,int> p1{10,6}
pair<string,int> p2{"anni",5}
pait<TreeNode,bool> p3{root,false}
...
make_pair
auto mypair = make_pair("hello","boy");
auto youPair = make_pair<string,sting>("test","that");
.....
Tuple
tuple是pair的泛化,不仅包含两个类型的对象,当要把多个对象作为一个对象传递给函数时,tuple很有用:生成一个tuple对象使用:make_tuple
#include<tuple>
auto my_tuple = make_tuple("name",42,"address",667,..);
以上是关于Map容器的主要内容,如果未能解决你的问题,请参考以下文章