哈希表理论基础
哈希表就是利用一个hash函数,将元素的值value映射到一个索引范围内。比如通过取模运算将任意整数 X 映射到 [0, TableSize - 1],那么 TableSize 是哈希表的大小,索引范围就是 [0, TableSize - 1]。
根据元素的值就能实现常数级的查找。
主要用于需要判断一个元素是否存在一个集合中。
哈希函数的问题是:如果元素的取值空间远大于索引的取值空间,那么有可能会导致不同的元素被映射到相同的位置,也就是发生了碰撞。对于碰撞的处理有以下几种处理方式:线性探测、二次探测、开链等。
常用的哈希结构:
在C++的STL中提供基于不同底层数据结构的set和map,详细内容可见个人博客:https://guomw.net/
对于set来说,底层实现和优劣对比如下:(此处省略了unordered_multiset)
集合 |
底层实现 |
是否有序 |
数值是否可以重复 |
能否更改数值 |
查询效率 |
增删效率 |
std::set |
红黑树 |
有序 |
否 |
否 |
O(log n) |
O(log n) |
std::multiset |
红黑树 |
有序 |
是 |
否 |
O(logn) |
O(logn) |
std::unordered_set |
哈希表 |
无序 |
否 |
否 |
O(1) |
O(1) |
底层数据结构是红黑树的set,由于红黑树是一种平衡二叉树,是根据key值进行排序,所以key值不能修改。只能删除和增加。
对于map来说,底层实现和优劣对比如下:
映射 |
底层实现 |
是否有序 |
数值是否可以重复 |
能否更改数值 |
查询效率 |
增删效率 |
std::map |
红黑树 |
key有序 |
key不可重复 |
key不可修改 |
O(logn) |
O(logn) |
std::multimap |
红黑树 |
key有序 |
key可重复 |
key不可修改 |
O(log n) |
O(log n) |
std::unordered_map |
哈希表 |
key无序 |
key不可重复 |
key不可修改 |
O(1) |
O(1) |
综上,如果想要使用哈希表解决哈希问题,优先使用底层实现为hash table的unordered_set和unordered_map。
哈希表是使用空间换取时间的数据结构,set的元素是一个值,map个每个元素是键值对。