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> ,insert和emplace插入时不会覆盖原有的键值相同的元素,所以如果插入的元素键值原来已经有了,就会插入失败,返回值的第二个值就为false,相反成功则为true

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的函数
posted @ 2020-11-26 17:54  滴哒哒哒  阅读(145)  评论(0编辑  收藏  举报