我们来学习最重要的数据结构之一:散列表或哈希表。
基本介绍
那么什么是哈希表呢?哈希表怎么做到 O(1) 时间复杂度找到某个元素的呢?
概念:哈希表是根据键值(key value)而直接进行访问的数据结构。它通过把键值映射到一个位置来访问记录,以加快查找的速度。
具体映射过程是:把 Key 通过一个映射函数转换成一个整型数字,然后将该整型数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该取余数字为下标的数组空间里。
这个映射函数称为哈希函数,映射过程称为哈希化,存放记录的数组叫做哈希表。
查询
查询:数组的特点是寻址容易,插入和删除困难;而链表的特点是寻址困难,插入和删除容易;
哈希表则实现了寻址容易,插入删除也容易。
当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value。哈希表是一个在时间和空间上做出权衡的数据结构。
如果没有内存限制,那么可以直接将键作为数组的索引。那么所有的查找时间复杂度为O(1);
如果没有时间限制,那么可以使用无序数组并进行顺序查找,这样只需要很少的内存。
哈希冲突以及解决
哈希映射对不同的键,可能得到同一个散列地址,即同一个数组下标,这种现象称为冲突。
1.拉链法:通过哈希函数,我们可以将键转换为数组的索引(0~M-1),但是对于两个或者多个键具有相同索引值的情况,我们需要有一种方法来处理这种冲突。一种比较直接的办法就是,将大小为M 的数组的每一个元素指向一个条链表,链表中的每一个节点都存储散列值为该索引的键值对,这就是拉链法。
2.线性探测法:基本原理为,使用大小为M的数组来保存N个键值对,其中M>N,我们需要使用数组中的空位解决碰撞冲突。当碰撞发生时即一个键的散列值被另外一个键占用时,直接检查散列表中的下一个位置即将索引值加1,这样的线性探测会出现三种结果:
1)命中,该位置的键和被查找的键相同;
2)未命中,键为空;
3)继续查找,该位置和键被查找的键不同。
举例
明天再来搞代码实现吧,今天就粗略讲解一下哈哈
每日一句
Great minds have purpose, others have wishes.(杰出的人有着目标,其他人只有愿望)