散列函数

散列分配算法:散列表大小尽量设为素数

  • 输入的关键字是整数 ============ 返回 Key mod TableSize ,通俗的讲也就是取余数 比如 2 mod 10 = 1 那么 关键字为2的值存放在 [1] 的 位置 
  • 输入的关键字个位数是0 =========== 设置表的大小为素数 返回 Key mod TableSize

    素数释义:曾称质数。一个大于1的正整数,如果除了1和它本身以外,不能被其他正整数整除,就叫素数。如2,3,5,7,11,13,17…。

  • 关键字是字符串 ============= 把字符串中的ASCII码(或UNICODE码)加起来然后 mod TableSize 。注意:char 也可以用int 表示 例如  int i = char("ok");ASCII位数最多为127,如果key长度为8 那么至多有 8*127=1016种可能,如果表超过1016 那么就不能均匀的分配。
  •    字符串horner算法,hashVal = 37 * hashVal + key.charAt(i); hashVal %= tableSize ;if(hashVal < 0) hashVal + =tableSize return hashVal;

冲突解决算法:

  • 分离链接法:当hash冲突时,在当前hash位置 向后添加一条链表 ,具体实现参照JAVA8 HashMap 实现(链表新增从1.7的头插法改为了尾插法,因为头插法在并发扩容的时候出现过死循环)
  • 线性探测法:tableSize =10 ; key1 = 89 ;  89 mod 10 = 9 ; key2=99 ; 99 mod 10 = 9  则9放在 数组[9]的位置,key2 与key1 冲突则key2 往下延续一个格子 放在 数组[0]的位置;
  • 平方探测法:当key在[x]位置遇到冲突的时候往下一位找,如果[x+1] 也冲突,那么在 [x]的基础上往后移动到 2^2 的位置 ,例如 tableSize =10(下标为0) ,位置[x] = 8 ,那么最终 key所在的位置为 8(冲突位置)->[9]->[0]->[1]->[2] 最终key 为移动到tableSize[2] 的位置  平方探测发定理,如果使用平方探测法,且表的大小是素数,那么当表至少有一半是空的时候,总能够插入一个新的元素
  • 双散列:通过二次hash函数计算位置,注意这里 mod 值一定不要为0 否则二次散列无效。
  • 再散列:当tableSize = 7 的散列表被填满 %70的时候 ,将原散列表大小 * 2  并寻找第一个素数 17 ,那么新的散列表大小就为 17,然后重新扫描原散列表 把数据重新 映射到 新的散列表当中,类似扩容机制。至于在什么时候扩容有3种方式,一:当表满达到一半就进行扩容,二:当插入失败就进行扩容,三:类似负载因子的计算进行扩容。(可以称为rehash)
  • 布谷鸟散列:

    1、两个位置均为空,则任选一个插入;
    2、两个位置中一个为空,则插入到空的那个位置
    3、两个位置均不为空,则踢出一个位置后插入,被踢出的对调用该算法,再执行该算法找其另一个位置,循环直到插入成功。
    4、如果被踢出的次数达到一定的阈值,则认为hash表已满,并进行重新哈希rehash

  • 跳房子散列:线性探测的时候加上一个探测阈值,比如发生hash冲突时候,最多探测4次就结束。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值