map
模板类
实现原理
红黑树存储键值对,红黑树的key就是传递的key,value是pair对象。
注意一些函数的参数,比如find函数:利用key寻找值,返回迭代器,而不是利用值寻找值。
|-----------|----------------------------------------------------------------------------------------------------------------------|
| find(key) | 在 map 容器中查找键为 key 的键值对,如果成功找到,则返回指向该键值对的双向迭代器;反之,则返回和 end() 方法一样的迭代器。另外,如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。 |
map容器的迭代器
一定要注意:map容器中存放的不是键值对,也不是值。而是pair模板结构体,pair中才是存储键值对。
对map容器的迭代器进行指向操作,指向的是pair结构体中的函数或者变量。
对于map的迭代器(iterator),对其解引用后,就是一个pair对象,所以iterator->first = 键、iterator->second = 值。
map容器和其他容器迭代器解引用的相同点和不同点
相同点:解引用的结果都是容器中存储的元素(对象)。
不同点:
其他容器解引用出来的元素就是存储的值;
map容器解引用出来的是也是其元素,但是这个元素是一个pair对象,而不直接就是存储的值。
总结一句话:
容器中存储的是什么,迭代器解引用就是的结果就是什么。
map容器建立和存储的过程
建立map容器
容器内建立pair对象存储键值对
容器内建立RB-tree对象存储pair。
map容器初始化和赋值方法
1,赋值:{{},{}}赋值法。
2,拷贝:利用赋值构造函数:map<int,string>ffmap(fmap);
3,截取:
map 类模板还支持取已建 map 容器中指定区域内的键值对,创建并初始化新的 map 容器。例如:
- std::map<std::string, int>myMap{ {"C语言教程",10},{"STL教程",20} };
- std::map<std::string, int>newMap(++myMap.begin(), myMap.end());
这种方法注意end()的选择,如果要选择到最后,不要--mymap.end();
4,下标赋值。
复制代码
map<int,string>mymap{{0,"fangfang"},{1,"xiaoli"}};
auto ite=mymap.find(1);
cout<<(*ite).second<<endl;
cout<<ite->first<<" "<<ite->second<<endl;
map<int,string> fmap;
fmap[0]="aaaa";
fmap[1]="bbbb";
fmap[2]="cccc";
int i=0;
for(i;i<fmap.size();i++)
{
cout<<fmap[i]<<" ";
}
cout<<endl;
map<int,string>ffmap(fmap);
for(i=0;i<ffmap.size();i++)
{
cout<<ffmap[i]<<" ";
}
cout<<endl;
map容器不能像vector一样从数组中获取值。
5,insert插入法:
insert可以先建立pair键值对再插入,也可以插入临时值(右值引用插入):
复制代码
int main()
{
map<string,string>mymap;
pair<map<string,string>::iterator,bool> ret=mymap.insert({"China","Beijing"});
cout<<ret.first->first<<"---"<<ret.first->second<<endl;
pair<string,string> add={"Americ","Niuyake"};
ret=mymap.insert(add);
cout<<ret.first->first<<"---"<<ret.first->second<<endl;
return 0;
}
~
注意:
(1,pair键值对的定义,
(2,insert返回类型以及如何定义返回类型变量。
(3,insert还可以同时插入多个键值对。
关于Insert更多看-------连接
6,两个效率更高的插入方法:
1》
template <class... Args>
pair<iterator,bool> emplace (Args&&... args);
- 当该方法将键值对成功插入到 map 容器中时,其返回的迭代器指向该新插入的键值对,同时 bool 变量的值为 true;
- 当插入失败时,则表明 map 容器中存在具有相同键的键值对,此时返回的迭代器指向此具有相同键的键值对,同时 bool 变量的值为 false。
- 返回类型同insert
2》
template <class... Args>
iterator emplace_hint (const_iterator position, Args&&... args);
- 该方法不仅要传入创建键值对所需要的数据,还需要传入一个迭代器作为第一个参数,指明要插入的位置(新键值对键会插入到该迭代器指向的键值对的前面);
- 该方法的返回值是一个迭代器,而不再是 pair 对象。当成功插入新键值对时,返回的迭代器指向新插入的键值对;反之,如果插入失败,则表明 map 容器中存有相同键的键值对,返回的迭代器就指向这个键值对。
3**. 成功,返回一个指向键值对的迭代器。**
复制代码
int main()
{
map<string,int>mymap;
pair<map<string,int>::iterator,bool> ret=mymap.emplace("China",1);
cout<<ret.first->first<<" "<<ret.first->second<<endl;
map<string,int>::iterator ite=mymap.emplace_hint(mymap.end(),"Americ",2);
cout<<ite->first<<" "<<ite->second<<endl;
return 0;
}
map访问值的方法
1,迭代器指向second对象:ite-second;
2,迭代器解引用之后引用second:(*ite).second;
3,下标访问(键作为下标访问):
需要特别注意的是:这个下标是键值,而不一定是0,1,2这些数字,。
eg:
mymap["YunNan"]
因为map是可以修改值的值的,所以:
mymap["YunNan"]="sanqizhixiang"
注意,只有当 map 容器中确实存有包含该指定键的键值对,借助重载的 [ ] 运算符才能成功获取该键对应的值;反之,若当前 map 容器中没有包含该指定键的键值对,则此时使用 [ ] 运算符将不再是访问容器中的元素,而变成了向该 map 容器中增添一个键值对。 其中,该键值对的键用 [ ] 运算符中指定的键,其对应的值取决于 map 容器规定键值对中值的数据类型,如果是基本数据类型,则值为 0;如果是 string 类型,其值为 "",即空字符串(即使用该类型的默认值作为键值对的值)。
4,除了借助 [ ] 运算符获取 map 容器中指定键对应的值,还可以使用 at() 成员方法。和前一种方法相比,at() 成员方法也需要根据指定的键,才能从容器中找到该键对应的值;不同之处在于,如果在当前容器中查找失败,该方法不会向容器中添加新的键值对,而是直接抛出 out_of_range 异常。
mymap.at("YunNan");
注意:键和值的类型任意,不是键只能为int。
[ ]和at()
\]:
#include
#include