一、哈希表
1.首先什么是哈希表?
哈希表,英文名叫作Hash table,国内有些书籍也翻译为散列表。哈希表是根据关键码的值而直接进行访问的数据结构。
通俗来说其实数组就是一张哈希表
那么哈希表能解决什么问题呢?
一般哈希表都是用来快速判断一个元素是否出现在集合里。
例如要查询一个名字是否在这所学校里。
要枚举的话时间复杂度是O(n),但如果使用哈希表的话,只需要O(1)就可以做到。
我们只需要初始化把这所学校里学生的名字都存在哈希表里,在查询的时候通过索引直接就可以知道这位同学在不在这所学校里了。
2.哈希函数
哈希函数,把学生的姓名直接映射为哈希表上的索引,然后就可以通过查询索引下标快速知道这位同学是否在这所学校里。
哈希表如下图所示,通过hashcode把名字转化为数值,一般hashcode是通过特定的编码方式,可以将其他数据格式转化为不同的数值,这样就把学生名字映射为哈希表上的索引数字。
由于数组大小固定,如果学生数量大于哈希表的大小,必然会造成几位学生的名字同时映射到哈希表同一个索引小标的位置。那么,就引入了哈希碰撞。
3.哈希碰撞
哈希碰撞,顾名思义,就是指两个名字同时映射到了哈希表的同一个下标。
解决方法:拉链法和线性探测法
1)拉链法
发生冲突的元素都被存储在链表中,这样就可以通过索引找到小李和小王了。
其实拉链法就是要选择适当的哈希表的大小,这样既不会因为数组空值而浪费大量内存,也不会因为链表太长而在查找上浪费太多时间。
2)线性探测法
使用线性探测法,一定要保证tablesize大于datasize。需要依靠哈希表中的空位来解决碰撞问题。
即在发生碰撞时,当前位置存放一个,在其余空位处存放一个。
4.常见的哈希结构
数组
set集合
map映射
当使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删的效率最优,如果需要集合有序的,那么就用set,如果要求不仅有序还要有重复数据的话,就用multiset。