散列表详解

1. 简介

如果所有的键都是小整数,我们可以用一个数组来实现无序的符号表,将键作为数组的索引而
数组中键 i 处储存的就是它对应的值。这样我们就可以快速访问任意键的值

使用散列的查找算法分为两步:

  1. 用散列函数将被查找的键转化为数组的一个索引(理想情况下每个键对应的索引都不一样,实际上会有不同的键转化成相同的索引)
  2. 多个键都会散列到相同的索引值,需要处理碰撞冲突的情况(拉链法和线性探测法)
    在这里插入图片描述

2. 散列函数

散列函数:将键转化为数组的索引

要求:

  1. 散列函数应该易于计算
  2. 能够均匀分布所有的键,减少冲突
  • 每种数据类型都需要相应的散列函数,于是 Java 令所有数据类型都继承了一个能够返回一个32 比特整数的 hashCode() 方法
  • 如果 a.equals(b) 返回 true,那么 a.hashCode() 的返回值必然和 b.hashCode()的返回值相同
  • 两个对象的 hashCode() 方法的返回值相同,这两个对象也有可能不同,还需要用 equals() 方法进行判断
  • 如果两个对象的 hashCode() 方法的返回值不同,那么我们就知道这两个对象是不同的
		Integer a=1;
		Integer b=1;
		System.out.println(a.hashCode());//1
		System.out.println(b.hashCode());//1
		String s1="hello";
		String s2="hello";
		System.out.println(s1.hashCode());//99162322
		System.out.println(s2.hashCode());//99162322

要为自定义的数据类型定义散列函数,需要同时重写 hashCode() 和 equals() 两个方法,默认散列函数会返回对象的内存地址

hashcode方法返回一个32bit的数值,但是数组的索引往往没有那么大,因此不能直接使用hashcode值,需要进行转换,将默认的 hashCode()方法和除留余数法结合起来产生一个 0 到 M-1 的整数

private int hash(Key x) {
		return (x.hashCode()&0x7fffffff)%M;
	}

上面这段代码的作用:

  1. 将一个 32 位整数变为一个 31 位非负整数
  2. 用除留余数法计算它除以 M 的余数

3. 基于拉链法的散列表

将大小为 M 的数组中的每个元素指向一条链表,链表中的每个结点都存储了散列值为该元素的索引的键值对。这种方法被称为拉链法

在这里插入图片描述


4. 基于线性探测法的散列表

用大小为 M 的数组保存 N 个键值对,其中 M>N。依靠数组中的空位解决碰撞冲突。基于这种策略的所有方法被统称为开放地址散列表,开放地址散列表中最简单的方法叫做线性探测法

当碰撞发生时(当一个键的散列值已经被另一个不同的键占用),直接检查散列表中的下一个位(将索引值加 1,到达数组结尾时折回数组的开头),直到找到该键或者遇到一个空元素

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodePanda@GPF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值