什么是哈希表

来源:互联网 发布:淘宝有办假行驶证的吗 编辑:程序博客网 时间:2024/06/06 03:48
想写博客很久了,一直没有时间,也不知道从何写起,现在想想,其实早就应该写一写了,就从哈希表开始吧。哈希表在面试中,特别是一面中,是会经常问到的数据结构,对于哈希表的理解。说了这么多,我们还是来看一看到底什么是哈希吧 哈希表,也叫散列表,散列散列,就是分散排列,什么意思呢,说到这个,我们还得说说为什么会有散列的出现存在即合理,这个我想大家都听说过,在我们常见的存储结构中,有这么两种是最常用的,一个就是数组,一个就是链表,但是,福兮祸所伏,祸兮福所倚。数组:寻址快,插入删除慢链表:插入删除快,寻址慢综上所述,哈希表就是结合了二者的优点而产生的产物,它的优点就是寻址快,插入删除也快!而且,哈希表既是一种存储方法,也是一种查找方法。那么问题来了,这么好的数据结构,咋实现的呢?在Java中,哈希表的实现就是用的数据+链表。我们称之为:拉链法,也就是链表的数组。1 直接定址法

这里写图片描述
下面我们来说一说在Java中哈希表的实现方法:
首先HashMap里面实现一个静态内部类Entry,其重要的属性有 key , value, next,从属性key,value我们就能很明显的看出来Entry就是HashMap键值对实现的一个基础bean,我们上面说到HashMap的基础就是一个线性数组,这个数组就是Entry[],Map里面的内容都保存在Entry[]里面。
2 散列函数的原则
原则:1 计算简单 2 散列地址分布均匀
计算简单大家比较好理解,我用哈希表本来就是为了快,然后你给我弄个散列函数,算了半个小时,是不是傻
至于散列地址分布均匀,这个我们一会儿再说。
3 构造方法
.1 直接定址法
也就是说啊,我们取关键字的某个线性函数值为散列地址,即:
f(key)=a*key+b(a,b为常数)
优点:简单,真的简单啊,还均匀,也不会产生冲突
缺点:适用范围太小,怎么可能所有的数据你都知道,而且还知道关键字的分布情况

.2 数字分析法
就是分析当前的key的值,如果key的数字是比较有规律的,比如说,电话号,校园卡大家都用过吧,基本上,你和你室友的电话号就差最后一位,那么,当你的电话号为key值时,你的散列函数就是用前10位,都不带好使的!
所以,数字分析法其实就是在你是先知道或者预计key的值的情况下,抽取一部分数字进行运算,作为我们的这个散列值,这个就是比较靠谱的
适用范围:适合处理关键字比较大的情况。
优点:简单
示例:
.3 平方取中法
适用于关键字比较小的情况,又不用事先知道关键字的分布
.4折叠法
折叠法时将关键字从左到右分割乘位数相等的几部分,然后将这些部分叠加求和,并按散列表长,取最后即为作为散列地址
试用范围:事先不知道关键字的分布,适合关键字位数较多的情况
.5 除留余数法
此方法是最常用的构造散列函数的方法,对于散列表长的m的散列函数公式为:
f(key)=key%p(p<=m)
这个方法不仅可以对关键字直接取膜,也可在折叠,平方取中后再取模。
哪p取多少好呢,最好是小于等于表长的最小质数或者不包含小于20质因子的合数
.6 随机数法
就是取个随机数作为散列地址了 当关键字长度不定的时候,这个比较合适,

注:大家可能会问,你说的这个都是数字,我key值是字符串呢
其实,无论是英文字符,还是中文字符,都可以当作数字来对待,至于是ASCII还是Unicode,都可以啊

4 处理散列冲突的方法
上回书我们讲到,散列方法的构造函数需要有两个条件,一个是简单,一个是分布均匀,为啥要分布均匀呢,其实就是为了避免冲突,哪啥叫冲突,冲突有什么坏处呢?

避免冲突方法
1 开放地址法:
2 再散列函数法
3 链地址法
4 公共溢出区法

1 开放地址法
线性探测法
二次探测法
随机探测法
2 再散列函数法
当发生冲突时 就换个散列函数继续计算 当然,事先你需要准备多个散列函数 但也增加了计算的时间
3 链地址法(Java中HashMap就是用这种方法实现的散列)
数组中每个元素为一个Entry类,类中有next,key,value三个重要属性,冲突一个,就将新的结点插入,然后,将其next指针指向原来的链表的头节点。这样就好了
4 公共溢出区法
就是再找块儿地存储冲突的元素。对于基本表而言,如果出现的冲突的数据量比较小的话,可以使用。

寻址代码

// 存储时:int hash = key.hashCode(); // 这个hashCode方法这里不详述,只要理解每个key的hash是一个固定的int值int index = hash % Entry[].length;Entry[index] = value;// 取值时:int hash = key.hashCode();int index = hash % Entry[].length;return Entry[index];

借鉴文档:http://blog.csdn.net/vking_wang/article/details/14166593

3 0
原创粉丝点击