数据结构与算法(如何设计一个工厂的hash表)

回顾:通过上一节课的学习,我们不能笼统的说hash表的查找的时间复杂度为O(1 ),hash表的时间复杂度跟hash函数,装载因子,hash冲突等有关,如果hash函数设计的不好,或者装载因子过高,活导致hash表查询的时间复杂度增大,在极端的情况下,当hash函数设计不好,所有数据经过hash都存在同一个佣中,hash表查找会变成单链表的查找.

1>今天我们主要学习下该如何设计一个工程的hash表,应该注意哪些要点,

       a>Hash函数的设计,一个好的hash函数应该满足这样的条件,hash计算不能太过复杂,太过复杂容易导致计算性能下降,且通过hash函数的值应该随机分布,这样才可以避免hash冲突,即使存在hash冲突,也会使得每个佣中的数据个数大致相同,不会使得查询变成极端的成功.

    2>装载因子的值都低是多少合适呢?

      公式:装载因子= 佣用的元素个数/佣的个数

      如果涉及的装载因子过大,说明佣中的存储空间已经很少了,hash冲突的概率增大,在插入的过程中需要多次寻址,且需要很长的链表.查找也需要遍历较长的链表结构,

      对于没有频繁的插入操作的情况下,我们很容易设计出完美的Hash表,毕竟数据是已知的,

    对于频繁的进行插入删除操作,因为数据量我们无法估计,我们可以使用动态扩容机制,重新申请一个更大的散列表,重新hash,将数据加载到新的Hash表中,

解说:在图中21本身存储在佣中的0下标,经过动态扩容机制之后,佣数量变为原来的2倍,经过重新hash,数据21存储在下标为7的位置,

 复杂度分析:在最好的情况下,插入一个数据不需要动态扩容,数据放在链表就可,时间复杂度为O(1),当插入一个数据需要进行动态扩容,重新hash,插入的时间复杂度是O(n);

  3>如何高效的解决hash冲突 

            上节课我们讲了2种方法,开放寻址法,链表法,java中的hashmap就是佣的链表法 ,localhashmap中使用的是开放寻址法莱解决hash冲突.

      当数据量比较小的情况下 ,且装载因子比较小,适合采用开放寻址法,

     当数据量比较大的时候,比起开放寻址法,他更起到优化作用,比如用红黑树代替链表结构.

4>hashmap的实列

           a:hashmap在初始创建,容量大小是16,这个值是可以设置的,可以设置的更大,来减少扩容的次数

           b:装载因子:hashmap的装载隐因子是0.75,当hashmap中的元素数据个数超过0.75*16=12,就会进行扩容,每次扩容都会变为原来的2倍.

         c:hashmap底层采用的是拉链法莱解决hash冲突,但是在一些极端的情况下,也避免不了链表过长,查找性能下降,在jdk1.8中,当链表长度超过8时,链表将用红黑树来代替,

5>解答开篇,工厂hash表的设计

        1>支持快速的插入删除操作

        2>内存占用合理,不鞥浪费过多的空间内存

        3>性能稳定,在极端的情况下,散列表退化成链表可在接受的情况下

如何设计一个散列表

          a>设计一个合适的hash函数

          b>定义装载因子的阈值,支持动态扩容机制

          c>选择合适的hash冲突解决方法(开放寻址法,链表法)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值