(P24)miniftpd项目实战24:减少冲突的方法:开地址法,减少冲突的方法:建立公共溢出区

1.减少冲突的方法:开地址法

  • 基本思想:当关键码key的哈希地址 H 0 H_0 H0 = hash(key)出现冲突时,以H0为基础,产生另一个哈希地址H1 ,如果H1仍然冲突,再以 H 1 H_1 H1为基础,产生另一个哈希地址 H 2 H_2 H2 ,…,直到找出一个不冲突的哈希地址 H i H_i Hi ,将相应元素存入其中。这种方法有一个通用的再散列函数形式:
    Hi = (H0 + di) % m, i =1, 2, …, m-1

  • 其中H0 为hash(key) , hash(key) 表示通过哈希函数得到的第一个哈希地址,或者说是第一个桶号,如果这个桶号所对应的桶不是空的,则说明产生了冲突,则需要计算下一个桶,m为表长,di称为增量序列。增量序列的取值方式不同,相应的再散列方式也不同。主要有以下四种:
    (1)线性探测再散列, d i 是 i d_i是i dii,最容易产生堆积
    (2)二次探测再散列, d i 是 + i 2 或 者 − i 2 d_i是+i^2或者-i^2 di+i2i2,最不容易产生堆积,缺点:不容易探测整个表空间
    (3)伪随机探测再散列, d i 是 随 机 数 R a n d o m d_i是随机数Random diRandom,不好用
    (4)双散列法
    ,, d i 是 i ∗ R e h a s h ( ) d_i是i*Rehash() diiRehash(),最好用,最大限度的避免堆积现象
    这4种方法的区别在于di取值不同

  • 线性探测再散列
    在这里插入图片描述

  • eg:假设给出一组表项,它们的关键码为 Burke, Ekers, Broad, Blum, Attlee, Alton, Hecht, Ederly。采用的散列函数是:取其第一个字母在字母表中的位置。
    hash (x) = ord (x) - ord (‘A’)
    这样,可得
    hash (Burke) = 1 hash (Ekers) = 4
    hash (Broad) = 1 hash (Blum) = 1
    hash (Attlee) = 0 hash (Hecht) = 7
    hash (Alton) = 0 hash (Ederly) = 4

  • 又设散列表为HT[26],m = 26。采用线性探查法处理溢出,则上述关键码在散列表中散列位置如图所示。括号内的数字表示找到空桶时的探测次数。
    在这里插入图片描述

先放Burk到桶号为1的位置,再放Ekers到桶号为4的位置,再放Broad,发现1号位置被占了,所以依据哈希公式向下探查,放到了桶号为2的位置,以此类推
在这里插入图片描述

最后的位置是:括号内的数字表示找到空桶时的探测次数。
在这里插入图片描述

  • 不同于链地址法,线性探测再散列法的重要说明:linear_probing\hash.c
typedef struct hash_node
{
	enum entry_status status;//引入了节点的状态,因为再插入的时候要判定这个地址是否是空的
							//这个地址存放一个节点,如果节点是空的就可以放进来,所以需要状态
							//假设将Broad删除,然后我们要查找Blum,Blum这时映射到了1这个地址,发现
							//产生了冲突,要向下探查2这个地址,若做的是物理删除的话,那么此时就不能继续探查了,因为是空的
							//所以这里应该做逻辑删除,给node一个删除状态,方便能够继续向下搜索。直到能找到Blum
	void *key;
	void *value;
} hash_node_t;

在这里插入图片描述

  • eg:linear_probing其中的内容

  • 测试:
    在这里插入图片描述

  • 线性探测再散列法会造成堆积现象
    (1)散列地址不同的结点争夺同一个后继散列地址的现象称为堆积(Clustering)。就是找桶的过程
    (2)这将造成不是同义词的结点也处在同一个探测序列中,从而增加了探测序列长度,即增加了查找时间。
    (3)若散列函数不好、或装填因子过大,都会使堆积现象加剧。
    装填因子,反应的是表的装满程度,
    α = 表元素个数/表长 <=1,链地址法是可以>1的

  • 二次探测再散列
    (1)为改善“堆积”问题,减少为完成搜索所需的平均探查次数,可使用二次探测法。
    (2)通过某一个散列函数对表项的关键码 x 进行计算,得到桶号H0 ,它是一个非负整数。
    H0 = hash(x)
    (3)二次探测法在表中寻找“下一个”空桶的公式为:
    在这里插入图片描述
    式中的 m 是表的大小,它应是一个值为 4k+3 的质数,其中k是一个整数。这样的质数如 3, 7, 11, 19, 23, 31, 43, 59, 127, 251, 503, 1019, …。
    探测序列形如 H0, H0+1, H0-1, H0+4, H0-4, …。
    在做 (H0 - i 2 i^2 i2 ) % m 的运算时,当 H0 - i2 <0 时,运算结果也是负数。实际算式可改为
    在这里插入图片描述
    若设表的长度为TableSize = 23,则利用二次探查法所得到的散列结果如图所示。
    在这里插入图片描述
    为了能够以上一个地址位置为基础而得到的新的位置pos,对公式做一定的处理
    在这里插入图片描述

  • eg:quardratic_probing\hash.c等内容

  • 双散列法
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

2.减少冲突的方法:建立公共溢出区

  • 这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

喜欢打篮球的普通人

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

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

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

打赏作者

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

抵扣说明:

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

余额充值