irpas技术客

c++ map unordered_map使用大全_bitcarmanlee_c++ unordered_map用法

irpas 1676

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


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #C #unordered_map用法 #直接用符mapampltint #Stringampgt #mymapmymap1