unordered_map&&unordered_set

unordered_map&&unordered_set

底层实现

​ 在STL中,C++11引入了unordered_map、unordered_set、unordered_multimap、unordered_multimap。尽管不是名字不是哈希表,但是底层仍然是。相比于map等,这个查找的平均时间更加快。看看它的底层实现(l来自《STL源码剖析》):

//以下是基于gnu2.9版本的提取的
template<class Value, class Key, class HashFcn, 
		 class ExtractKey, class EqualKey, 
		 class Alloc=alloc>
class hashtable{
    public:
    	typedef HashFcn hasher;
    	typedef EqualKey Key_equal;
    	typedef size_t size_type;
   private:
    	hasher hash;//哈希函数(可以是函数指针或函数对象(仿函数),返回值需要是bool值)
    	key_equal equals;//key的判断相等函数(可以是函数指针或函数对象(仿函数)返回值需要是bool值)
    	ExtractKey get_key;//key的提取函数,从value_type中提取出key
    	
    	typedef _hashtable_node<Value> node;
    
    	vector<node*,Alloc> buckets;//存储桶,可见后面的图示
    	size_type num_elements;//存储桶的数量
    public:
    	size_type bucket_count() const { return buckets.size()}
    ……
};
template<class Value>
struct _hashtable_node{
    _hashtable_node* next;
    Value val;
};
//hashtable的迭代器设计
template<class Value, class Key, class HashFcn, 
		 class ExtractKey, class EqualKey, 
		 class Alloc>
struct _hashtable_iterator{
    ……
    node* cur;
    hashtable* ht;
};      


//GNU 7.2.0 中重新分解了各种容器的实现细节。此处贴出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;
//7.2.0版本已经有默认的hash函数(根据key类型选择的hash函数),只需要定义key与value类型即可。

内存结构:类似deque的分段存储。采用链地址法解决冲突。

在这里插入图片描述

构造、析构、赋值

构造

h 函数原型(C++14)
empty(1) unordered_map();
//这里的n是什么意思?指定的是数据桶的数量
explicit unordered_map ( size_type n,
const hasher& hf = hasher(),
const key_equal& eql = key_equal(),
const allocator_type& alloc = allocator_type() );
explicit unordered_map ( const allocator_type& alloc );
unordered_map ( size_type n, const allocator_type& alloc );
unordered_map ( size_type n, const hasher& hf, const allocator_type& alloc );
range (2) template< class InputIterator>
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() );
template< class InputIterator>
unordered_map ( InputIterator first, InputIterator last,
size_type n, const allocator_type& alloc );
template< class InputIterator>
unordered_map ( InputIterator first, InputIterator last,
size_type n, const hasher& hf, const allocator_type& alloc );
copy (3) unordered_map ( const unordered_map& ump );
unordered_map ( const unordered_map& ump, const allocator_type& alloc );
move (4) unordered_map ( unordered_map&& ump );
unordered_map ( unordered_map&& ump, const allocator_type& alloc );
initializerlist(5) 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() );
unordered_map ( initializer_list il,
size_type n, const allocator_type& alloc );
unordered_map ( initializer_list il,
size_type n, const hasher& hf, const allocator_type& alloc );

上述的size_type n;均是指定指数据桶的数量。初始化一个哈希表的时候注意以下数据桶的数量,数据多,而数据桶少,就会使得查找效率更低。

析构

~unordered_map();

赋值

函数类型 函数原型
copy (1) unordered_map& operator= ( const unordered_map& ump );
move (2) unordered_map& operator= ( unordered_map&& ump );
initializer list (3) unordered_map& operator= ( intitializer_list il );

迭代器与容器大小

Iterators 函数说明及其函数原型
begin
cbegin
returns an iterator to the beginning (public member function)
iterator begin(); (since C++11)
const_iterator begin() const; (since C++11)
const_iterator cbegin() const; (since C++11)
end
cend
returns an iterator to the end (public member function)
iterator end(); (since C++11)
const_iterator end() const; (since C++11)
const_iterator cend() const; (since C++11)

​ 通过迭代器访问的是值类型。注意unordered_map的值类型是pair<Key,Value>。而unordered_set的值类型就是Key。另外,unordered_map是forward_iterator_tag。单链表类似的访问方式。

Capacity 函数说明及其函数原型
empty checks whether the container is empty (public member function)
bool empty() const; (since C++11)
size returns the number of elements (public member function)
size_type size() const; (since C++11)
max_size returns the maximum possible number of elements (public member function)
size_type max_size() const; (since C++11)

修改

各个操作无论是传入参数,还是返回值与map类似。

Modifiers 函数说明及其函数原型
clear clears the contents (public member function)
void clear(); (since C++11)
insert inserts elements or nodes (since C++17) (public member function)
1-2返回的是,插入成功,返回插入元素的迭代器,以及true。若已有key,插入失败,返回的是已有元素的迭代器,以及false。
(1) pair<iterator,bool> insert ( const value_type& val );
(2) template < class P>
pair<iterator,bool> insert ( P&& val );
3-4返回的是,插入成功,返回插入元素的迭代器。若已有key,插入失败,返回的是已有元素的迭代器。
(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_or_assign(C++17) inserts an element or assigns to the current element if the key already exists (public member function),插入后会改变value值(即使有相同key元素)
emplace constructs element in-place (public member function)即便有相同key的元素,也会构造新元素。
template <class… Args>
pair<iterator, bool> emplace ( Args&&… args );
emplace_hint constructs elements in-place using a hint (public member function),在指引迭代器附近插入。可以提高插入效率。
template <class… Args>
iterator emplace_hint ( const_iterator position, Args&&… args );
try_emplace (C++17) inserts in-place if the key does not exist, does nothing if the key exists (public member function)如果有相同key元素,不做任何事。
template <class… Args>
pair<iterator, bool> try_emplace(const key_type& k, Args&&… args);
(1) (since C++17)
template <class… Args>
pair<iterator, bool> try_emplace(key_type&& k, Args&&… args);
(2) (since C++17)
template <class… Args>
iterator try_emplace(const_iterator hint, const key_type& k, Args&&… args);
(3) (since C++17)
template <class… Args>
iterator try_emplace(const_iterator hint, key_type&& k, Args&&… args);
(4) (since C++17)
erase erases elements (public member function)三种方式删除元素
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 );
swap swaps the contents (public member function),交换指针一些东西,效率挺高
void swap ( unordered_map& ump );
extract (C++17) extracts nodes from the container (public member function)
node_type extract( const_iterator position ); (1) (since C++17)
node_type extract( const key_type& x ); (2) (since C++17)
merge (C++17) splices nodes from another container (public member function)
template<class H2, class P2>
void merge(std::unordered_map<Key, T, H2, P2, Allocator>& source);
template<class H2, class P2>
void merge(std::unordered_map<Key, T, H2, P2, Allocator>&& source);

notes:

对于unorder_map,每个数据桶只能装一个元素。

对于extract:(唯一一种改变元素key值而不需要重新申请内存分配的,要使用move)

extract is the only way to change a key of a map element without reallocation。

merge:从source中提取不同key的元素(是对于* this的hash函数以及key相等函数的意义上的key不同)。* this与source要求分配器类型是一致的。

另外,无论是insert,emplace等,他们如果增加了元素。会在当前size()>最大装载因子*数据桶数量的时候进行rehash。rehash的意思是:增大数据桶的数量。装载因子等于

查询

在unordered_multimap中无at,operator[ ]。

Lookup
at access specified element with bounds checking (public member function)注意返回的是mapped_type。
mapped_type& at ( const key_type& k );
const mapped_type& at ( const key_type& k ) const;
operator[ ] access specified element (public member function)
mapped_type& operator[] ( const key_type& k );
mapped_type& operator[] ( key_type&& k );
count returns the number of elements matching specific key (public member function),返回特定key的元素数量
size_type count ( const key_type& k ) const;
find finds element with specific key (public member function),两种寻找方式,通过迭代器或通过key寻找元素
iterator find( const Key& key ); (1)
const_iterator find( const Key& key ) const; (2)
equal_range returns range of elements matching a specific key (public member function)左闭右开区间,包含所有特定的key。
std::pair<iterator,iterator> equal_range( const Key& key ); (since C++11)
std::pair<const_iterator,const_iterator> equal_range( const Key& key ) const;
(since C++11)

数据桶信息

数据通接口 函数原型及其说明
begin(int)
cbegin(int)
returns an iterator to the beginning of the specified bucket (public member function)返回指定数据桶的第一个元素的迭代器
local_iterator begin( size_type n );
(since C++11)
const_local_iterator begin( size_type n ) const;
(since C++11)
const_local_iterator cbegin( size_type n ) const;
end(int)
cend(int)
returns an iterator to the end of the specified bucket (public member function)
local_iterator end( size_type n );
(since C++11)
const_local_iterator end( size_type n ) const;
(since C++11)
const_local_iterator cend( size_type n ) const;
(since C++11)
bucket_count returns the number of buckets,返回桶的数量 (public member function)
size_type bucket_count() const;
(since C++11)
max_bucket_count returns the maximum number of buckets ,返回桶的最大数量(public member function)
size_type max_bucket_count() const;
(since C++11)
bucket_size returns the number of elements in specific bucket,返回特定桶中的元素数量 (public member function)
size_type bucket_size( size_type n ) const;
(since C++11)
bucket returns the bucket for specific key, 返回key对应的桶编号(public member function)
size_type bucket( const Key& key ) const;
(since C++11)

哈希策略

Hash policy
load_factor returns average number of elements per bucket (public member function),装载因子就是元素个数除以数据桶个数
float load_factor() const;
(since C++11)
max_load_factor manages maximum average number of elements per bucket (public member function),如果超过这个装载因子就会重新设置桶的数量。默认最大装载因子为1,可以自己设置。
float max_load_factor() const;
(1) (since C++11)
void max_load_factor( float ml );
(2) (since C++11)
rehash reserves at least the specified number of buckets. This regenerates the hash table. (public member function),如果设置的桶数量,超过最大装载因子不会重新hash。
void rehash( size_type count );
(since C++11)
reserve reserves space for at least the specified number of elements. This regenerates the hash table.由元素数量申请空间(就是hash表的空间) (public member function)
void reserve( size_type count );
(since C++11)

一些仿函数

Observers
hash_function returns function used to hash the keys (public member function)
hasher hash_function() const;
(since C++11)
key_eq returns the function used to compare keys for equality (public member function)
key_equal key_eq() const;
(since C++11)

与unordered_set等的关系

​ 就像map与set一样,unordered_map与unordered_set之间最要注意的区别就是值类型不一致,一个是pair<key,map_type>,另外一个key类型就是值类型。而unordered_map与unordered_multimap,unordered_map要求相同的key的元素只有一个,而unordered_multimap,就可以有多个相同的key元素。

Reference

[1] https://www.bilibili.com/video/av45108908

[2]http://www.cplusplus.com/reference/unordered_map/

[3]候捷,《STL源码剖析》

Java企业场景下的实战入门课(Spring Boot+Redis)

04-20
<p> 企业场景下的Java实战课程!  </p> <p> 【超实用课程内容】 本课程主要是从最基础的技术要点一步一个脚印的介绍Spring Boot2.0相关的核心技术栈和缓存中间件Redis常见且典型的数据结构、相关的核心技术栈及典型的应用场景的实战。并附带业务场景实战用户注册和点赞系统中点赞功能模块的设计与实现为各位小伙伴提供企业级项目开发中常见且典型的Java核心技术,可以说是拒绝纸上谈兵、注重实战并学以致用!  </p> <p> <br> </p> <p> 套餐中一共包含2门实战入门课程(共82讲)  </p> <p> 课程1:《Java实战之Spring Boot入门到精通》  </p> <p> 课程2:《Java实战之Redis入门到精通》  </p> <p> <br> </p> <p> 【基础要求】  </p> <p> 1、基本要求:具备一定的JavaSE以及Java Web项目的开发基础、了解spring boot更佳  </p> <p> 2、工具要求:会使用Intellij IDEA、Navicat以及Postman  </p> <p> <br> </p> <p> 【你能收获到什么?】  </p> <p> 1、帮助学员了解并掌握springboot和缓存中间件Redis的方方面面、包括其典型及常用的数据结构及其在实际项目开发中典型的应用场景!  </p> <p> 2、掌握如何基于Spring Boot搭建企业级项目,整合加入中间件Redis相关的依赖配置,并以此为扩展,为后续学习其他中间件做铺垫;可以提升学员Java中间件的实战能力。  </p> <p> 3、帮助学员了解并掌握缓存中间件Redis在实际应用中有哪些常见、典型的应用场景,如对象信息存储、列表存储、队列特性分发消息、试题库随机获取、排行榜等等,这对于学员在平时项目开发、跳槽面试等情况下将有很大的帮助  </p> <p> 4、本课程介绍的基于Redis相关数据结构的特性独立设计并实战项目中典型功能模块,如会员到期自动提醒、点赞功能模块等内容,将有助于学员将所学的技术栈真正应用到实际中、提升自身的数据库设计能力、业务理解能力、代码实战能力以及性能优化方面的能力  </p> <p> <br> </p> <p> 【课程如何观看?】  </p> <p> 1、登录CSDN学院 APP 在我的课程中进行学习;  </p> <p> 2、移动端:CSDN 学院APP(注意不是CSDN APP哦) 本课程为录播课,课程2年有效观看时长 【资料开放】 课件、课程案例代码完全开放给你,你可以根据所学知识,自行修改、优化 下载方式:电脑登录课程观看页面,点击右下方课程资料、代码、课件等打包下载 </p> <p> <img src="https://img-bss.csdn.net/202004200821078434.png" alt=""> </p>
©️2020 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值