/* (1)设计哈希表,该表应能够容纳50个英文单词。
(2)对该哈希表进行查询,实现对特定单词的快速查询,并显示经过的节点内容 已经发到你邮箱里了enochwills@ */ #include <conio.h> #include <memory.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define szNAME 80 #define HASH_ROOT 47 /*用于计算哈希地址的随机数*/ #define szHASH 50 /*哈希表总长度*/ #define POPULATION 30 /*学生总数*/ /*哈希表结构体*/ 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*/。