题目:
为班级30个人的姓名设计一个哈希表,假设姓名用汉语拼音表示。要求用除留余数法构造哈希函数,用线性探测再散列法处理冲突。
#include<stdio.h>
#include<stdlib.h>
#define NULLKEY 0 /*代表空记录的关键字值*/
#define m 50 /*代表哈希表长度*/
#define n 47 /*代表哈希表长度的最大素数*/
#define x 30 /*代表存入哈希表中的总数*/
typedef int KeyType; /*假设关键字类型*/
typedef struct
{
KeyType key;
}RecordType;
typedef RecordType HashTable[m]; /*定义哈希表*/
void InitHash(HashTable ht){
int i;
for(i=0;i<50;i++){
ht[i].key=NULLKEY;
}
}
void CreatHash(HashTable ht){
char ch;
int i=0,all=0,z=0; //all计算姓名中大写字母求和 z控制a[]数组的存放位置 i控制b[]数组的存放位置(计算存放者的姓名有几个字)
int j;
int a[x]={};
/*b[5]数组:短暂存放一个人的名字中首字母大写的数值——通过此数组,将一个人的名字首大写字母加起来求和——例:王芳——b[0]=W,b[1]=F,b[0]+b[1]=29存放在a[x]数组中*/
int b[5]={};
while((ch=getchar())!='\n'){
if(ch!=' '){
if(ch>='A'&&ch<='Z'){
b[i]=(int)ch-64; //将大写字母转为26字母表中的位置
i++; //i——计算该姓名是几个字
}
}else{
for(j=0;j<i;j++){
all+=b[j];
}
a[z]=all;
all=0; //重置,防止累加出现问题
i=0; //重置,防止累加出现问题
z++;
}
}
/*因为最后一组名字紧跟'\n'(换行符)而不是' '(空格),因此最后一组姓名并没有相加并且存放在a[]数组中,因此需要单独存放*/
for(j=0;j<i;j++){
all+=b[j];
}
a[z]=all;
/*将数组a[]开始依次转换为哈希表中的数字*/
for(i=0;i<30;i++){
j=a[i]%n;
while(ht[j].key!=NULLKEY){
j++;
}
ht[j].key=a[i];
}
}
void Travel(HashTable ht){
int i;
printf("哈希表:\n");
for(i=0;i<m;i++){
if(i==10||i==20||i==30||i==40||i==50){
printf("\n");
}
printf("%-3d ",ht[i].key);
}
printf("\n");
}
void SearchHash(HashTable ht){
int data,i,j;
printf("输入您想查找的数:");
scanf("%d",&data);
j=data%n;
if(ht[j].key==NULLKEY){
printf("哈希表中没有存在这个数!\n");
}else if(ht[j].key==data){
for(j;j<m;j++){
if(ht[j].key==data){
printf("该数在哈希表中第 %d 号位置\n",j);
}
}
}else{
while(ht[j].key!=data){
if(j<m){
j++;
}else{
printf("哈希表中没有存在这个数!\n");
break;
}
}
for(j;j<m;j++){
if(ht[j].key==data){
printf("该数在哈希表中第 %d 号位置\n",j);
}
}
}
}
int main(){
HashTable ht;
InitHash(ht);
CreatHash(ht);
Travel(ht);
SearchHash(ht);
system("pause");
return 0;
}
InitHash函数:将哈希表中的所有位置进行初始化
CreateHash函数:从键盘依次输入姓名存放在a[ ]数组中,将数组中的数字依次放置在哈希表中
TravelHash函数:将哈希表按照10个数字为一行进行打印
SearchHash函数:寻找你想找的数字在哈希表中的位置
1.我们首先用数组先创建学生姓名首字母的数字之和(例如:王芳—WF——WF在字母表的位置为,23-6,所以数组中存放23+6的和=29),再将这些数字取余所建立哈希表长度的最大素数得到他们在哈希表的对应位置。
2.算出在哈希表中对应位置后,要判断该位置是否已存放数字。如果未存放数字,即可存放当前算出的该数字;若已经存放数字,则需要用线性探测再散列法处理冲突,找到未存放的位置进行存放,直到数组所有数字都应存放进哈希表为止。
3.查找数字时,在数组中多次出现的数字也同样会在哈希表中多次出现;
4.算出数字在哈希表的位置时,此时在哈希表的位置中,该数字不一定存放在该位置,由于发生冲突有可能在该位置的后面。
运行实例:
因为47在数组中多次出现,所以肯定会出现冲突问题,因此运用线性探测再散列法解决冲突后,47该数字存放位置必定不唯一
因为44在数组中只出现过一次,在哈希表中只有一个位置符合
因为88未在数组中出现,因此也不可能在哈希表中出现