ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

unordered_map使用详解

2022-02-04 20:34:22  阅读:197  来源: 互联网

标签:map const 详解 key type unordered first


STL:unordered_map使用笔记

参考网址:

1.概述

unordered_map的模板定义如下:

template < class Key,                                    // unordered_map::key_type
           class T,                                      // unordered_map::mapped_type
           class Hash = hash<Key>,                       // unordered_map::hasher
           class Pred = equal_to<Key>,                   // unordered_map::key_equal
           class Alloc = allocator< pair<const Key,T> >  // unordered_map::allocator_type
           > class unordered_map;

unordered_map是一种关联容器,存储基于键值和映射组成的元素,即key-value。允许基于键快速查找元素。在unordered_map中,键值唯一标识元素,映射的值是一个与该对象关联的内容的对象。

对于有序和无序性:

  • unordered_map的无序体现在内部存储结构为哈希表,以便通过键值快速访问元素。
  • 与之对应的有序的关联容器为map,map的有序体现在内部存储结构为红黑树,存储时元素自动按照从小到大的顺序排列。

而内部存储结构也决定了unordered_map和map在某些特性上的不同:

  • 查找的效率
    • unordered_map查找效率更高,可以达到O(1),但是对于元素子集的范围迭代效率较低。
    • 对于map,按照中序遍历的遍历次序,能够方便迭代得出从小到大的元素

无序映射实现了直接访问操作符(operator[]),该操作符允许使用其键值作为参数直接访问映射值。容器中的迭代器至少是前向迭代器forward iterators

2.属性

2.1 关联性

关联容器中的元素由他们的键引用,而不是由他们在容器中的绝对位置引用。

2.2 无序性

无序容器使用散列表来组织它们的元素,散列表允许通过它们的键快速访问元素。

2.3 Map映射

每个元素将一个键key与一个映射值value相关联:键意味着标识其主要内容是映射值的元素。

2.4 key的唯一性

在容器中没有两个元素有相同的key

2.5 Allocator-aware

容器使用一个分配器对象来动态地处理它的存储需求。

3.模板参数

template < class Key,                                    // unordered_map::key_type
           class T,                                      // unordered_map::mapped_type
           class Hash = hash<Key>,                       // unordered_map::hasher
           class Pred = equal_to<Key>,                   // unordered_map::key_equal
           class Alloc = allocator< pair<const Key,T> >  // unordered_map::allocator_type
           > class unordered_map;
  • key

    键值的类型。unordered_map中的每个元素都是由其键值唯一标识的。

  • T

    映射值的类型。unordered_map中的每个元素都用来存储一些数据作为其映射值。

  • Hash

    一种一元函数对象类型,它接受一个key类型的对象作为参数,并根据该对象返回size_t类型的唯一值。这可以是一个实现函数调用操作符的类,也可以是一个指向函数的指针(参见构造函数)。默认为hash<Key>

  • Pred

    接受两个键类型参数并返回bool类型的二进制谓词。表达式pred (a, b), pred是这种类型的一个对象,a和b是键值,返回true,如果是应考虑相当于b。这可以是一个类实现一个函数调用操作符或指向函数的指针(见构造函数为例)。这默认为equal_to<Key>,它返回与应用相等操作符(a==b)相同的结果。

  • Allloc

    用于定义存储分配模型的allocator对象的类型。默认情况下,使用allocator类模板,它定义了最简单的内存分配模型,并且与值无关。

4.成员函数

4.1 构造函数与初始化

(1)模板类的默认构造函数,创建空的unordered_map

unordered_map<int, string> umap;

(2)使用初始化列表初始化

unordered_map<int, string> umap = unordered_map<int, string>({{1,"a"},{2,"b"}});  // 显式调用C++的构造函数
unordered_map<int, string> umap2({{3,"c"},{4,"d"}});	// 隐式调用构造函数,更简洁
unordered_map<string, string> umap{
    {"淘宝","https://www.taobao.com/"},
    {"京东","https://www.jd.com/"},
    {"天猫商城","https://jx.tmall.com/"} };

(3)拷贝构造函数初始化

// 拷贝构造函数 
unordered_map<int, string> umap4(umap3);

(4)迭代器初始化

// range
unordered_map<int, string> umap5(umap1.begin(), umap1.end());

(5)拷贝初始化

typedef std::unordered_map<std::string,std::string> stringmap;
first = {{"AAPL","Apple"},{"MSFT","Microsoft"}};  // init list
second = {{"GOOG","Google"},{"ORCL","Oracle"}};   // init list
third = merge(first,second);                      // move
first = third;                                    // copy	

4.2 capacity

(1)是否为空

cout << "first " << (first.empty() ? "is empty" : "is not empty") << endl;
cout << "first " << (second.empty() ? "is empty" : "is not empty") << endl;

(2)目前容量

cout << "thrid.size is" << third.size() << endl;

4.3 迭代

/**  Iteration **/
for (auto it = first.begin(); it != first.end(); it++){
    cout << " " << it->first << ":" << it->second;
}
cout<<endl;

4.4 元素的访问

(1)operator[]

first["GOOG"] = "Google";		// new element inserted
first["AAPL"] = "Apple";		// new element inserted
first["MSFT"] = "Microsoft";	// new element inserted
first["BOB"] = "Bob";
string brand1 = first["GOOG"];	// read
first["BOB"] = "";				// writen
for (auto it = first.begin(); it != first.end(); it++){
    cout << " " << it->first << ":" << it->second;
}
cout<<endl;

(2)at

unrdered_map<string,int> mymap = {
    {"Mars", 3000},
    {"Saturn", 60000},
    {"Jupiter", 70000}};
mymap.at("Mars") = 3396;
mymap.at("Saturn") += 127;
mymap.at("Jupiter") = mymap.at("Saturn") + 9638;
	
for (auto& x: mymap) {
    std::cout << x.first << ": " << x.second << std::endl;
}

4.5 元素的查找

(1)find

find函数的原型如下:

iterator find ( const key_type& k );
const_iterator find ( const key_type& k ) const;

find函数可以用来获取元素的迭代器:

std::unordered_map<std::string,double> mymap1 = {
	    {"mom",5.4},
	    {"dad",6.1},
	    {"bro",5.9} };
	
string person = "dad";
unordered_map<std::string,double>::const_iterator got = mymap1.find(person);

if(got == mymap1.end()){
    cout << "not found" << endl;
}else{
    cout << got->first << " is " << got->second << endl; 
}

注意迭代器的声明方式:

unordered_map<string,double>::const_iterator

(2)count

成员函数count判断集合中有没有键值k,函数原型如下:

size_type count ( const key_type& k ) const;

其中size_type是一个整型变量,如果无序map中有key k,那么返回值为1,否则返回值为0。

4.6 修改

(1)元素的插入

  • operator[]

    使用操作符map_name [key_name] = value,实现对应key的value值的覆盖,若是key值是原来不存在的key,那么实现了新的元素的插入。

  • emplace()

    在unordered_map中插入一个新元素(如果其键是唯一的)。此新元素是使用 args 作为元素构造函数的参数来构造的。

    仅当容器中没有元素具有与要放置的元素等效的键(unordered_map中的键是唯一的)时才会进行插入。

    如果插入,这实际上会将容器大小增加一个。

    存在类似的成员函数 insert,它将现有对象复制或移动到容器中。

    // unordered_map::emplace
    #include <iostream>
    #include <string>
    #include <unordered_map>
    
    int main ()
    {
      std::unordered_map<std::string,std::string> mymap;
    
      mymap.emplace ("NCC-1701", "J.T. Kirk");
      mymap.emplace ("NCC-1701-D", "J.L. Picard");
      mymap.emplace ("NCC-74656", "K. Janeway");
    
      std::cout << "mymap contains:" << std::endl;
      for (auto& x: mymap)
        std::cout << x.first << ": " << x.second << std::endl;
    
      std::cout << std::endl;
      return 0;
    }
    
  • insert()

    insert的插入和emplace的插入类似,只有当键是唯一时,才能进行插入,同时size增加。

    insert的插入形式比emplace更加灵活:

    (1)	
    pair<iterator,bool> insert ( const value_type& val );
    (2)	
    template <class P>
        pair<iterator,bool> insert ( P&& val );
    (3)	
    iterator insert ( const_iterator hint, const value_type& val );
    (4)	
    template <class P>
        iterator insert ( const_iterator hint, P&& val );
    (5)	
    template <class InputIterator>
        void insert ( InputIterator first, InputIterator last );
    (6)	
    void insert ( initializer_list<value_type> il );
    
    /** 元素的插入 **/
    // insert
    unordered_map<string,double> myrecipe, mypantry = {{"milk",2.0},{"flour",1.5}};;					
    pair<string,double> myshopping ("baking powder",0.3);
    myrecipe.insert(myshopping);	// copy insertion
    myrecipe.insert(mypantry.begin(), mypantry.end());	// range inseration
    myrecipe.insert({{"sugar",0.8},{"salt",0.1},{"sugar",0.9}});		// initializer list inseration
    
    cout << "myrecipe contains:" << endl;
    for(auto& x:myrecipe){
        cout << x.first << ":" << x.second << " "; 
    }
    

    image-20220204200919401

(2)元素的删除

元素的删除使用erase()方法,删除的形式有多种:

by position (1)iterator erase ( const_iterator position );
by key (2)size_type erase ( const key_type& k );
range (3)iterator erase ( const_iterator first, const_iterator last );
//erase
std::unordered_map<std::string,std::string> mymap3;

// populating container:
mymap3["U.S."] = "Washington";
mymap3["U.K."] = "London";
mymap3["France"] = "Paris";
mymap3["Russia"] = "Moscow";
mymap3["China"] = "Beijing";
mymap3["Germany"] = "Berlin";
mymap3["Japan"] = "Tokyo";

cout << endl;
cout << "------------------------------------------" << endl;
// 根据位置,删除第一个:
mymap3.erase(mymap3.begin());
// 根据key
mymap3.erase("France");
// range
mymap3.erase(mymap3.find("Germany"), mymap3.end());

for (auto& x : mymap3) {
    cout << x.first << ":" << x.second << " ";
}

标签:map,const,详解,key,type,unordered,first
来源: https://blog.csdn.net/weixin_45745854/article/details/122785542

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有