【数据结构】通讯录查询系统的设计与实现(散列表(哈希表))

1.问题描述:

为某个单位建立一个员工通讯录管理系统,可以方便查询每一个员工的电话与地址。设计散列表存储,设计并实现通讯录查找系统。

 

2.基本要求

(1)每个记录有下列数据项:电话号码、用户名、地址;

(2)从键盘输入各记录,分别以电话号码为关键字建立散列表;

(3)采用二次探测再散列法解决冲突;

(4)查找并显示给定电话号码的记录;

(5)通讯录信息文件保存。

 

3 . 原理

1.哈希表是根据关键码值而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希表,函数f(key)为哈希函数。
2. 二次探测再散列法:若发生冲突,则按照+1²,-1²,+2²,-2²…方式进行探测再散列的方法。

 

4 . 思路

 

此题基本上可以说就是哈希表的简单应用:

①   构建哈希表(需要构造一个哈希函数,确定一个合适的处理冲突的方法)

②   按照电话号码查找并输出

③   将哈希表按序存进文件Output中

 

5 . 代码

 

#include
#include
#include
#include
#define MAXSIZE 50
using namespace std;
int Czy=1;
typedef struct record 
{
	char Number[20];
	char Name[20];
	char Address[20];
}Record;
 
typedef struct Hash
{
	Record *data;
	int cnt;
	int size;
}*HashTable,HashElem;

//哈希函数,将电话号码每一位求和 
int GetHashKey(char ar[])
{
	int len=strlen(ar);
	int key=0;
	for(int i=0;idata[(key+(Czy/2)*(Czy/2))%MAXSIZE].Name[0]==0)
		 		return (key+(Czy/2)*(Czy/2))%MAXSIZE;
		} 
		else if(Czy%2!=0) {
			if((key-(Czy/2)*(Czy/2))<0) continue;//由于是减法,要注意负数不能取模 
			if(table->data[(key-(Czy/2)*(Czy/2))%MAXSIZE].Name[0]==0)
		 		return (key-(Czy/2)*(Czy/2))%MAXSIZE;
		}
	}
	//return -1;
}

//构建哈希表 
void CreateHashTable(HashTable &table,Record *record,int n)
{
	int key;
	for(int i=0;idata[key].Name[0]!=0)
			key=HandleCollision(table,key);
			
		strcpy(table->data[key].Number,record[i].Number);
		strcpy(table->data[key].Name,record[i].Name);
		strcpy(table->data[key].Address,record[i].Address);
	}	
}

//按照电话号码寻找 
int SerchKey(HashTable table,char PhoneNumber[])
{
	int key=GetHashKey(PhoneNumber);
	if(strcmp(table->data[key].Number,PhoneNumber)){
		for(Czy=1;Czydata[(key+(Czy/2)*(Czy/2))%MAXSIZE].Number)){
		 		key= (key+(Czy/2)*(Czy/2))%MAXSIZE;
		 		break;
		 	}
		} 
		else if(Czy%2!=0) {
			if((key-(Czy/2)*(Czy/2))<0) continue;//由于是减法,要注意负数不能取模 
			if(!strcmp(PhoneNumber,table->data[(key-(Czy/2)*(Czy/2))%MAXSIZE].Number)){
		 		key= (key-(Czy/2)*(Czy/2))%MAXSIZE;
				break;
		 	}
			}
		}
	} 
	//if(flag) cout<<"未找到!请重新输入!"<data[key].Name<<" "<data[key].Number<<" "<data[key].Address<data[i].Name[0]!=0)
			fprintf(fp,"%s %s %s\n",table->data[i].Name,table->data[i].Number,table->data[i].Address);	
			//printf("%s %s %s\n",table->data[i].Name,table->data[i].Number,table->data[i].Address);	
		fclose(fp);	
}
 
int main(){
	//定义及初始化 
	Record record[50];
	HashElem table;
	HashTable numbertable;
	numbertable = & table;
	numbertable->data=(Record*)malloc(sizeof(record[0])*MAXSIZE);
	memset(numbertable->data,0,sizeof(record[0])*MAXSIZE);
	numbertable->size=MAXSIZE;
	numbertable->cnt=0;
	int k;
	//输入数据 组数及 各个数据 
    //freopen("Data.txt","r",stdin);
	cin>>k;
	for(int i=0;i>record[i].Number>>record[i].Name>>record[i].Address;
	//创建哈希表 
	CreateHashTable(numbertable,record,k);
	//存入文件中 
	GoToFile(numbertable);
	//输入并寻找PhoneNumber(必须存在表中) 
	char PhoneNumber[20];
	cin>>PhoneNumber;
	cout<<"给定电话号码为:"<

 

 

 

5.注:

 

 

1.哈希函数求出key时,必须取模MAXSIZE,否则key有可能使数组越界!
2.二次探测再散列的时候只定义一个变量Czy即可,既可以区分奇偶(用于区分正负),也可以算出移动大小(+x²,-x²)
3.只有正数能取模%,因此必须加特判if((key-(Czy/2)*(Czy/2))<0)

你可能感兴趣的:(-----数据结构-----)