C++ std::unordered_map 用法详解

1. std::unordered_map 的定义与特性

  • 所在头文件:

  • std::unorederd_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;
    
  • 关联性:std::unorederd_map 是一个关联容器,其中的元素根据键来引用,而不是根据索引来引用。

  • 无序性:在内部,std::unordered_map中的元素不会根据其键值或映射值按任何特定顺序排序,而是根据其哈希值组织到桶中,以允许通过键值直接快速访问各个元素(常量的平均时间复杂度)。

  • 唯一性:std::unorederd_map中的元素的键是唯一的。

  • 一些类型定义:

    类型成员 定义
    key_type 第一个模板参数(Key)
    mapped_type 第二个模板参数(T)
    value_type pair
    hasher 第三个模板参数(Hash)
    key_equal 第四个模板参数(Pred)

2. 构造 std::unordered_map

构造方式 函数声明
构造空的 unordered_map explicit unordered_map ( size_type n = /* see below */,
                                        const hasher& hf = hasher(),
                                        const key_equal& eql = key_equal(),
                                        const allocator_type& alloc = allocator_type() );
                       

explicit unordered_map ( const allocator_type& alloc );
由一对范围迭代器指定输入 template
unordered_map(InputIterator first, InputIterator last,
                           size_type n = /* see below */,
                           const hasher& hf = hasher(),
                           const key_equal& eql = key_equal(),
                           const allocator_type& alloc = allocator_type() );
复制构造 unordered_map ( const unordered_map& ump );
unordered_map ( const unordered_map& ump, const allocator_type& alloc );
移动构造 unordered_map ( unordered_map&& ump );
unordered_map ( unordered_map&& ump, const allocator_type& alloc );
利用初始化列表构造 unordered_map (initializer_list il,
                            size_type n = /* see below */,
                            const hasher& hf = hasher(),
                            const key_equal& eql = key_equal(),
                            const allocator_type& alloc = allocator_type() );

参数解释
n : 初始时,桶的最小数量,即最少有多少个桶。
hf :哈希函数对象。它是一个函数,根据传递给它的键计算并返回一个整数。
eql :比较函数对象。如果传递给它的两个参数相等,则返回true.

例子:

// constructing unordered_maps
#include 
#include 
#include 

typedef std::unordered_map<std::string,std::string> stringmap;

stringmap merge (stringmap a,stringmap b) {
  	stringmap temp(a); 
  	temp.insert(b.begin(),b.end()); 
  	return temp;
}

int main () {
	  stringmap first;                              // empty

	  // 一个元素为:{key, value}
	  stringmap second ( {{"apple","red"}, {"lemon","yellow"}} );       // init list
	  stringmap third ( {{"orange","orange"}, {"strawberry","red"}} );  // init list
	  stringmap fourth (second);                    // copy
	  stringmap fifth (merge(third,fourth));        // move
	  stringmap sixth (fifth.begin(),fifth.end());  // range
	
	  std::cout << "sixth contains:";
	  for (auto& x: sixth) 
	  		std::cout << " " << x.first << ":" << x.second;
	  std::cout << std::endl;
	
	  return 0;
}

3. 赋值操作

赋值方式 函数声明
复制 unordered_map& operator= ( const unordered_map& ump );
移动 unordered_map& operator= ( unordered_map&& ump );
初始化列表 unordered_map& operator= ( intitializer_list il );

例子:

// assignment operator with unordered_map
#include 
#include 
#include 

typedef std::unordered_map<std::string,std::string> stringmap;

stringmap merge (stringmap a,stringmap b) {
  	stringmap temp(a); 
  	temp.insert(b.begin(),b.end()); 
  	return temp;
}

int main () {
	  stringmap first, second, third;
	  
	  first = {{"AAPL","Apple"}, {"MSFT","Microsoft"}};  // init list
	  second = {{"GOOG","Google"}, {"ORCL","Oracle"}};   // init list
	  third = merge(first,second);                       // move
	  first = third;                                     // copy
	
	  std::cout << "first contains:";
	  for (auto& elem: first) 
	  		std::cout << " " << elem.first << ":" << elem.second;
	  std::cout << std::endl;
	
	  return 0;
}

4. 迭代器操作

4.1 指向整个容器中的元素

即,“第一个”指整个容器中的第一个,“尾后”指整个容器中的尾后。

函数声明 解释
iterator begin() noexcept;
const_iterator begin() const noexcept;
返回一个迭代器,指向第一个元素
iterator end() noexcept;
const_iterator end() const noexcept;
返回一个迭代器,指向尾后元素
const_iterator cbegin() const noexcept; 返回一个常量迭代器,指向第一个元素
const_iterator cend() const noexcept; 返回一个常量迭代器,指向尾后元素

4.2 指向某个桶中的元素

即,“第一个”指某个桶中的第一个,“尾后”指某个桶中的尾后。

函数声明 解释
local_iterator begin( size_type n );
const_local_iterator begin ( size_type n ) const;
返回一个迭代器,指向第n个桶内的第一个元素
local_iterator end(size_type n);
const_local_iterator end (size_type n) const;
返回一个迭代器,指向第n个桶内的尾后元素
const_local_iterator cbegin( size_type n ) const; 返回一个常量迭代器,指向第n个桶内的第一个元素
const_local_iterator cend( size_type n ) const; 返回一个常量迭代器,指向第n个桶内的尾后元素

例子:

// unordered_map::cbegin/cend example
#include 
#include 

int main () {
	  std::unordered_map<std::string,std::string> mymap;
	  mymap = {{"Australia","Canberra"},{"U.S.","Washington"},{"France","Paris"}};
	
	  std::cout << "mymap contains:";
	  for ( auto it = mymap.cbegin(); it != mymap.cend(); ++it )
	      std::cout << " " << it->first << ":" << it->second;  // cannot modify *it
	  std::cout << std::endl;
	
	  std::cout << "mymap's buckets contain:\n";
	  for ( unsigned i = 0; i < mymap.bucket_count(); ++i) {
	      std::cout << "bucket #" << i << " contains:";
	      for ( auto local_it = mymap.cbegin(i); local_it!= mymap.cend(i); ++local_it )
	          std::cout << " " << local_it->first << ":" << local_it->second;
	      std::cout << std::endl;
	  }
	
	  return 0;
}

结果:
mymap contains: France:Paris Australia:Canberra U.S.:Washington
mymap’s buckets contain:
bucket #0 contains:
bucket #1 contains:
bucket #2 contains:
bucket #3 contains:
bucket #4 contains:
bucket #5 contains: France:Paris
bucket #6 contains:
bucket #7 contains: Australia:Canberra
bucket #8 contains: U.S.:Washington
bucket #9 contains:
bucket #10 contains:


5. 容量操作

函数声明 解释
bool empty() const noexcept; unordered_map 是否为空
size_type size() const noexcept; 获取unordered_map 中元素的数量

6. 访问操作

访问方式 函数声明 解释
使用方括号([]) mapped_type& operator[] (const key_type& k);

mapped_type& operator[] (key_type&& k);
如果 k 匹配容器中某个元素的键,则该函数返回该映射值的引用。

如果 k 与容器中任何元素的键都不匹配,则该函数将使用该键插入一个新元素,并返回该映射值的引用。
使用 at() mapped_type& at (const key_type& k);

const mapped_type& at (const key_type& k) const;
如果 k 匹配容器中某个元素的键,则该函数返回该映射值的引用。

如果 k 与容器中任何元素的键都不匹配,则该函数将抛出 out_of_range 异常。

注意:const std::unordered_map 不能使用 operator[] 操作!!

例子:

// unordered_map::at
#include 
#include 
#include 

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

7. 插入操作

插入方式 函数声明 说明
插入单个元素 pair insert (const value_type& val);

template
pair insert (P&& val); // 类型P应当可以转换为 value_type类型
返回一个pair,其中第一个值为一个迭代器,指向新插入的元素或其键等于待插入元素的键的元素(原先就已存在的元素);第二个值是一个bool值,当插入一个新元素时,该值设为true,当该键已存在时,该值设为false
带插入位置提示 iterator insert (const_iterator position, const value_type& val);

template
iterator insert (const_iterator position, P&& val);
返回一个迭代器,该迭代器指向新插入的元素或指向键相等的已存在元素。
由一对范围迭代器指定输入 template
void insert (InputIterator first, InputIterator last);
使用初始化列表指定插入元素 void insert (initializer_list il);

例子:

// unordered_map::insert
#include 
#include 
#include 

int main () {
	  std::unordered_map<std::string,double>
	              myrecipe,
	              mypantry = {{"milk",2.0},{"flour",1.5}};
	
	  std::pair<std::string,double> myshopping ("baking powder",0.3);
	
	  myrecipe.insert (myshopping);                        // copy insertion
	  myrecipe.insert (std::make_pair<std::string,double>("eggs",6.0)); // move insertion
	  myrecipe.insert (mypantry.begin(), mypantry.end());  // range insertion
	  myrecipe.insert ( {{"sugar",0.8},{"salt",0.1}} );    // initializer list insertion
	
	  std::cout << "myrecipe contains:" << std::endl;
	  for (auto& x: myrecipe)
	      std::cout << x.first << ": " << x.second << std::endl;
	
	  std::cout << std::endl;
	  return 0;
}

8. 删除操作

删除方式 函数声明 说明
根据元素位置 iterator erase (const_iterator position); 返回一个迭代器,指向被删除元素的后一个元素
根据元素的键 size_type erase (const key_type& k); 返回被删除元素的数目,此处为1
由一对范围迭代器指定删除的范围 iterator erase (const_iterator first, const_iterator last); 返回一个迭代器,指向最后一个被删除元素的后一个元素
删除所有元素 void clear() noexcept;

例子:

// unordered_map::erase
#include 
#include 
#include 

int main () {
	  std::unordered_map<std::string,std::string> mymap;
	
	  // populating container:
	  mymap["U.S."] = "Washington";
	  mymap["U.K."] = "London";
	  mymap["France"] = "Paris";
	  mymap["Russia"] = "Moscow";
	  mymap["China"] = "Beijing";
	  mymap["Germany"] = "Berlin";
	  mymap["Japan"] = "Tokyo";
	
	  // erase examples:
	  mymap.erase ( mymap.begin() );      // erasing by iterator
	  mymap.erase ("France");             // erasing by key
	  mymap.erase ( mymap.find("China"), mymap.end() ); // erasing by range
	
	  // show content:
	  for ( auto& x: mymap )
	      std::cout << x.first << ": " << x.second << std::endl;
	
	  return 0;
}


9. 查找操作

函数声明 说明
iterator find (const key_type& k);

const_iterator find (const key_type& k) const;
在容器中搜索键值等于 k 的元素,如果找到,则返回一个指向该元素的迭代器,否则返回一个指向unordered_map :: end的迭代器。

例子:

// unordered_map::find
#include 
#include 
#include 

int main () {
	  std::unordered_map<std::string,double> mymap = {
	     {"mom",5.4},
	     {"dad",6.1},
	     {"bro",5.9} };
	
	  std::string input;
	  std::cout << "who? ";
	  getline (std::cin,input);
	
	  // 查找
	  std::unordered_map<std::string,double>::const_iterator got = mymap.find (input);
	
	  if ( got == mymap.end() )
	      std::cout << "not found";
	  else
	      std::cout << got->first << " is " << got->second;
	
	  std::cout << std::endl;
	
	  return 0;
}

10. 桶操作

函数声明 说明
size_type bucket_count() const noexcept; 获取容器中桶的数目
size_type bucket_size ( size_type n ) const; 获取第 n 个桶中元素的数量
size_type bucket ( const key_type& k ) const; 获取键为 k 的元素所在桶的序号

参考:http://www.cplusplus.com/reference/unordered_map/unordered_map/

你可能感兴趣的:(C++)