为什么使用hash类?

为什么使用hash类?

我们为什么要用“键值对”这样类型的数据结构?除了刚才提到的便于信息检索外,另一个原因是,使用“键值对”类型的数据结构,我们可以提高在大数据量里检索信息的速度。

我们来看一个具体的例子,我们在实际代码里,用一个长度为10000(或更长)的数组来容纳整型数字对象,如果要从其中查询指定数字的话,我们不得不依次遍历这个数组,这样效率会很低。

如果我们换一种思路,在向这数组里插入数字元素的时候,不是插入在数组的第一个空闲空间里,而是根据数据元素 的值,进行一个函数处理,把函数处理的结果作为插入位置的索引值,而在查找数字的时候,也根据这个同样的函数,计算出该数字的索引值,然后据此直接到指定 位置查找,这样我们可以很好地提高效率。

比如,我们定义转换函数的形式是f(x) = x*x%13,其中,x表示插入和待查找的数字,而f(x)则表示这个数字在数组里的索引值,假设我们要插入100这个数字,根据函数我们得到索引值为100*100%13 = 3,那么我们可以把100放在索引值是3的位置,而查找的时候,可直接到这个位置去查找。

这就是Hash表提高索引效率的做法,其中,刚才提到的转换函数叫“散列函数”(也叫Hash函数),存放在数组里的数字称之为Hash表的“值”,而与数字对应的“在数字里的索引位置”则称为Hash表的“键”,由此我们可以看到“键值对”的思路对提高数据检索速度的作用。

这里讲到的“散列函数”是广义的,它不仅可以根据数值型的“值”生成索引值,更可以根据字符型甚至是对象型的“值”生成索引值。

不过,在使用Hash表的时候,我们经常会遇到“索引冲突”这个问题,即对于散列函数,不同的“值”会得到相同的“键”,由此,不同的对象可能存放在同一个索引位置上,比如根据f(x) = x*x%13这个散列函数,4和100会有相同的索引值。

为了解决这个“冲突”问题,一方面可以采用技术上的方法,比如设计出尽量降低冲突情况出现的散列函数,或者是 指定冲突发生时的应对策略(比如遇到冲突时,对象如果发现对应它的索引位置已被占据,就依次顺延到下一个位置,而在搜索时,如果在对应的索引位置没有发现 指定元素,就一直向后查找),而另一方面,则可根据待存储的数据量,适当提高Hash表的容量,用加大空间的代价,来换取冲突发生的低概率。

这里就有一个新的问题:如何根据Hash表里的存储数据量,开辟Hash表的存储空间?如果空间开设较小,虽然可以节省内存使用量,但会提高冲突发生的概率,从而降低数据搜索的效率,反之,虽然可以提高搜索效率,但会过多地使用内存。

对此,Hash表里,专门有个名词,叫装载因子,即Hash表里实际容纳对象的比率,一般来说,这个常数在75%左右最为合适。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值