zoukankan      html  css  js  c++  java
  • map/unordered_map

    1. map

       1)map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对。它提供基于key的快速检索能力。

       2)map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。

       3)map的具体实现采用红黑树变体的平衡二叉树的数据结构。在插入操作和删除操作上比vector快。

       4)map可以直接存取key所对应的value,支持[]操作符,如map[key]=value。

       map对象的构造

    map<T1,T2> mapX;

       map的插入与迭代器

    map<int, string> mapStu;
    mapStu.insert(pair<int,string>(3,"Jack"));            // return pair<map<int, string>::iterator,bool>
    mapStu.inset(make_pair(0, "John"));                   // return pair<map<int, string>::iterator,bool>
    mapStu.insert(map<int,string>::value_type(1,"小李")); // return pair<map<int, string>::iterator,bool>
    void insert(InputIterator first, InputIterator last); // 插入一个范围
    
    mapStu[3] = "小明";          // 这种方法虽然非常直观,但存在一个性能的问题。插入3时,先在mapStu中查找主键为3的项,
                                 // 若没发现,则将一个键为3,值为初始化值的对组插入到mapStu中,然后再将值修改成"小明"。
                                 // 若发现已存在3这个键,则修改这个键对应的value
    string strName = mapStu[2];  // 只有当mapStu存在2这个键时才是正确的取操作,否则会自动插入一个实例,键为2,值为初始化值。
     
    map.begin();   // 返回容器中第一个数据的迭代器。
    map.end();     // 返回容器中最后一个数据之后的迭代器。
    map.rbegin();  // 返回容器中倒数第一个元素的迭代器。
    map.rend();    // 返回容器中倒数最后一个元素的后面的迭代器。
     
    // 迭代器遍历
    for (map<int,string>::iterator it=mapA.begin(); it!=mapA.end(); ++it)
    {
        pair<int, string> pr = *it;
        int iKey = pr.first;
        string sValue = pr.second;
    }

       map选择key排序方式

    map<T1,T2,less<T1> >  mapA;    // 该容器是按键的升序方式排列元素。未指定函数对象,默认采用less<T1>函数对象。
    map<T1,T2,greater<T1>> mapB;   // 该容器是按键的降序方式排列元素。
    // less<T1> 与 greater<T1> 可以替换成其它的函数对象functor。
    

       map对象的拷贝构造与赋值

    map(const map &mp);             // 拷贝构造函数
    map& operator=(const map &mp);  // 重载等号操作符
    map.swap(mp);                   // 交换两个容器集合
    

       map的大小

    map.size();   // 返回容器中元素的数目
    map.empty();  // 判断容器是否为空
    

       map的删除

    map.clear();                                                  // 删除所有元素
    iterator  erase(const_iterator position);                     // 删除pos迭代器所指的元素,返回下一个元素的迭代器
    size_type erase(const key_type& k);                           // 删除容器中key为k的pair
    iterator  erase(const_iterator first, const_iterator last);   // 除区间[beg,end)的所有元素,返回下一个元素的迭代器
    

       map的查找

    iterator find(const key_type& k);          // 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
    size_type count(const key_type& k) const;  // 返回容器中key为 k 的对组个数。对map来说,要么是0,要么是1
    iterator lower_bound(const key_type& k);   // 返回第一个 key>=k 元素的迭代器
    iterator upper_bound(const key_type& k);   // 返回第一个 key>k 元素的迭代器
    

    2. unordered_map

       它是一个关联容器,内部采用的是hash表结构,拥有快速检索的功能。每个key会通过一些特定的哈希运算映射到一个特定的位置,我们知道,

       hashtable是可能存在冲突的(多个key通过计算映射到同一个位置),在同一个位置的元素会按顺序链在后面。所以把这个位置称为一个bucket是

       十分形象的(像桶子一样,可以装多个元素)。

       

       所以 unordered_map 内部其实是由很多哈希桶组成的,每个哈希桶中可能没有元素,也可能有多个元素。每当桶不够用时,桶数会以

       大致 bucket[n] = 2 * bucket[n-1] + 奇数 (1, 3, 5, 9 ...)来增长。与 vector 成倍增长是不同的。

       这里我们将map和unordered_map做一个对比:

       1)map在缺省下,按照递增的排序顺序unordered_map不排序。

       2)Map中桶的元素初始化是链表保存的,其查找性能是O(n)。当链表长度很小的时候,即使遍历,速度也非常快,但是当链表长度不断

          变长,肯定会对查询性能有一定的影响,而树结构能将查找性能提升到O(log(n)),这时map内部存储结构由链表转成树。

          unordered_map内部实现是哈希表(数组),由链地址法解决冲突。

       3)map搜索时间复杂度为log(n)。unordered_map搜索时间复杂度,O(1)为平均时间,最坏情况下的时间复杂度为O(n)。

       4)map空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点,孩子节点以及红/黑性质,

          使得每一个节点都占用大量的空间。unordered_map建立哈希表比较耗费时间,但查找速度更快(受到冲突的影响)。

       unordered_map对象的构造

    unordered_map<T1,T2> mapX;
    

       unordered_map的插入与迭代器

    std::unordered_map<std::string, double> map1, map2 = { {"milk",2.0},{"flour",1.5} };
    std::pair<std::string, double> myshopping("baking powder",0.3);
    
    map1.insert(myshopping);                                      // copy insertion
    map1.insert(std::make_pair<std::string, double>("eggs",6.0)); // move insertion
    map1.insert(map2.begin(), map2.end());                        // range insertion
    map1.insert({ {"sugar",0.8}, {"salt",0.1} });                 // initializer list insertion
    
    umap.begin();   // 返回容器中第一个数据的迭代器。
    umap.end();     // 返回容器中最后一个数据之后的迭代器。
    
    for (auto& x: map1) {
        std::cout << x.first << ": " << x.second << std::endl;
    }
    

       自定义哈希函数

       使用自定义哈希函数可以有效避免构造数据产生的大量哈希冲突。要想使用自定义哈希函数,需要定义一个结构体,并在结构体中重载()运算符。

    // 通过 unordered_map<int, int, my_hash> my_map; 的定义方式将自定义的哈希函数传入容器了。
    struct my_hash 
    {
        static uint64_t splitmix64(uint64_t x) 
        {
            x += 0x9e3779b97f4a7c15;
            x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
            x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
            return x ^ (x >> 31);
        }
    
        size_t operator()(uint64_t x) const 
        {
            static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
            return splitmix64(x + FIXED_RANDOM);
        }
    };
    

       unordered_map对象的拷贝构造与赋值

    unordered_map(const unordered_map& ump);             // 拷贝构造函数
    unordered_map(unordered_map&& ump);                  // 移动构造函数
    unordered_map& operator=(const unordered_map& ump);  // 重载赋值运算符
    unordered_map& operator=(unordered_map&& ump);       // 移动赋值
    void swap(unordered_map& ump);                       // 交换两个容器集合
    

       unordered_map的大小

    umap.size();          // 返回容器中元素的数目
    umap.empty();         // 判断容器是否为空
    umap.bucket_count();  // 返回容器中桶的数目
    umap.bucket_size(n);  // 返回第n个桶中元素个数 
    

       unordered_map的删除

    umap.clear();                                                 // 删除所有元素
    iterator  erase(const_iterator position);                     // 删除pos迭代器所指的元素,返回下一个元素的迭代器
    size_type erase(const key_type& k);                           // 删除容器中key为k的pair
    iterator  erase(const_iterator first, const_iterator last);   // 除区间[beg,end)的所有元素,返回下一个元素的迭代器
    

       unordered_map的查找

    iterator find(const key_type& k);          // 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回umap.end();
    size_type count(const key_type& k) const;  // 返回容器中key为 k 的对组个数。对umap来说,要么是0,要么是1
    

      

  • 相关阅读:
    软件开发平台正在面临一次重大的升级,java, net比起来简直弱爆了,新型的Html5+JS+JSON开发平台正在形成 人工智能
    Qt编写地图综合应用48地球模式、三维模式、地铁模式
    Qt数据库应用1数据导入导出csv
    Qt编写地图综合应用50获取区域边界
    Qt编写地图综合应用49地图类型(街道图、卫星图)
    Qt数据库应用2数据导出到xls
    Qt编写地图综合应用47经纬度地址互相转换
    C# 线程手册 第七章 网络和线程 系列
    SQL Server Transaction Log Truncate && Shrink
    a href=#与 a href=javascript:void(0) 的区别 打开新窗口链接的几种办法
  • 原文地址:https://www.cnblogs.com/yanghh/p/13036091.html
Copyright © 2011-2022 走看看