散列表查找 (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
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值