数据结构与算法 — 哈希函数及其实现、哈希表的实现、哈希表的扩容

本文详细介绍了哈希函数的设计原则,包括快速计算和均匀分布,探讨了哈希表的实现,如链地址法,以及哈希表的扩容策略。在哈希函数中,使用霍纳法则优化计算并利用质数提高分布均匀性。此外,文章还讨论了哈希表的插入、获取、删除等操作,并提到了判断质数的高效方法,以及为何哈希表容量选择质数的益处。
摘要由CSDN通过智能技术生成

目录

一. 哈希函数

  1.快速的计算

  2.均匀的分布

二、哈希函数的实现 

三、哈希表实现

  1.封装哈希表

  2.插入&修改操作

   3.获取操作

  4. 删除操作

  5.其他方法

四、哈希表扩容

五、判断质数

  1.普通判断质数的方法

  2.高效判断质数的方法     

六、实现容量为质数


一. 哈希函数

  1.快速的计算

        哈希表的主要优点是它的速度,提高速度的一个办法就是让哈希函数中尽量少有乘法和除法。因为它们的性能是比较低的。

        在前面, 我们计算哈希值的时候使用的方式cats = 3*27³+1*27²+20*27+17= 60337

        这个表达式其实是一个多项式: a(n)xn+a(n-1)x(n-1)+…+a(1)x+a(0)

        现在问题就变成了多项式有多少次乘法和加法:

        乘法次数: n+(n-1)+…+1=n(n+1)/2

        加法次数: n次

 多项式的优化: 霍纳法则

通过如下变换我们可以较快的算法,即

Pn(x)= anx n+a(n-1)x(n-1)+…+a1x+a0=((…(((anx +an-1)x+an-2)x+ an-3)…)x+a1)x+a0,

这种求值的方法称为霍纳法则,变换后的乘法次数: N次,变换后的加法次数: N次.

如果使用大O表示时间复杂度的话, 则直接从O(N²)降到了O(N).

  2.均匀的分布

        在设计哈希表时,为了处理映射到相同下标值的情况可以使用链地址法或者开放地址法。为了提高效率,最好让数据在哈希表中均匀分布。

        因此, 我们需要在使用常量的地方, 尽量使用质数.

        质数的使用:

  • 哈希表的长度。
  • N次幂的底数(上例中使用的是27)

哈希表的长度使用质数:

这个在链地址法中的重要性不是特别明显,明显的是在开放地址法中的再哈希法中.

再哈希法中质数的重要性:

        假设表的容量不是质数,例如:表长为15(下标值0~14)。有一个特定关键字映射到0,步长为5。探测序列是0 - 5 - 10 - 0 - 5 - 10, 依次类推循环。算法只探测这三个单元,如果这三个单元已经有了数据,那么会一直循环下去,直到程序崩溃。

        如果容量是一个质数,比如13。探测序列是0 - 5 - 10 - 2 - 7 - 12 - 4 - 9 - 1 - 6 - 11 - 3, 这样下去。不仅不会产生循环,而且可以让数据在哈希表中更加均匀的分布。

链地址法中质数没有那么重要, 甚至在Java中故意是2的N次幂

二、哈希函数的实现 

    设计哈希函数
    1.将字符串转化为较大的数字:hashCode
    2.将大的数字hashCode压缩到数组范围(大小)之内 

    function hashFunc(str,size){
        //1.定义hashCode变量
        var hashCode = 0

        //2.霍纳算法,来计算hashCode的值
        //cats -> Unicode编码
        for(var i=0; i<str.length; i++){
            hashCode = 37*hashCode + str.charCodeAt(i)
        }

        //3.取余操作
        var index = hashCode % size

        return index
    }

测试哈希函数:

    alert(hashFunc('rty',8))//7
    alert(hashFunc('bds',8))//1
    alert(hashFunc('kyu',8))//5
    alert(hashFunc('mbc',8))//2

三、哈希表实现

        采用链地址法来实现哈希表

实现的哈希表(基于storage的数组)每个index对应的是一个数组(bucket)。(基于链表也可以)

bucket中存放key和value,继续使用一个数组

最终哈希表的数据格式是这样: [[ [k,v], [k,v], [k,v] ] , [ [k,v], [k,v] ], [ [k,v]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值