散列函数及冲突处理方法

本文详细介绍了散列函数的原理和常见的冲突处理方法,包括开放定址法、再哈希法、链地址法和建立公共溢出区。散列函数如直接定址法、平方取中法和除留余数法被用来将元素转化为数组下标。冲突处理中,线性探查、平方探查和拉链法是常用手段。这些技术在数据结构和算法中有着广泛的应用,特别是在哈希表的实现中。
摘要由CSDN通过智能技术生成

散列函数及冲突处理方法

散列函数及冲突处理方法

1 散列
将元素通过一个函数转换为整数,使得该整数可以尽量唯一地代表这个元素,其中这个转换函数称为散列函数H

2 散列函数
2.1 直接定址法
恒等变换H(key)=key,或是线性变换H(key)=a*key+b

2.2 平方取中法
取key的平方的中间若干位作为hash值(很少用)

2.3 除留余数法
把key除以一个数mod得到的余数作为hash值的方法,H(key)=key%mod。

通过这个方法可以把很大的数转换为不超过mod的整数,这样就可以把它作为可行的数组下标。

当mod是一个素数时,H(key)能尽可能覆盖[0,mod)范围内的每一个数

2.3.1 线性探查法
如果表中下标为H(key)的位置已经被某个其他元素使用了,那么就检查下一个位置H(key)+1是否被占,如果还是被占,就继续检查下一个位置(hash值不断加1).如果检查过程中超过了表长,那么就回到表的首位继续循环,直到找到一个可以使用的位置。

2.3.2 平方探查法
H(key)+12、H(key)-12、H(key)+22、H(key)-22、H(key)+3^2…

如果H(key)+k2超过了表长TSize,那么就把H(key)+k2对表长TSize取模

2.3.3 链地址法(拉链法)
把所有H(key)相同的key连接成一条单链表。

设定一个数组Link,范围是Link[0]-Link[mod],Link[h]存放H[key]=h的一条单链表。

一般不需要自己实现上面解决冲突的方法,可以使用map来直接使用hash的功能

Hash算法解决冲突的方法一般有以下几种常用的解决方法
1, 开放定址法:
所谓的开放定址法就是一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入
公式为:fi(key) = (f(key)+di) MOD m (di=1,2,3,……,m-1)
※ 用开放定址法解决冲突的做法是:当冲突发生时,使用某种探测技术在散列表中形成一个探测序列。沿此序列逐个单元地查找,直到找到给定的关键字,或者
碰到一个开放的地址(即该地址单元为空)为止(若要插入,在探查到开放的地址,则可将待插入的新结点存人该地址单元)。查找时探测到开放的地址则表明表
中无待查的关键字,即查找失败。
比如说,我们的关键字集合为{12,67,56,16,25,37,22,29,15,47,48,34},表长为12。 我们用散列函数f(key) = key mod l2
当计算前S个数{12,67,56,16,25}时,都是没有冲突的散列地址,直接存入:

这里写图片描述
计算key = 37时,发现f(37) = 1,此时就与25所在的位置冲突。
于是我们应用上面的公式f(37) = (f(37)+1) mod 12 = 2。于是将37存入下标为2的位置:
这里写图片描述

2, 再哈希法:
再哈希法又叫双哈希法,有多个不同的Hash函数,当发生冲突时,使用第二个,第三个,….,等哈希函数
计算地址,直到无冲突。虽然不易发生聚集,但是增加了计算时间。

3, 链地址法:
链地址法的基本思想是:每个哈希表节点都有一个next指针,多个哈希表节点可以用next指针构成一个单向链表,被分配到同一个索引上的多个节点可以用这个单向
链表连接起来,如:
键值对k2, v2与键值对k1, v1通过计算后的索引值都为2,这时及产生冲突,但是可以通道next指针将k2, k1所在的节点连接起来,这样就解决了哈希的冲突问题
这里写图片描述
4, 建立公共溢出区:
这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表

首先,我们需要选择一个合适的散列函数。在实际应用中,通常使用哈希函数来将输入映射为固定长度的输出。常见的哈希函数有MD5、SHA-1等。在本例中,我们选择SHA-256算法作为哈希函数。 其次,我们需要考虑冲突处理方法。当两个不同的输入映射到同一个哈希值时,就会发生哈希冲突。这种情况下,我们需要采取一些措施来解决冲突。常见的冲突处理方法有开放地址法、链表法等。在本例中,我们选择链表法作为冲突处理方法。 下面是QQ账户的申请与登录的编程实现(Python代码): ```python import hashlib class User: def __init__(self, username, password): self.username = username self.password = self._hash_password(password) def _hash_password(self, password): sha256 = hashlib.sha256() sha256.update(password.encode('utf-8')) return sha256.hexdigest() class QQAccount: def __init__(self): self.user_dict = {} def register(self, username, password): if username in self.user_dict: print('Username already exists!') return user = User(username, password) self.user_dict[username] = user print('Registration successful!') def login(self, username, password): if username not in self.user_dict: print('Username does not exist!') return False user = self.user_dict[username] if user.password != password: print('Password incorrect!') return False print('Login successful!') return True ``` 在上面的代码中,我们定义了一个`User`类来表示用户,其中`_hash_password`方法使用SHA-256算法对密码进行哈希。然后,我们定义了一个`QQAccount`类来管理用户账户,其中`register`方法用于注册新用户,`login`方法用于用户登录。在`login`方法中,我们首先检查用户名是否存在,然后比较输入的密码和哈希后的密码是否匹配,最后返回登录结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值