散列表查找 (15 分)

设散列表a[18],散列函数是hask(k)=k%17,用开放地址法解决冲突hi=(h0+di)%m。冲突时采用平方探测法,使用增量序列di=i* i。计算输入序列(值>=0)对应的散列地址并进行查找,如果有此元素,则输出散列地址,如果无此元素,则输出not found。并输出查找次数(输入个数不会超过15个)

输入格式:

第一行为输入个数;

第二行为对应的输入值,用空格隔开;

第三行为需查找的元素,第1个为查找元素个数,后面为查找元素

输出格式:

第一行输出输入序列的散列地址,以一个空格隔开;

第二行开始输出查找元素的散列地址,每个元素占一行,每行对应一个值及其散列地址,中间用空格隔开(即pos前后均有一个空格),如果无此元素,则输出not found。

输入样例:

5
141 73 95 112 56
7 5 73 95 141 112 56 18

输出样例:

5 6 10 11 9 
5 not found,try 4
73 pos:6,try 2
95 pos:10,try 1
141 pos:5,try 1
112 pos:11,try 2
56 pos:9,try 3
18 not found,try 1
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int a[18], b[18],pos[18],//a顺序存放输入散列表的序列,b按散列函数计算出的地址存放输入元素
arr1[18],arr2[18];//arr1按顺序存放查找元素,arr2顺序存放输入散列表序列的各元素的冲突值
int main() {
	int d,i,j,n,temp,m,k,count;
	//将a,b,pos数组中的内容初始化为-1
	memset(a, -1, sizeof(a));
	memset(b, -1, sizeof(b));
	memset(pos, -1, sizeof(pos));
	scanf("%d", &n);
	for (i = 0; i < n; i++) {
		scanf("%d", &a[i]);
		temp = a[i] % 17;//用散列函数计算散列地址
		d = 1;
		while (b[temp] != -1) {
			temp = (a[i]%17 + d * d) % 18;//平方探测法解决冲突
			arr2[i] = d;
			d++;
		}
		b[temp] = a[i];
		pos[i] = temp;
	}
	scanf("%d", &m);//输入待查找的元素个数
	for (i = 0; i < m; i++)
		scanf("%d", &arr1[i]);//输入待查找元素
	for (i = 0; i < n; i++) {//输出顺序存入散列表的元素地址
		if (i != 0)printf(" ");
		printf("%d", pos[i]);
	}
	printf("\n");
	for (i = 0; i < m; i++) {
		count = 0;
		d = 0;
		for (j = arr1[i] % 17; j < 18;j= (arr1[i] % 17 + d * d) % 18) {
			d++;
			count++;
			if (arr1[i] == b[j]) {
				for (k = 0; k < n; k++) {//在顺序输入散列表的元素中找到与b[j]相等的元素a[k]
					if (b[j] == a[k]) {
						//查找成功的查找次数等于该元素存放时产生冲突的次数+1
						printf("%d pos:%d,try %d\n", arr1[i], pos[k], arr2[k] + 1);
						break;
					}
				}
				break;
			}
			else if (b[j] == -1 || count == 18) {
				//若查找元素应该放入散列表中的位置处没有该元素或遍历一遍散列表未发现此元素则查找失败
				printf("%d not found,try %d\n", arr1[i], count);
				break;
			}
			if (j == 18)j = 0;//因为j是从arr1[i] % 17开始的,若j==18则让j从0开始继续查找
		}
	}
	system("pause");
	return 0;
}

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
散列表查找是一种常见的数据结构操作,可以快速地查找特定的元素。开放地址法是一种常见的解决哈希冲突的方法,它的基本思想是在哈希表中寻找空槽位,将冲突的元素插入到空槽位中,从而解决冲突。 针对您的问题,我假您需要实现一个使用开放地址法散列表查找算法,其散列函数hask(k)=k mod 18,您可以按照以下步骤进行实现: 1. 定义散列表a[18],并初始化为-1,表示所有槽位都是空的。 2. 定义散列函数hask(k)=k mod 18,用于将关键字k映射到散列表中的槽位。 3. 实现查找算法。对于给定的关键字k,首先计算它的散列地址h=hask(k),然后从散列地址h开始向后遍历散列表,直到找到一个空槽位或者槽位中的元素等于k为止。如果找到了空槽位,则说明关键字k不存在于散列表中;否则,找到了相应的元素,返回它的下标即可。 4. 实现插入算法。对于给定的关键字k,首先计算它的散列地址h=hask(k),然后从散列地址h开始向后遍历散列表,直到找到一个空槽位或者槽位中的元素等于k为止。如果找到了空槽位,则将关键字k插入到该槽位中;否则,说明散列表已满,无法插入新元素。 需要注意的是,开放地址法有多种不同的实现方式,比如线性探测、二次探测、双重散列等,您可以根据具体的需求选择不同的实现方式。另外,由于开放地址法容易产生聚集现象,导致性能下降,因此在实际应用中需要结合具体情况进行调整和优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值