写在之前
- 什么是函数?
- 在中学中,函数被定义为,已知一个数集A,通过特定对应法则,由数集A得到了数集B。我们可以这样理解数集A中的每一个数,经过特定处理,得到了数集B。
- 函数有三个组成部分,定义域A、值域B和对应法则。
哈希表
- 哈希表本质上是一个数组,数组的每个位置上储存着键值对(key : value),key是关键字,value是我们想要查找的值,把关键字输入哈希函数,可以得到储存着键值对的下标。
哈希函数
- 哈希函数也叫散列函数,哈希函数的定义域是所有key值,值域是下标。
- 哈希函数可以通过一定特定法则,把key值转换成下标。
为什么需要哈希函数
- 当我们想要根据key去找对应的value时,如果没有哈希函数,那么我们需要从头开始一个一个对比,一个一个确认,这样查找的时间复杂度就是O(n)。
哈希冲突
- 哈希冲突也叫哈希碰撞。
- 储存键值对的下标是通过关键字经过哈希函数计算出来的,那么如果两个不同的关键字,如:10234和10354经过哈希函数计算出来都是1,这样就出现了哈希冲突。
- 哈希冲突是会影响性能的,所以我们需要设计好哈希函数,减少哈希冲突。
如何解决哈希冲突
- 开放寻址法
开放寻址法是指,当出现哈希冲突时,把键值对储存在数组下一个位置。
如:10234经过哈希函数计算出下标是1,那么键值对1储存在数组下标为1的位置上,后面又遇到了10354经过哈希函数计算出下标是1,这时发现下标是1的位置已经被占据了,那么开放寻址法就会允许把这个键值对储存在下标为2的位置上(如果下标为2的位置也被占了,那么就继续往下面找。)
- 拉链法
拉链法是指,当遇到哈希冲突时,把后来的键值对放在链表中,先来的键值对所在的位置上多储存一个next指针,指向后来的键值对。
如:10234经过哈希函数计算出下标是1,那么键值对1首先储存在数组中了,之后又遇到了10354经过哈希函数计算出下标是1,那么这个时候,向数组下标是1的位置上放入一个指针next,指向关键字是10354的键值对(如果后面又有其他的键值对计算出下标是1,那么10354键值对多储存一个next指针,指向新来的键值对。)
哈希表读取数据
- 当我们需要读取关键字对应的value时,我们把key输入哈希函数,计算出下标,并把key与储存在下标位置的key对比,如果相同,那么读出value,如果不同,说明之前发生了哈希冲突,根据解决哈希冲突的不同方法找下一位对比并读取。
什么时候使用哈希表
- 当数据结构是键值对时,如leetcode 两数之和