散列表 又叫 哈希表 (hash table)。经过访问key而直接访问存储的value值。它的key - value之间存在一个映射函数,咱们能够经过key值和“看不到”的映射函数(散列函数)访问对应的value值。这加快了查找的速度!存放记录的数组称作散列表。散列方法不一样于顺序查找、二分查找、二叉排序树及B-树上的查找。它不以关键字的比较为基本操做,采用直接寻址技术 (就是说,它是直接经过key映射[映射函数,实现的方式有多种] 到内存地址上去的)。在理想状况下,无须任何比较就能够找到待查关键字,查找的指望时间为O(1)(面试的时候犯了这个错误)。php
举个形象的例子来讲:为了查找电话簿中某人的号码,能够建立一个按照人名首字母顺序排列的表(即创建人名到首字母
的一个函数关系),在首字母为W的表中查找“王”姓的电话号码,显然比直接查找就要快得多。这里使用人名做为关键字,“取首字母”是这个例子中散列函数的函数法则
,存放首字母的表对应散列表。关键字和函数法则理论上能够任意肯定。[维基百科]面试
散列表
设全部可能出现的关键字集合记为U(简称全集)。实际发生(即实际存储)的关键字集合记为K(|K|比|U|小得多)。
散列方法是使用函数h将U映射到表T[0..m-1]的下标上(m=O(|U|))。这样以U中关键字为自变量,以h为函数的运算结果就是相应结点的存储地址。从而达到在O(1)时间内就可完成查找。
其中:
① h:U→{0,1,2,…,m-1} ,一般称h为散列函数(Hash Function)。散列函数h的做用是压缩待处理的下标范围,使待处理的|U|个值减小到m个值,从而下降空间开销。
② T为散列表(Hash Table)。
③ h(Ki)(Ki∈U)是关键字为Ki结点存储地址(亦称散列值或散列地址)。
④ 将结点按其关键字的散列地址存储到散列表中的过程称为散列(Hashing)数组
咱们基本知道了value和key之间存在一个映射关系h,简单的表示为 value = h(key)。 咱们会有疑问,函数以容许多对一出现的,也就是说,当多个key对应一个value时怎么办?安全
这就是散列表中的冲突。分布式
散列表的冲突现象
(1)冲突
两个不一样的关键字,因为散列函数值相同,于是被映射到同一表位置上。该现象称为冲突(Collision)或碰撞。发生冲突的两个关键字称为该散列函数的同义词(Synonym)。
【例】上图中的k2≠k5,但h(k2)=h(k5),故k2和K5所在的结点的存储地址相同。
(2)安全避免冲突的条件
最理想的解决冲突的方法是安全避免冲突。要作到这一点必须知足两个条件:
①其一是|U|≤m
②其二是选择合适的散列函数。
这只适用于|U|较小,且关键字均事先已知的状况,此时通过精心设计散列函数h有可能彻底避免冲突。
(3)冲突不可能彻底避免
一般状况下,h是一个压缩映像。虽然|K|≤m,但|U|>m,故不管怎样设计h,也不可能彻底避免冲突。所以,只能在设计h时尽量使冲突最少。同时还须要肯定解决冲突的方法,使发生冲突的同义词可以存储到表中。
函数
构造散列函数spa
(直接复制的维基百科,详细可参见[1]) 散列函数能使对一个数据序列的访问过程更加迅速有效,经过散列函数,数据元素将被更快定位。设计
散列表的查找过程基本上和造表过程相同。一些关键码可经过散列函数转换的地址直接找到,另外一些关键码在散列函数获得的地址上产生了冲突,须要按处理冲突的方法进行查找。在介绍的三种处理冲突的方法中,产生冲突后的查找仍然是给定值与关键码进行比较的过程。因此,对散列表查找效率的量度,依然用平均查找长度来衡量。xml
查找过程当中,关键码的比较次数,取决于产生冲突的多少,产生的冲突少,查找效率就高,产生的冲突多,查找效率就低。所以,影响产生冲突多少的因素,也就是影响查找效率的因素。影响产生冲突多少有如下三个因素:blog
参考:【1】维基百科 散列表 http://zh.wikipedia.org/zh-cn/%E5%93%88%E5%B8%8C%E8%A1%A8
【2】维基百科 分布式散列表 http://zh.wikipedia.org/zh-cn/%E5%88%86%E6%95%A3%E5%BC%8F%E9%9B%9C%E6%B9%8A%E8%A1%A8