【Java】哈希表与哈希函数

本文介绍了哈希表和哈希函数的基本概念,包括它们如何通过映射函数实现快速查找,以及常见的哈希冲突解决方法。同时,还详细讨论了五种构造哈希表的方法,帮助读者深入理解哈希技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(本人是菜鸟一枚,仅代表个人的一些见解,如有不对,请轻喷!!!!)
哈希函数与哈希表在java工作中最为常见,故做一些哈希方面得知识整理(借鉴自杨守乐大神的公众号),后续会继续完善补充。

一、哈希表和哈希函数

在记录的存储位置和它的关键字之间建立一个确定的对应关系(映射函数),使每个关键字和一个存储位置能唯一对应。

这个映射函数称为哈希函数,根据这个原则建立的表称为哈希表(Hash Table),也叫散列值。

如果通过数学的形式描述就是:

查找关键字为key,则其值放在f(key)的存储位置上。由此,不需比较便可直接取得所查记录。

注:哈希查找与线性查找和树表查找最大的区别在于:不用比较数值。


二、冲突
若key1 != key2,存在f(key1) = f(key2),这种情况称之为冲突。

根据哈希函数和处理冲突的方法将一组关键字映射到一个有限的连续的地址集上,并以关键字在地址集中的“像”作为记录在表中的存储位置,这一映射过程称之为构造哈希表。
构造哈希表这个场景就像汽车找停车位,如果车位被人占了,只能找空的地方停。

三、构造哈希表

有以上内容可知,哈希查找本身其实不费吹灰之力,问题的关键在于构建哈希表和处理冲突。
常见构造哈希表的方法有五种:

① 直接定址法
说白了,就是小学学的一元一次方程。
即f(key) = a*key + b。a和b都是常数。

② 数字分析法
假设关键字是R进制数,并且哈希表中可能出现的关键字是事先知道的,则可选取关键字的若干数位组成哈希地址。
选取的原则是使得到的哈希地址尽量避免冲突,即选取位数上的数字尽可能是随机的。

③ 平方取中法
取关键字平方后的中间几位为哈希地址。通常在选定哈希函数时不一定能知道关键字的全部情况,仅取其中的几位为地址不一定合适;
而一个数平方后的中间几位数和数的每一位都相关,由此得到的哈希地址的随机性更大。取的位数由表长决定。

④ 除留余数法
取关键字被某个不大于哈希表表长m的数p除后所得的余数为哈希地址。
即f(key) = key%p(p<=m)
这是一种最简单,最常用的方法,它不仅可以对关键字直接取模,也可在折叠、平方中等运算之后取模。
注意:p的选择很重要,如果选的不好,容易产生冲突。根据经验,一般情况下可以选p为素数。

⑤ 随机数法
选择一个随机函数,取关键字的随机函数值为它的哈希地址,即f(key) = random(key).
通常在关键字长度不等时采用此法构造函数较为恰当。

四、 解决冲突
设计合理的哈希函数可以减少冲突,但不能完全避免冲突。

所以需要有解决冲突的方法,常见有两类:

(1) 开放定址法
如果两个数据元素的哈希值相同,则在哈希表中为后插入的数据元素另外选择一个表项。
当程序查找哈希表时,如果没有在第一个对应的哈希表项中找到符合查找要求的数据元素,程序就会继续往后查找,直到找到一个符合查找要求的数据元素或遇到一个空的表项。

(2)拉链法
将哈希值相同的数据元素存放在一个链表中,在查找哈希表的过程中,当查找到这个链表时,必须采用线性查找方法。
在这种方法中,哈希表中每个单元存放不再是记录本身,而是相应同义词单链表的头指针。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值