数据结构中由数组和链表来实现对数据的存储,他们各有特点。
(1) 数组:占用空间连续。 寻址容易,查询速度快。但是,增加和删除效率非常低。
(2) 链表:占用空间不连续。 寻址困难,查询速度慢。但是,增加和删除效率非常高。
那么,我们能不能结合数组和链表的优点(即查询快,增删效率也高)呢? 答案就是“哈希表”。 哈希表的本质就是“数组+链表”。
什么是哈希表(Hash Table)
哈希表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值。
试想一下,在程序当中,我们可能会经常碰到需要“查表”的时候,就是用某种形式的关键字(key),去查询标识对应的相关信息(value):例如统计一段文字的单词频率: 那你就得建立一个从每个单词到出现次数的对应关系,扫描文字的时候看到哪个词就把它的频次+1。这样的“关键字查询”需求在程序设计的过程中无处不在,所以我们需要一个高效的机制,来存储key和value的对应关系。
哈希函数
哈希表在记录的存储位置和对应的关键字之间建立一个确定的对应关系f,使得每一个关键字key对应于一个存储位置f(key)。在查找的时候,根据这一确定的对应关系,就可以找到给定关键字key所对应的映射f(key),如果在查找的集合当中有这个记录,那么就会根据这个key查找到f(key)的位置。
这个对应关系就是哈希函数,说白了,hash函数就是根据key计算出应该存储地址的位置,而哈希表是基于哈希函数建立的一种查找表。
哈希表的查找步骤
整个哈希过程就是两步:
第一步:在存储时,通过哈希函数计算出记录的存储地址,并按照这个地址存储这个记录,不管是什么记录,都要通过一个韩系函数计算出存储地址之后再进行存储。
第二步:在查找记录的时候,通过同样的哈希函数计算记录的存储地址,按照这个地址访问该条记录。说起来简单,在哪里存的,上哪里去找,由于存取用的是同一个哈希函数,因此结果肯定相同。
所以说哈希技术即使一种存储的方法,也是一种查找的方法。韩系几束的数据记录之间不存在什么逻辑关系,它只与关键字相关联。因此哈希结构是面向查找的存储结构。
哈希表的适用条件
哈希表适用于那种查找性能要求高,数据元素之间无逻辑关系要求的情况。对于那些同样的关键字,它能对应很多记录的情况,却不适合用散列技术。比如一个班级有很多学生,如果要使用性别关键字来查找的话,会对应很多学生的记录,这显然是不合适的。只有对于那个每条信息中具有唯一性的属性彩饰盒作为关键字,例如学号。
同样散列表也不适合范围查找,比如查找年纪在18-20之间的学生,是没有办法实现的。想获得表中记录的排序也是不可能,最大值和最小值也无法得到。
哈希函数的构造方法
1.直接定址法
哈希函数为关键字的线性函数如 f(key)=a*key+b
这种构造方法比较简便,均匀,但是有很大限制,仅限于地址大小=关键字集合的情况
这样的哈希函数优点是简单,均匀,也不会产生冲突,但问题是这需要实现知道关键字的分布情况