zoukankan      html  css  js  c++  java
  • map、multimap和unordered_map(hash_map)以及unorderd_multimap

    壹、hash_map & unordered_map

    hash_map就是unordered_map中文标准库:unordered_map
    搜索、插入和元素移除拥有平均常数时间复杂度。元素在内部不以任何特定顺序排序,而是组织进桶中。元素放进哪个桶完全依赖于其键的哈希。这允许对单独元素的快速访问,因为一旦计算哈希,则它准确指代元素所放进的桶。

    multimap 键值可以重复,中文标准库:multimap

    贰、std::map

    中文标准库std::map

    map是一个关联式的容器,它提供一对一(其中第一个可以称为关键字key,每个关键字只能在map中出现一次,且map按照key的大小排序,不是按照插入顺序,第二个称为该关键字的值value)的数据处理能力,它的特点是:增加和删除节点对迭代器的影响很小,除了操作的那个节点,对其他的节点都没有什么影响。map可以修改值value,而不能修改关键字key。

    map是容器,pair是容器map的元素,每个pair 可以存储两个值。这两种值的类型没有限制(多个值可以用tuple)

    一、构造map,插入map元素

    insert和emplace插入成功都返回当前插入元素的迭代器加一个bool值std::pair<std::map<type, type>::iterator, bool>

    map插入新的元素,是按照键值排序的,即后插入的元素,键值只要小于前面的元素就会放在前面。

        std::map<int, std::string> map1;
        map1.insert(std::pair<int, std::string>(1, "abc"));  //pair定义在 <utility>
        map1.insert(std::map<int, std::string>::value_type(2, "bbb"));  //不会覆盖前面的(2,bcd),等于插入失败
        map1.insert(std::make_pair(6, "sss"));
        map1[0] = "ddd";//这种方式会覆盖前面的元素
        std::map<int, std::string> map2{ {1,"abc"},{2,"bcd"},{2,"xyz"} };  //和insert一样,键值相同不会覆盖,即key=2,对应的value是"bcd"
        map1.emplace(3, "ggg");  //不会覆盖相同键值的元素
    

    value_type在源码中有如下定义:using value_type = pair<const _Kty, _Ty>;

    二、修改map元素

    map只能修改值value,不能直接修改键值key,如果要想修改key,可以先把该元素存到一个临时的pair再删除原来map的元素,再修改pair的第一个元素,最后再将修改后的pair插入map

        map[key] = value;    //直接用数组方式修改,这种方式,如果键值不存在则会插入一个新的元素
        std::map<int, std::string>::iterator it = map1.find(2);  //搜索键值key,返回一个迭代器,返回end则没找到key
        it->second = value;  //迭代器方式修改
    

    三、查找、访问map元素

        auto z = map1[111];   //返回键为111对应的值,如果键111不存在,则会添加一个值为空键为111的元素
        auto y = map1.at(1);  // 返回map.second,即返回键值key为1对应的值value,如果键值不匹配则会抛出异常,谨慎使用
        auto end = --map.end(); //访问map的最后一个元素,注意--位置
        std::map<int, std::string>::iterator it = map1.find(2);  //搜索键值key,返回一个迭代器,返回end则没找到key
    

    四、遍历map元素

        //1.数组方式遍历(存在局限性,键值要符合条件,比如连续)
        std::map<int, int> map3;
        for (int i = 0; i < 5; i++)
        {
            map3.emplace(i, i * 10);
        }
        for (int i = 0; i < map3.size(); i++)
        {
            std::cout << i << "," << map3[i] << std::endl;
        }
        //2.迭代器遍历
        for (auto it = map1.begin(); it != map1.end(); it++)
        {
            std::cout << it->first << "," << it->second << std::endl;
        }
        //3.反向迭代器遍历
        for (auto& x : map1)
        {
            //x.second = "oooo"; //传引用可以修改值,
            std::cout << x.first << "," << x.second << std::endl;
        }
    

    rbegin()rend()是反向迭代器,即rbegin() = end()rend() = begin()

    cbegin、cend,crbegin、crend都是const型的迭代器,它们不能修改容器的值

    const_iterator对象可以用于const型的容器或非const的容器,它自身的值可以改(可以指向其他元素),但不能改写其指向的元素值

    五、删除map元素

    • 删除一个节点:

    map1.erase(1);参数为key的值,如果key不存在即删除失败返回0,删除成功返回非0

    auto r = map1.erase(iterator)参数为一个指向map1的迭代器,返回值为删除节点的下一个节点的迭代器,因此参数不能为end()rbegin(),用erase()清空容器可以这样做:

    for(iter=myMap.begin(); iter!=myMap.end(); ) 
    {
        iter = myMap.erase(iter);
    }
    
    • 清空map:

    上面的方式虽然也可以清空容器,不过还有一种更简单的方式:

    map1.clear()

    示例代码:

    点击查看代码
    #include <iostream>
    #include <map>
    #include <utility>
    #include <string>
    
    int main()
    {
        //构造map,插入元素
        std::map<int, std::string> map1;
        map1.insert(std::pair<int, std::string>(1, "abc"));  //pair定义在 <utility>
        map1.insert(std::map<int, std::string>::value_type(2, "bcd"));
        map1.insert(std::make_pair(6, "sss"));
        map1.insert(std::map<int, std::string>::value_type(2, "bbb"));  //不会覆盖前面的(2,bcd),等于插入失败
        map1[5] = "def";
        map1[1] = "aaa";
        map1[5] = "ddd";//这种方式会覆盖前面的元素
        map1.emplace(3, "ggg");
        map1.emplace(3, "sss");  //不会覆盖(3,"ggg")
        std::map<int, std::string> map2{ {1,"abc"},{2,"bcd"} ,{5,"def"} ,{2,"xyz"} };  //和insert一样,键值相同不会覆盖,即key=2,对应的value是"bcd"
    
        //map的大小
        auto num = map1.size();
    
        //查找map键值并修改值value
        std::map<int, std::string>::iterator it = map1.find(2);  //搜索键值key,返回一个迭代器,返回end则没找到key
        it->second = "fff";
    
        decltype(it) it1 = map1.begin();
        auto x = it1->first;  // 返回key
        auto y = map1.at(1);  // 返回map.second,即返回键值为1对应的值  如果键值不匹配则会抛出异常,谨慎使用
        auto z = map1[111];   // 返回键为111对应的值,如果键111不存在,则会添加一个值为空,键为111的元素
    
        //遍历元素
        //1.数组方式遍历(存在局限性,键值要符合条件,比如连续)
        std::map<int, int> map3;
        for (int i = 0; i < 5; i++)
        {
            map3.emplace(i, i * 10);
        }
        for (int i = 0; i < map3.size(); i++)
        {
            std::cout << i << "," << map3[i] << std::endl;
        }
        //2.迭代器遍历
        for (auto it = map1.begin(); it != map1.end(); it++)
        {
            std::cout << it->first << "," << it->second << std::endl;
        }
        //3.反向迭代器遍历
        for (auto& x : map1)
        {
            //x.second = "oooo"; //传引用可以修改值,
            std::cout << x.first << "," << x.second << std::endl;
        }
    
        //删除元素
        it1 = map1.begin();
        auto r0 = map1.erase(it1);  //返回值为删除第一个元素后map1的第一个元素
        map1.clear(); //清空map1
    
        system("pause");
        return 0;
    }
    

    map常用操作函数(示例代码出现过的不再描述:

    函数 作用
    count() 返回指定元素出现的次数
    empty() 如果map为空则返回true
    equal_range() 返回特殊条目的迭代器对
    get_allocator() 返回map的配置器
    key_comp() 返回比较元素key的函数
    lower_bound() 返回键值 >= 给定元素的第一个位置
    max_size() 返回可以容纳的最大元素个数
    swap() 交换两个map
    upper_bound() 返回键值 > 给定元素的第一个位置
    value_comp() 返回比较元素value的函数
  • 相关阅读:
    冒泡排序
    python isinstance 函数
    2.x与3.x差异、条件语句、数据类型、其他
    区间结构
    配置文件监听器
    Enumerable扩展方法
    EsayUI + MVC + ADO.NET(项目架构)
    vue.js 官网及组件网站记录
    vue.js 二维码生成组件
    分享一些学习资料-大量PDF电子书
  • 原文地址:https://www.cnblogs.com/mmmmmmmmm/p/14043638.html
Copyright © 2011-2022 走看看