有关于STL中的哈希表一些基础知识
四种无序容器 | 存储元素 | key能否重复 | key能否修改 |
---|---|---|---|
unordered_map | NO | NO | |
unordered_multimap | YES | NO | |
unordered_set | NO | NO | |
unordered_multise | YES | NO |
哈希表是牺牲空间换取时间,通过使用额外的数组、set或是map来存放数据,才能实现快速的查找。
要寻找哈希表中的元素,只需要通过哈希函数对该元素关键字进行计算,就可以得出存储地址,也就是说元素的存储位置与它的关键码之间能够建立一种映射的关系
关键字的某个线性函数作为哈希地址
H a s h ( k e y ) = a × k e y + b Hash(key)=a×key+b Hash(key)=a×key+b
散列表的长度是 m , p m,p m,p是0~m中最大的质数
H a s h ( k e y ) = k e y ( m o d ) p Hash(key)=key (mod) p Hash(key)=key(mod)p
不同关键字通过相同哈希函数计算出相同的哈希地址,该种现象称为 哈希冲突 或 哈希碰撞,把具有不同关键码而具有相同哈希地址的数据元素称为 同义词。
从发生冲突的位置依次向后查找,直到找到一个空位置
从发生冲突的位置向后查找,每次往后移动 i^2 个位置,直到找到空位置,也就是每次往后移动的距离都会增大,不容易导致数据堆积
首先对关键字集合通过哈希函数计算出哈希地址,将有相同哈希地址的关键字放在同一个子集合,也就是一个哈希桶,在哈希桶内部关键字通过单链表连接,头结点放在哈希表中
所有元素全部产生冲突,最终都放到了同一个单链表中,此时该哈希表增删查改的效率就退化成 O ( N ) ,我们就可以用红黑树来作为哈希桶的数据结构。红黑树搜索时间复杂度是 O(logN)
但有些地方也会选择不把桶中的单链表结构换成红黑树结构,因为随着哈希表中数据的增多,该哈希表的负载因子也会逐渐增大,最终会触发哈希表的增容条件,此时该哈希表当中的数据会全部重新插入到另一个空间更大的哈希表,此时同一个桶当中冲突的数据个数也会减少,因此不做处理问题也不大。
参考:C++ STL unordered_map容器用法详解
template < class Key, //键值对中键的类型
class T, //键值对中值的类型
class Hash = hash<Key>, //容器内部存储键值对所用的哈希函数
class Pred = equal_to<Key>, //判断各个键值对键相同的规则
class Alloc = allocator< pair<const Key,T> > // 指定分配器对象的类型
template < class Key, //键(key)的类型
class T, //值(value)的类型
class Hash = hash<Key>, //底层存储键值对时采用的哈希函数
class Pred = equal_to<Key>, //判断各个键值对的键相等的规则
class Alloc = allocator< pair<const Key,T> > // 指定分配器对象的类型
> class unordered_multimap;
template < class Key, //容器中存储元素的类型
class Hash = hash<Key>, //确定元素存储位置所用的哈希函数
class Pred = equal_to<Key>, //判断各个元素是否相等所用的函数
class Alloc = allocator<Key> //指定分配器对象的类型
> class unordered_set;
template < class Key