c++ 常用STL 之unordered_map

c++ 常用STL 之set_kangshuangzhu的博客-CSDN博客 中总结了关联式容器和set。这一篇介绍一下unordered_map的用法。

之所以介绍unordered_map而不是map,是因为unordered_map在效率上有明显的优势

                  | map             | unordered_map
---------------------------------------------------------
Ordering        | increasing  order   | no ordering
                | (by default)        |

Implementation  | Self balancing BST  | Hash Table
                | like Red-Black Tree |  

search time     | log(n)              | O(1) -> Average 
                |                     | O(n) -> Worst Case

Insertion time  | log(n) + Rebalance  | Same as search
                      
Deletion time   | log(n) + Rebalance  | Same as search

unordered_map还是从初始化,增,删,改, 查入手

初始化

    std::unordered_map<std::string, std::string> m1;
 
    // list constructor
    std::unordered_map<int, std::string> m2 =
    {
        {1, "foo"},
        {3, "bar"},
        {2, "baz"},
    };
 
    // copy constructor
    std::unordered_map<int, std::string> m3 = m2;
 
    // move constructor
    std::unordered_map<int, std::string> m4 = std::move(m2);
 
    // range constructor
    std::vector<std::pair<std::string, int>> v = { {"0x12", 1}, {"0x01",-1} };
    std::unordered_map<std::string, double> m5(v.begin(), v.end());

这里需要注意的问题是unordered_map的key一定得是可hash的,即自己带有hash函数,否则就不能当做unordered_map的key。 不过可以当做map的key,因为map以红黑树形式存储。

遍历 

    std::vector<std::pair<std::string, int>> v = { {"0x12", 1}, {"0x01",-1},  {"0x00",-1} ,{"0x03",-2}};
    std::unordered_map<std::string, double> m5(v.begin(), v.end());
    for(auto i: m5){
        std::cout << i.first << " " << i.second << std::endl;
    }
    for(auto i = m5.begin(); i != m5.end(); i++){
        std::cout << i -> first << " " << i -> second << std::endl;
    }

 在第二种方法中,因为i是迭代器(benzhi jius

查找某个元素

    std::vector<std::pair<std::string, int>> v = { {"0x12", 1}, {"0x01",-1},  {"0x00",-1} ,{"0x03",-2}};
    std::unordered_map<std::string, double> m5(v.begin(), v.end());
    auto i = m5.find("0x12");
    std::cout << i -> first << " " << i -> second << std::endl;

如果find没有找到某键值对,则返回迭代其end() 

这里可以看到查找和遍历的时候,对map的一个键值对的处理特别像pair,事实上c++确实是把map的一个键值对当成了pair来处理的。下面的代码可以很清晰的看到这个特点

    std::vector<std::pair<std::string, int>> v = { {"0x12", 1}, {"0x01",-1},  {"0x00",-1} ,{"0x03",-2}};
    std::unordered_map<std::string, double> m5(v.begin(), v.end());
    auto i = m5.find("0x12");
    std::cout << typeid(*i).name()  << std::endl;

输出
NSt3__14pairIKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEdEE

unordered_map还有一个类似java的写法 map[key]  但是应该特别注意,用这种写法查询一个key的值的时候,如果key不存在,会给把key加入到map中,value添加一个默认值。而且这种写法可以直接修改map中一个key的值

    std::unordered_map<std::string,std::string> mp;
    std::cout << "kkk " << (mp.find("kkk") == mp.end()) << std::endl;
    std::cout << "kkk " << mp["kkk"] << std::endl;
    std::cout << "kkk " << (mp.find("kkk") == mp.end()) << std::endl;
    mp["kkk"] += "nonono"; 
    std::cout << "kkk " << mp["kkk"] << std::endl;
输出

kkk 1
kkk 
kkk 0
kkk nonono

value的默认值对数值类型是0 ,string类型是空字符串,其他类型没有尝试过,但为了不增加debug难度,最好不要用于其他的复杂结构。

有的版本c++中unordered_map有at这个函数,有的版本没有,为了保险起见,最好不要用这个函数。

判断unordered_map 是否包含某个元素:

umap.find(x) != map.end()//查
//或者
umap.count(x) != 0

empty()  返回map是否为空

size()  返回map大小

unordered_map也是一个无序容器,所以新增元素的时候位置并不重要。

emplace

    std::vector<std::pair<std::string, int>> v = { {"0x12", 1}, {"0x01",-1},  {"0x00",-1} ,{"0x03",-2}};
    std::unordered_map<std::string, double> m5(v.begin(), v.end());
    for(auto i: m5){
        std::cout << i.first << " " << i.second << std::endl;
    }
    m5.emplace("kkk",20);
    for(auto i = m5.begin(); i != m5.end(); i++){
        std::cout << i -> first << " " << i -> second << std::endl;
    }

emplace一次向map中添加一个键值对。

 insert 可以一次性插入多个键值对

    std::vector<std::pair<std::string, int>> v = { {"0x12", 1}, {"0x01",-1},  {"0x00",-1} ,{"0x03",-2}};
    std::unordered_map<std::string, double> m5(v.begin(), v.end());
    // auto i = m5.find("0x12");
    // std::cout << typeid(*i).name()  << std::endl;
    // std::cout << i -> first << " " << i -> second << std::endl;
    for(auto i: m5){
        std::cout << i.first << " " << i.second << std::endl;
    }
    m5.insert({{"kkk",20},{"sss",3}});
    for(auto i = m5.begin(); i != m5.end(); i++){
        std::cout << i -> first << " " << i -> second << std::endl;
    }

当然,insert也可以用来合并两个map

    std::vector<std::pair<std::string, int>> v = { {"0x12", 1}, {"0x01",-1},  {"0x00",-1} ,{"0x03",-2}};
    std::unordered_map<std::string, double> m5(v.begin(), v.end());
    for(auto i: m5){
        std::cout << i.first << " " << i.second << std::endl;
    }
    std::unordered_map<std::string, double> m6 = { {"yyy", 23}, {"uuu", 34}};
    m5.insert(m6.begin(), m6.end());
    for(auto i = m5.begin(); i != m5.end(); i++){
        std::cout << i -> first << " " << i -> second << std::endl;
    }

clear 删除所有元素

erase 删除某个键值对

    std::vector<std::pair<std::string, int>> v = { {"0x12", 1}, {"0x01",-1},  {"0x00",-1} ,{"0x03",-2}};
    std::unordered_map<std::string, double> m5(v.begin(), v.end());
    for(auto i: m5){
        std::cout << i.first << " " << i.second << std::endl;
    }
    std::unordered_map<std::string, double> m6 = { {"yyy", 23}, {"uuu", 34}};
    m5.erase("0x03");
    for(auto i = m5.begin(); i != m5.end(); i++){
        std::cout << i -> first << " " << i -> second << std::endl;
    }

修改一个key的值是用的最多的场景

	auto it = umap.find(key) //改
	if(it != umap.end()) {it->second = new_value; }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值