/*哈希表结构体*/
struct THash {
int key; /*钥匙码*/
char name[10]; /*姓名*/
int depth; /*检索深度*/
};
/*根据钥匙码和哈希根计算哈希地址*/
int GetHashAddress(int key, int root)
{
return key % root;
}/*end GetHashAddress*/
/*冲突地址计算,如果发现地址冲突,则用当前地址和钥匙码、哈希根重新生成一个新地址*/
int GetConflictAddress(int key, int address, int root)
{
int addr = address + key % 5 + 1;
return addr % root;
}/*end GetConflictAddress*/
/*根据字符串生成哈希钥匙码,这里的方法是将串内所有字符以数值形式求累加和*/
int CreateKey(char * name)
{
int key = 0;
unsigned char * n = (unsigned char *)name;
while(*n) key += *n++;
return key;
}/*end CreateKey*/
/*输入一个名字,并返回哈希钥匙码*/
int GetName(char * name)
{
scanf("%s", name);
return CreateKey(name);
}/*end CreateKey*/
/*根据学生人数、长度和哈希根构造哈希表*/
struct THash * CreateNames(int size, int root, int population)
{
int i =0, key = 0, addr = 0, depth = 0; char name[10];
struct THash * h = 0, *hash = 0;
/*哈希根和长度不能太小*/
if(size < root || root < 2) return 0;
/*根据哈希表长度构造一个空的哈希表*/
hash = (struct THash *)malloc(sizeof(struct THash) * size);
/*将整个表清空*/
memset(hash, 0, sizeof(struct THash) * size);
for(i = 0; i < population; i++) {
/*首先产生一个随机的学生姓名,并根据姓名计算哈希钥匙码,再根据钥匙码计算地址*/
key = GetName(name);
addr = GetHashAddress(key, root);
h = hash + addr;
if (h->depth == 0) { /*如果当前哈希地址没有被占用,则存入数据*/
h->key = key;
strcpy(h->name , name);
h->depth ++;
continue;
}/*end if*/
/*如果哈希地址已经被占用了,就是说有冲突,则寻找一个新地址,直到没有被占用*/
depth = 0;
while(h->depth ) {
addr = GetConflictAddress(key, addr, root);
h = hash + addr;
depth ++;
}/*end while*/
/*按照新地址存放数据,同时记录检索深度*/
h->key = key;
strcpy(h->name , name);
h->depth = depth + 1;
}/*next*/
return hash;
}/*end CreateNames*/
/*在哈希表中以特定哈希根查找一个学生的记录*/
struct THash * Lookup(struct THash * hash, char * name, int root)
{
int key = 0, addr = 0; struct THash * h = 0;
/*不接受空表和空名称*/
if(!name || !hash) return 0;
key = CreateKey(name);
addr = GetHashAddress(key, root);
h = hash + addr;
/*如果结果不正确表示按照冲突规则继续寻找*/
while(strcmp(h->name , name)) {
addr = GetConflictAddress(key, addr, root);
h = hash + addr;
if(h->key == 0) return 0;
}/*end while*/
return hash + addr;
}/*end Lookup*/
/*根据一条哈希表记录打印该记录的学生信息*/
void Print(struct THash * record)
{
if (!record) {
printf("【查无此人】/n");
return ;
}/*end if*/
if(record->depth)
printf("【钥匙码】%04d/t【姓名】%s/t【检索深度】%d/n", record->key, record->name, record->depth );
else
printf("【空记录】/n");
/*end if*/
}/*end Print*/
/*打印学生花名册*/
void Display(struct THash * hash, int size)
{
struct THash * h = 0;
if (!hash || size < 1) return ;
printf("学生花名册:/n");
printf("--------------------/n");
for(h = hash; h < hash + size; h++) {
printf("【地址】%d/t", h - hash);
Print(h);
}/*next*/
printf("--------------------/n");
}/*end Display*/
/*主函数,程序入口*/
int main(void)
{
/*哈希表变量声明*/
struct THash * hash = 0, * h = 0;
int cmd = 0; /*命令*/
char name[10]; /*学生姓名*/
/*生成30个学生用的哈希表*/
hash = CreateNames(szHASH, HASH_ROOT, POPULATION);
for(;;) {
printf("哈希表展示:1-显示哈希表;2-检索姓名;其他任意键退出:/n");
cmd = getch();
cmd -= '0';
switch(cmd) {
case 1: Display(hash, szHASH); break;
case 2:
printf("请输入要检索的学生姓名:");
scanf("%s", name);
h = Lookup(hash, name, HASH_ROOT);
printf("【地址】%d/t", h - hash);
Print(h);
break;
default:
free(hash);
return 0;
}/*end case*/
}/*next*/
return 0;
}/*end main*/