c++ map unordered_map使用大全
Posted bitcarmanlee
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++ map unordered_map使用大全相关的知识,希望对你有一定的参考价值。
1.插入元素
map中插入元素的方法有如下集中
1.1 直接用[]符
map<int, string> mymap;
mymap[1] = "a";
map的源码中重载了[]操作符,
map<_Key, _Tp, _Compare, _Allocator>::operator[](key_type&& __k)
return __tree_.__emplace_unique_key_args(__k,
_VSTD::piecewise_construct,
_VSTD::forward_as_tuple(_VSTD::move(__k)),
_VSTD::forward_as_tuple()).first->__get_value().second;
而且从上面代码不难看出,[]操作,先是move掉了map中原有的数据,再将新数据放进去,所以用[]操作的话,可以改变map中已有的key对应的value。
1.2 make_pair
make_pair是比较方便的方法,该方法可以根据传入的两个参数,直接构造成一个pari对象,insert到map中。
mymap.insert(make_pair(3, "c"));
1.3 pair
可以使用pari方法插入kv对。
mymap.insert(pair<int, string>(4, "d"));
1.4 value_type
为了避免隐式转换,可以使用value_type来传递类型,value_type是容器中本身提供的型别定义。
mymap.insert(map<int, string>::value_type(2, "b"));
需要注意的一点是,所有insert方式,如果插入的key值在map中原来存在,都不能改变其原来对应的值。
2.判断元素是否存在
2.1 find方法
bool one_in_map = mymap.find(1) != mymap.end()? true:false;
如果key在map中,find方法会返回key对应的迭代器。如果key不存在,find会返回end。
2.2 count方法
bool five_in_map = mymap.count(5) > 0? true: false;
count方法可以统计key在map中出现的次数。对于map来书,key不能重复,因此count方法返回值为1或者0。
3.获取key对应的值
3.1 find方法
前面我们已经提到了find方法可以找到key对应的迭代器
string one_value = mymap.find(1)->second;
3.2 at方法
at方法可以直接返回key对应的值
string two_value = mymap.at(2);
3.3 []操作符
[]也可以直接获取key对应的值。不过需要注意的是,如果key不在map中,[]这种方式会将key插入map中,而前面的find方法,at方法, 都会报异常。
string six_value = mymap[6];
4.删除元素
erase方法可以删除map中的元素。
mymap.erase(1);
注意删除元素的时候,当删除迭代器所指向的对象时,迭代器可能会失效。
for(iter=mymap.begin(); iter!=mymap.end(); iter++)
mymap.erase(iter);
上述代码在运行的时候就会报错,在我自己机器上测试的时候会有如下错误
libc++abi.dylib: terminating with uncaught exception of type std::bad_alloc: std::bad_alloc
对iter直线的元素进行erase时,会使得iter不再成为一个有效的迭代器,如果此后未对iter重新设值就使用iter,会出现异常。iter++就能导致一个未定义行为。
如果我们要在迭代器中删除元素,可以按照如下方式:
for(iter=mymap.begin(); iter!=mymap.end();)
if (iter->second=="c")
mymap.erase(iter++);
else
iter++;
5.遍历map
遍历容器是最常见的需求,一般可以通过下面两种方式来遍历。
5.1 通过迭代器
map<int, string>::iterator iter;
for(iter=mymap.begin(); iter!=mymap.end(); iter++)
cout<<iter->first<<": "<<iter->second<<endl;
5.2 auto关键字
上面的iter类型比较复杂,我们可以偷懒使用auto关键字,让编译器自动推断类型。
for(auto node: mymap)
cout<<node.first<<": "<<node.second<<endl;
6.unordered_map用法
unordered_map与map的用法基本一直,最大的区别在于:
map的key是有序的,而unordered_map的key为无序。
void f2()
map<int, string> commap;
unordered_map<int, string> umap;
commap[1]="a"; commap[3]="c"; commap[2]="b"; commap[4]="d";
umap[1]="aa"; umap[3]="cc"; umap[4]="dd"; umap[2]="bb";
for(auto node: commap)
cout<<node.first<<": "<<node.second<<endl;
for(auto node: umap)
cout<<node.first<<": "<<node.second<<endl;
以上代码输出:
2: b
3: c
4: d
2: bb
4: dd
3: cc
1: aa
对比map与unordered_map,两者的区别如下:
实现方式:unordered_map为哈希表,map为红黑树。
查找操作:unordered_map 平均为O(1),最差为O(n), map为log(n)。
插入,删除操作:unordered_map与查找一样,map为log(n)+平衡二叉树所用的时间。
适用场景:unordered_map适用查找频率高,而map适合要求key有序的场景。
void f2()
map<int, string> commap;
unordered_map<int, string> umap;
commap[1]="a"; commap[3]="c"; commap[2]="b"; commap[4]="d";
umap[1]="aa"; umap[3]="cc"; umap[4]="dd"; umap[2]="bb";
for(auto node: commap)
cout<<node.first<<": "<<node.second<<endl;
for(auto node: umap)
cout<<node.first<<": "<<node.second<<endl;
输出结果为
1: a
2: b
3: c
4: d
2: bb
4: dd
3: cc
1: aa
7.map自定义key排序规则
map的key,默认是按照升序排列的,可以参考一下其中源码
template <class _Key, class _Tp, class _Compare = less<_Key>,
class _Allocator = allocator<pair<const _Key, _Tp> > >
class _LIBCPP_TEMPLATE_VIS map
...
其中less的签名为
struct _LIBCPP_TEMPLATE_VIS less : binary_function<_Tp, _Tp, bool>
_LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
bool operator()(const _Tp& __x, const _Tp& __y) const
return __x < __y;
;
根据上述代码不难看出,less是一个结构体,重载了()操作符,是一个函数对象,默认升序排列。
如果我们想让map按key降序排列,可以这样
map<string, int, greater<string>> map1;
其中greater与less就是对应的,表示降序。
如果想自定义排序规则,也是可以的。
void f3()
map<string, int, greater<string>> map1;
map1["a"]=1; map1["b"]=2; map1["c"]=3; map1["d"]=4;
for(auto node: map1)
cout<<node.first<<": "<<node.second<<endl;
cout<<endl;
map<string, int, myCompare> map2;
map2["bbbb"]=1; map2["ccc"]=2; map2["a"]=3; map2["dd"]=4;
for(auto node: map2)
cout<<node.first<<": "<<node.second<<endl;
int main(int argc, char const *argv[])
f3();
return 0;
d: 4
c: 3
b: 2
a: 1
bbbb: 1
ccc: 2
dd: 4
a: 3
我们重写了一个类似less结构体,重载()操作符,就可以实现自己的排序规则。
8.map按value排序
如果我们想要对map按照value排序,可以利用stl库中的sort方法。我们可以将map中的元素先拷贝到vector中,再对vector进行排序。
bool mycompare_func(const pair<string, int> &a, const pair<string, int> &b)
if (a.second==b.second) return a.first>b.first;
else return a.second>b.second;
void f4()
map<std::string, int> mymap"b", 1, "d", 2, "c", 3, "a", 4;
vector<pair<std::string, int>> v(mymap.begin(), mymap.end());
sort(v.begin(), v.end(), mycompare_func);
for(auto node: v)
cout<<node.first<<": "<<node.second<<endl;
int main(int argc, char const *argv[])
f4();
return 0;
最后代码输出结果为
a: 4
c: 3
d: 2
b: 1
以上是关于c++ map unordered_map使用大全的主要内容,如果未能解决你的问题,请参考以下文章
在 C++ unordered_map 中有效地使用 [] 运算符
C++ std::unordered_map 中使用的默认哈希函数是啥?
c++ 中的 map 和 unordered_map 在内存使用方面有啥区别吗?