数据结构 实验5——散列表的构造和查找

一、实验名称:散列表的构造和查找

二、实验学时:6学时

三、实验目的

1.理解散列表的存储结构;

2.掌握常用散列函数构造方法和处理冲突方法;

3.在散列表上实现查找的算法。

四、实验内容(步骤)

为小于n个关键字设计一个散列表,使得查找成功时平均查找长度<2.0,要求完成相应的散列表建立和查找。假设关键字为整型数据,散列函数用除留余数法,采用开放定址法的线性探测法处理冲突。

1.从键盘输入关键字个数n及关键字数据;

2.根据输入的关键字个数及平均查找长度要求,设计散列函数和计算表长;

3.构造散列表;

4.在散列表中进行查找。

【实验源代码】

#include<iostream>
#include<cstdlib>
#include<limits.h>

#define INFINITY INT_MAX

using namespace std;

typedef int KeyType;

// 顺序表存储结构
typedef struct 
{
	KeyType key; // 关键字(数据项)
	int time; // 探测次数
}ElemType;

typedef struct
{
	ElemType *elem; // 数据元素存储空间基址
	int length; // 查找表的长度 
}HashTable;

void inputData(KeyType KeyData[],int n)
{
	printf("请输入%d个关键字:",n);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&KeyData[i]);
	}
}

void initHashTable(HashTable &HT,int m)
{
	int i;
	HT.elem=(ElemType *)malloc(m*sizeof(ElemType));
	HT.length=m;
	for(i=0;i<HT.length;i++)
	{
		HT.elem[i].key=INFINITY; // 赋初值
		HT.elem[i].time=0;	
	}
}

void outputHashTable(HashTable HT)
{
	int i,count=0,sum=0;
	printf("%8s","地址");
	for(i=0;i<HT.length;i++)
		printf("%3d",i);
	printf("\n");
	
	printf("%8s","关键字");
	for(i=0;i<HT.length;i++)
	{
		if(HT.elem[i].key==INFINITY)
			printf("%3s","");
		else
			printf("%3d",HT.elem[i].key); 
	}
	printf("\n");
	printf("%8s","探测次数");
	for(i=0;i<HT.length;i++)
	{
		if(HT.elem[i].time==0)
			printf("%3s","");
		else
		{
			printf("%3d",HT.elem[i].time);
			count++;
			sum+=HT.elem[i].time;
		}
	}
	printf("\n查找成功时的平均查找长度为:%.2f",sum*1.0/count);
}

void calcpm(int n,int &p,int &m)
{
	int i,j;
	float Snl=2.0; // 平均查找长度
	float a; // 装填因子 
	
	// 求m
	a=1-1/(2*Snl-1);
	m=int(n/a)+1;
	m=12; 
	// 求p
	p=2;
	for(i=m;i>2;i--)
	{
		for(j=2;j*j<=i;j++)
		{
			if(i%j==0)
				break;
		}
		if(j*j>i)
		{
			p=i;
			break; // 求得小于m的最大质数 
		}
	}
}

int hashFunc(KeyType key,int p)
{
	int addr=-1;
	addr=key%p;
	return addr;	
}

int linearProbing(HashTable HT,int addr,int m,int &time)
{
	int i,addri;
	for(i=1;i<m;i++)
	{
		addri=(addr+i)%m;
		time++; // 统计探测次数
		if(HT.elem[addri].key==INFINITY)
			break; // 不冲突 
	}
	return addri;
}

void createHashTable(HashTable &HT,KeyType KeyData[],int n,int p,int m)
{
	int i,addr,addri,time;
	
	for(i=0;i<n;i++)
	{
		time=1;
		addr=hashFunc(KeyData[i],p); // 求散列地址
		if(HT.elem[addr].key < INFINITY) // 冲突
		{
			addri=linearProbing(HT,addr,m,time); // 处理冲突
			HT.elem[addri].key=KeyData[i];
			HT.elem[addri].time=time;	
		}
		else // 不冲突 
		{
			HT.elem[addr].key=KeyData[i];
			HT.elem[addr].time=time; 
		}
	}
}

int search(HashTable HT,KeyType key,int p,int m)
{
	int i,addr,addri;
	addr=hashFunc(key,p); // 求散列地址
	
	if(HT.elem[addr].key==key)
		return addr; // 查找成功 
	else
		if(HT.elem[addr].key==INFINITY)
			return -1; // 查找失败 
	else
		for(i=1;i<m;i++)
		{
			addri=(addr+i)%m;
			{
				if(HT.elem[addri].key==key)
					return addri; // 查找成功 
				else if(HT.elem[addri].key==INFINITY)
					return -1; // 查找失败 
			}
		}
	return -1;
}

void menu()
{
	int i;
	system("cls"); // 清屏 
	printf("\n");
	printf("%50s\n","散列表的构造和查找\n");
	for(i=0;i<=80;i++)
		printf("*");
	printf("\n");printf("*") ;
	printf("				1 输入数据					*\n");printf("*") ;
	printf("				2 构造散列函数 					*\n");printf("*") ;
	printf("				3 构造散列表					*\n");printf("*") ;
	printf("				4 查看散列表					*\n");printf("*") ;
	printf("				5 散列表查找					*\n");printf("*") ;
	printf("				0 退出 						*\n");printf("*") ;		
//	printf("			\n");
	for(i=0;i<80;i++)
		printf("*");
	printf("\n");
	printf("请输入操作序号:"); 
}

int main()
{
	// KeyType 相当于 int 
	HashTable HT;
	KeyType KeyData[50]; // 存放关键字数据

	int choice,n,m,p,addr;
	KeyType key; // int key
	
	while(1)
	{
		menu();
		scanf("%d",&choice); // 输入你的选择 
		getchar(); // 接受回车键
		switch(choice)
		{
			case 1:
				printf("请输入关键字个数:");
				scanf("%d",&n); // 输入关键字 
				inputData(KeyData,n);
				break;
			case 2:
				calcpm(n,p,m);
				printf("p=%d,m=%d\n",p,m);
				printf("成功构造散列函数.\n");
				break;
			case 3:
				initHashTable(HT,m);
				createHashTable(HT,KeyData,n,p,m);
				printf("成功构造散列表.\n");
				break;
			case 4:
				printf("散列表:\n");
				outputHashTable(HT);
				printf("\n");
				break; 
			case 5:
				printf("请输入要查找的关键字:");
				scanf("%d",&key);
				addr=search(HT,key,p,m);
				if(addr!=-1)
					printf("关键字%d在散列表中找到,地址为%d.\n",key,addr);
				else
					printf("关键字%d不在散列表中.\n",key);
				break;
			case 0:
				return 0;
				break;
			default:
				printf("\n输入错误!");
				break; 
		}
		system("pause");
	}
	return 0; 
}

【实验运行结果】

  • 14
    点赞
  • 101
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值