【1】c++ unordered_map详解

https://www.jianshu.com/p/56bb01df8ac7

unordered_map 使用

头文件:

#include <unordered_map>

取得键和值:

unordered_map<Key,T>::iterator it;
it->first;               // same as (*it).first   (the key value)
it->second;              // same as (*it).second  (the mapped value) 

成员函数:
===================迭代器====================
begin | 返回指向容器起始位置的迭代器(iterator)
end | 返回指向容器末尾位置的迭代器
cbegin | 返回指向容器起始位置的常迭代器(const_iterator)
cend | 返回指向容器末尾位置的常迭代器
===================Capacity===================
size 返回有效元素个数
max_size 返回 unordered_map 支持的最大元素个数
empty 判断是否为空
===================元素访问===================
operator[] 访问元素
at 访问元素(如 m.at(5) = 3.33)
===================元素修改===================
insert 插入元素
erase 删除元素
swap 交换内容
clear 清空内容
emplace 构造及插入一个元素
emplace_hint 按提示构造及插入一个元素
=====================操作=====================
find 通过给定主键查找元素
count 返回匹配给定主键的元素的个数
equal_range 返回值匹配给定搜索值的元素组成的范围
===================Buckets====================
bucket_count 返回槽(Bucket)数
max_bucket_count 返回最大槽数
bucket_size 返回槽大小
bucket 返回元素所在槽的序号
load_factor 返回载入因子,即一个元素槽(Bucket)的最大元素数
max_load_factor 返回或设置最大载入因子
rehash 设置槽数
reserve 请求改变容器容量

 

 

  • at(): This function in C++ unordered_map returns the reference to the value with the element as key k.
  • begin(): Returns an iterator pointing to the first element in the container in the unordered_map container
  • end(): Returns an iterator pointing to the position past the last element in the container in the unordered_map container
  • bucket(): Returns the bucket number where the element with the key k is located in the map.
  • bucket_count: bucket_count is used to count the total no. of buckets in the unordered_map. No parameter is required to pass into this function.
  • bucket_size: Returns number of elements in each bucket of the unordered_map.
  • count(): Count the number of elements present in an unordered_map with a given key.
  • equal_range: Return the bounds of a range that includes all the elements in the container with a key that compares equal to k.

 

--------------------------------------------------------------------------------------------------------------------------------

https://appdividend.com/2019/07/17/cpp-unordered_map-example-unordered_map-in-cpp-tutorial/

C++ Unordered_map Example

Unordered map containers are faster than typical map containers. The reason for this is attributed to the fact that the unordered map is implemented using hash tables. The key values of the map are linked to the hash values of the table, which are then organized into separate buckets. 

 

This way, once the hash values are calculated, the compiler can quickly access the exact bucket where the specified element is located.

#Syntax

unordered_map<key_datatype, mapped_datatype> map_name;

#Program to show the creation of Unordered map container

#include <iostream>
#include <iterator>
#include <unordered_map>
using namespace std;
int main()
{
    unordered_map<int, char> map1;
    unordered_map<int, char>::iterator cursor;
    map1[1] = 'a';
    map1[2] = 'b';
    cout << "KEY\tELEMENT" << endl;
    for (cursor = map1.begin(); cursor != map1.end(); cursor++)
    {
        cout << cursor->first;
        cout << '\t' << cursor->second << '\n'
             << endl;
    }
}

See the following output.

 

 

C++ Unordered_map Example

Comparison of Unordered maps :

#With usual map containers

In map containers, elements are placed in a proper order whereas in unordered maps the order is completely random. The reason for this is attributed to the fact that map containers are implemented using tree structure having specific traversal paths, but the unordered maps are done using the hash tables. But this makes the unordered maps quite faster accessible with time complexity of O(1), as compared to typical map containers having O(nlogn).

#With unordered sets

In unordered sets, the elements are not stored in key-value pairs but rather just in the form of keys which are used to judge the presence of elements in a set. But with unordered maps, we can have the frequencies of the presence of an element except for just its presence.

#Methods on Unordered maps

#begin():

The begin() function returns a bidirectional iterator that is pointing to the very first element of the map. This function demands no parameter to be passed and shows an error when it is done.

Syntax:

mapcontainer_name.begin();

See the following program.

#include <iostream>
#include <iterator>
#include <map>
using namespace std;
int main()
{
  map<int, char> map1;
  map<int, char>::iterator cursor;
  map1[1] = 'a';
  map1[2] = 'b';
  map1.begin();
}

(Returns an iterator pointing the first element of the map.)

#end()

The end() function is meant to return a bidirectional iterator that is pointing to the element next to the last element in the map container. Just like begin() function, this too doesn’t require any parameter. Also, since it is pointing to a non-valid element, it cannot be dereferenced.

 

#Syntax:

mapcontainer_name.end();

See the following program.

#include <iostream>
#include <iterator>
#include <map>
using namespace std;
int main()
{
  map<int, char> map1;
  map<int, char>::iterator cursor;
  map1[1] = 'a';
  map1[2] = 'b';
  map1.end();
}

(Returns an iterator pointing to next of the last element of the map.)

#at()

The at() function is used to access the mapped values in the unordered map container whose key values you know.

#Syntax:

mapcontainer_name.at(key_value);

See the following program.

#include <iostream>
#include <iterator>
#include <unordered_map>
using namespace std;
int main()
{
  unordered_map<int, char> map1;
  unordered_map<int, char>::iterator cursor;
  map1[1] = 'a';
  map1[2] = 'b';
  cout << map1.at(2) << endl;
}

See the following output.

 

Syntax

#bucket()

The bucket() function is used to get the bucket number, which holds the mapped value of the key-value you provide as a parameter.

#Syntax:

mapcontainer_name.bucket(key_value);

See the following program.

 

#include <iostream>
#include <iterator>
#include <unordered_map>
using namespace std;
int main()
{
  unordered_map<int, char> map1;
  unordered_map<int, char>::iterator cursor;
  map1[1] = 'a';
  map1[2] = 'b';
  cout << map1.bucket(2) << endl;
}

See the following output.

 

obucket

#bucket_count()

The bucket_count() function is used to get the total number of buckets in an unordered map container. This function doesn’t require any parameters.

#Syntax:

mapcontainer_name.bucket(key_value);

See the following program.

#include <iostream>
#include <iterator>
#include <unordered_map>
using namespace std;
int main()
{
  unordered_map<int, char> map1;
  unordered_map<int, char>::iterator cursor;
  map1[1] = 'a';
  map1[2] = 'b';
  cout << map1.bucket_count() << endl;
}

See the following output.

 

ibucket_count

#bucket_size()

The bucket_size() function is used to get the number of elements in a single bucket of the unordered map container.

#Syntax

mapcontainer_name.bucket_size(bucket_value);

See the following program.

#include <iostream>
#include <iterator>
#include <unordered_map>
using namespace std;
int main()
{
  unordered_map<int, char> map1;
  unordered_map<int, char>::iterator cursor;
  map1[1] = 'a';
  map1[2] = 'b';
  cout << map1.bucket_size(2) << endl;
}

See the following output.

 

obucket_size

#count()

The count() function is used to get several elements with the same key value in a container. But since a map container allows only one mapped value with a certain key value, this function only checks if a key is present or not.

#Syntax:

mapcontainer_name.count(key_value);

See the following program.

#include <iostream>
#include <iterator>
#include <unordered_map>
using namespace std;
int main()
{
  unordered_map<int, char> map1;
  unordered_map<int, char>::iterator cursor;
  map1[1] = 'a';
  map1[2] = 'b';
  cout << map1.count(1) << endl;
}

See the following output.

 

ocount

#equal_range()

The equal_range() function returns the initial and end iterators of the range K which contain all the elements whose key is equal to K. Now since in map containers there are no duplicate keys, the range contains at most one value.

Syntax:

mapcontainer_name.equal_range(key_value);

See the following program.

#include <iostream>
#include <iterator>
#include <unordered_map>
using namespace std;
int main()
{
    unordered_map<int, char> map1;
    unordered_map<int, char>::iterator cursor;
    map1[1] = 'a';
    map1[2] = 'b';
    auto len = map1.equal_range(1);
    for (auto m = len.first; m != len.second; m++)
    {
        cout << "Key : " << m->first << endl;
        cout << "Value : " << m->second << endl;
    }
}

See the following output.

 

oequal_range

Finally, C++ unordered_map Example Tutorial is over.

 

---------------------------------------------------------------------------------------------------------------------------

https://codeforces.com/blog/entry/21853

What is unordred_map?

It is a data structure like map but it is more than 4 times faster than map.you can use it in C++11 with including #include<unordered_map>.for example:

#include<unordered_map>
using namespace std;
int main(){
  unordered_map<int,int>mp;
  mp[5]=12;
  mp[4]=14;
  cout<<mp[5]<<' '<<mp[4]<<endl;//prints: 12 14
}

Lets explain it more.

How it works?

Focus on unordered_set for simplify.You can imagine that it has vector of vector like vector<vector<type> > mp. Every time you insert value V in that, it calculate its hash(I will explain how it works), let hash(V)=K; it inserts V into mp[K] (formally it calls mp[K].push_back(V)).When you call mp.count(V) it searchs for V in mp[K].

map VS unordered_map (and set VS unordered_set)

1-unordered_map is more than 4 times faster

Focus on problem 527E - Data Center Drama, it seems that it is good to use unordered_map instead of map.

My submission with map14269000 Time:484 MS.

My submission with unordered_map14269381 Time:358 MS.

Another good sample to show how fast is unordered_map is problem 178C3 - Smart Beaver and Resolving Collisions:

My submission with map15781810 Time limit exceeded on test 36 .

My submission with unordered_map15774685 Accepted (Time:966 MS).

2-unordered_set (and unordered_map) is not sorted

Please note that set (and map) is sorted, for example *(s.begin()) is always smallest number in the set; but in unordered_set it isn't. similarly there isn't lower_bound and upper_bound in unordered_set (and unordered_map similarly).

Creating hash function for structs

Now, one other problem remains, you can try to compile this code:

unordered_map<pair<int,int>,int>mp;

You will get Compilation Error! Why? See this page for unordered_map supported types. For unsupported types, you have to create your own hash function for use. For example lets see how we can create a hash function for pair<int,int>.

As you know any int value is between -2^31+1 to 2^31-1.so if we create function that for every pair<int,int> returns distinct value in type size_t(alias of unsigned int), it will be done. It is pretty easy: x.first^(x.second<<32) is good. but be careful about overflow ;for having good hash function we use hash<long long>.The code is looks like this:

struct HASH{
  size_t operator()(const pair<int,int>&x)const{
    return hash<long long>()(((long long)x.first)^(((long long)x.second)<<32));
  }
};
unordered_map<pair<int,int>,int,HASH>mp;

Now you have a unordered_map of pair<int,int> (it isn't problem what is second member, in example it was int).Creating hash function for other structs is same.

How to test unordered_map is faster than map?

You can test that for N=10^6, unordered_set(unordered_map) is more than 4 times faster than set(map) ;with this code:(compile code with command: g++ file.cpp -std=c++11 -O2)

#include <bits/stdc++.h>
using namespace std;
unordered_set<int>s;//replace it with set for test.
int main(){
  auto T=clock();
  s.reserve(32768); //updated !
  s.max_load_factor(0.25); //updated !
  for(int i=0;i<1000000;i++)
    s.insert(i);
  cout<<double(clock()-T)/CLOCKS_PER_SEC<<'\n';
}

Note1: Let your hash function H(V), it is better that H(V) returns distinct value for every distinct V, it makes unordered_map faster; but if you can't do that it doesn't problem. The only problem is that unordered_map becomes slower(however it is better than map).

Note2: Please be careful about your hash function time complexly! it is fun to use this hash function:

struct HASH{
  size_t operator()(const pair<int,int>&x)const{
    size_t ans=0;
    for(int i=0;i<x.first;i++)
      ans+=x.second;
    return ans;
  }
};

UPD I will explain hash<type> in my next post.

UPD It seems that sometimes unordered_map becames so slow.but it can improve with this two lines of code:

unordered_map<int,int>mp;
mp.reserve(1024);
mp.max_load_factor(0.25);

With this two lines unordered_map become about 10 times faster. You can replace 1024 with another suitable power of two.(it depends on number of insert s you will do).

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值