8.5计算式查找(哈希查找及性能分析)

8.5计算式查找(哈希查找及性能分析)

一、哈希表的查找过程

哈希表的查找过程与哈希表的创建过程是一致的。假设要查找关键字为 K 的
元素,则查找过程如下:
[算法思想]:

  • (1) 首先计算 h0= hash(K);
  • (2) 如果单元 h0为空,则所查元素不存在;
  • (3) 如果单元 h0中元素的关键字为 K,则找到所查元素;
  • (4) 否则重复下述解决冲突的过程:
    a. 按解决冲突的方法,找出下一个哈希地址 hi ;
    b. 如果单元 hi为空,则所查元素不存在;
    c. 如果单元 hi中元素的关键字为 K,则找到所查元素。

下面以线性探测再散列为例,给出哈希表的查找算法。
[算法描述]: 哈希表的查找算法

#define m <哈希表长度>
#define NULLKEY <代表空记录的关键字值>
typedef int KeyType; /* 假设关键字为整型 */
typedef struct
{
	KeyType key;
	…… /* 记录中其它分量按需求确定 */
	……
} RecordType ;
typedef RecordType HashTable[m] ;
int HashSearch( HashTable ht, KeyType K)
{
	h0=hash(K);
	if (ht[h0].key==NULLKEY) 
		return (-1);
	else if (ht[h0].key==K) 
		return (h0);
	else /* 用线性探测再散列解决冲突 */
	{
		for (i=1; i<=m-1; i++)
		{
			hi=(h0+i) % m;
			if (ht[hi ].key==NULLKEY) 
				return (-1);
			else if (ht[hi].key==K) 
				return (hi);
		}
		return (-1);
	}
}

二、哈希法性能分析

由于冲突的存在,哈希法仍需进行关键字比较,因此,仍需用平均查找长度来评价哈希法的查找性能。哈希法中影响关键字比较次数的因素有三个:哈希函数、处理冲突的方法以及哈希表的装填因子。哈希表的装填因子α的定义如下:

在这里插入图片描述
α可描述哈希表的装满程度。显然,α越小,发生冲突的可能性越小,而α越大,发生冲突的可能性也越大。假定哈希函数是均匀的,则影响平均查找长度的因素只剩下两个:处理冲突的方法以及α。以下按处理冲突的不同方法,分别列出相应的平均查找长度的近似公式:

在这里插入图片描述
从以上讨论可知:哈希表的平均查找长度是装填因子α的函数,而与待散列元素数目 n 无关。因此,无论元素数目 n 有多大,都能通过调整α,使哈希表的平均查找长度较小。

对于一个具体的哈希表,通常采用直接计算的方法求其平均查找长度。

例已知一组关键字序列(19,14,23,01,68,20,84,27,55,11,10,79)给出按哈希函数 H(key)=key % 13 和线性探测处理冲突构造所得哈希表ht[0…15]。

如下图所示。其中,每个关键字下面带圈的数字,是放置该关键字时所进行的地址计算次数,或者说是放置该关键字时所进行的关键字比较次数(同时也是查找该关键字时所进行的关键字比较次数)。
在这里插入图片描述
查找 19 时,通过计算 H(19)= 6,ht[6].key 非空且值为 19 查找成功,则查找关键字 19,仅需要计算 1 次地址就可以找到。

查找 14 时,通过计算 H(14)= 1,ht[1].key 非空且值为 14 查找成功,则查找关键字 14,仅需要计算 1 次地址就可以找到。

查找 23 时,通过计算 H(23)=10,ht[10].key 非空且值为 23 查找成功,则查找关键字 23 ,仅需要计算 1 次地址就可以找到。

同样,查找关键字 68,20,11,均需要计算一次地址就可以找到。

查找关键字 01 时,通过计算 H(01)=1,ht[1].key 非空且值为 14≠01,则找第一次冲突处理后的地址 h1=(1+1)%16=2,此时,ht[2].key 非空且值为 01,查找成功,因此查找关键字 01 时,需要计算 2 次地址才可以找到。

查找关键字 55 时,通过计算 H(55)=3,ht[3].key 非空且值为 68≠55,则找第一次冲突处理后的地址 h1=(3+1)%16=4,此时,ht[4].key 非空且值为 27≠55,则找第二次冲突后处理地址 h2=(3+2)%16=5, ht[5].key 非空且值为 55,查找成功,因此查找关键字 55 时,需要计算 3 次地址才能找到。

同理,查找关键字 10,84 均需要计算 3 次地址才能找到。

查找关键字 27 时,通过计算 H(27)=1,ht[1].key 非空且值为 14≠27,则
找第一次冲突处理后的地址 h1=(1+1)%16=2,此时,ht[2].key 非空且值为01≠27,则找第二次冲突后处理地址 h2=(1+2)%16=3, ht[3].key 非空且值为 68≠27,则找第三次冲突后处理地址 h3=(1+3)%16=4,ht[4].key 非空且值为 27,查找成功,因此查找关键字 27 时,需要计算 4 次地址才可以找到。

根据上面的方法,查找关键字 79 时,通过计算 H(79)=1,ht[1].key 非空且值为 14≠79,则找第一次冲突处理后的地址 h1=(1+1)%16=2,此时,ht[2].key非空且值为 01≠79,则找第二次冲突后处理地址 h2=(1+2)%16=3, ht[3].key 非空且值为 68≠79,则找第三次冲突后处理地址 h3=(1+3)%16=4,ht[4].key 非空且值为 27≠79,则找第四次冲突后处理地址 h4=(1+4)%16=5,ht[5].key 非空且值为55≠79,则找第五次冲突后处理地址 h5=(1+5)%16=6,ht[6].key 非空且值为 19≠79 则找第六次冲突后处理地址 h6=(1+6)%16=7,ht[7].key 非空且值为 20≠79,则找第七次冲突后处理地址 h7=(1+7)%16=8,ht[8].key 非空且值为 84≠79,则找第八次冲突后处理地址 h8=(1+8)%16=9,ht[9].key 非空且值为 79,查找成功,因此查找关键字 79 时,需要计算 9 次地址才可以找到。

手工计算等概率情况下查找成功的平均查找长度公式

手工计算等概率情况下查找成功的平均查找长度规则如下:
在这里插入图片描述
其中 Ci为查找第 i 个元素时所需的比较次数(即置入第 i 个元素时所需的比较次数)。

据此计算公式,对下图所示采用线性探测再散列法处理冲突的哈希表,可计算出在等概率情况下其查找成功的平均查找长度为:
在这里插入图片描述
在这里插入图片描述
为便于计算,在上图哈希表的每个关键字下方标出了查找该关键字时所进行的关键字比较次数。

据此计算公式,对下图所示采用链地址法处理冲突的哈希表,可计算出在等概率情况下其查找成功的平均查找长度为:
在这里插入图片描述

手工计算在等概率情况下查找不成功的平均查找长度公式

手工计算等概率情况下查找不成功的平均查找长度规则如下:
在这里插入图片描述
其中 Ci为哈希函数取值为 i 时查找不成功的比较次数。

查找不成功的情况:(1)遇到空单元,(2)按解决冲突的方法完全探测一遍后仍未找到。0 到 r-1 相当于 r 个不成功查找的入口,从每个入口进入后,直到确定查找不成功为止,其关键字的比较次数就是与该入口对应的不成功查找长度。

据此计算公式,对下图所示的哈希表(采用线性探测再散列法处理冲突),可计算出在等概率情况下其查找不成功的平均查找长度为:
在这里插入图片描述
据此计算公式,对下图所示的哈希表(采用链地址法处理冲突),可计算出在等概率情况下其查找不成功的平均查找长度为:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值