文章目录
- 核心代码
- 链表节点定义
- 链地址法处理冲突
- 查询函数
- 完整代码下载
核心代码
哈希表使用「链地址法」解决地址冲突的方式,其数据结构就采用 数组+链表 ,数组的每一个元素都是一个链表节点,当地址冲突时,就往当前地址的链表末尾追加,这里可以把上一篇文章「 线性探测法 」稍作修改即可:
链表节点定义
typedef struct HashNode //哈希表
{char *name; //名字的拼音int key; //拼音所对应的ASCII总和,即关键字int si; //查找长度struct HashNode *next; // 指向下一节点的指针
} HashNode;
链地址法处理冲突
void CreateHash()
{ //建立哈希表for (i = 0; i < HASH_LEN; i++) //清空哈希表,未经此操作将储存空数据{HashNode *node = &hashTable[i];node->name = "\0";node->key = 0;node->si = 0;node->next = NULL;}for (i = 0; i < NAME_LEN; i++){int si = 1; // 查找长度默认为1int adr = (nameTable[i].hashCode) % P; //除留余数法H(name)=name%P,除数为P=47HashNode *p = &hashTable[adr]; //将指针指向当前节点if (p->si != 0) //如果当前节点不为空,说明冲突了,使用「链地址法」处理冲突{si++;while (p->next != NULL) //找到当前地址的最后一个节点{p = p->next;si++;}p->next = (HashNode *)malloc(sizeof(HashNode)); // 在最后一个节点的下一个追加节点p = p->next; // 再将指针指向追加的这个节点}// 将姓名表当前的节点存进p指针指向的hash表的节点中p->key = nameTable[i].hashCode;p->name = nameTable[i].name;p->si = si;p->next = NULL;}
}
查询函数
void FindName()
{char name[20] = {0};int hashCode = 0, si = 1;printf("\n请输入想要查找的姓名的拼音:");scanf("%s", name);getchar();hashCode = gethashCode(name); //求出姓名的拼音所对应的ASCII作为关键字int adr = hashCode % P; //除留余数法去地址int j = 0;// 如果hash地址为空,则直接认为不存在if (hashTable[adr].key == 0){printf("\n没有想要查找的人!\n");return;}// 如果hashCode和name都相等if (hashTable[adr].key == hashCode && 0 == strcmp(hashTable[adr].name, name)){printf("\n姓名:%s 关键字:%d 地址:%d 查找长度为: 1\n", hashTable[adr].name, hashCode, adr);}// 如果不相等,则进行从当前地址遍历链表else{int currAddr = adr;HashNode *p = &hashTable[adr];boolean hasFind = FALSE; // 标志:标记是否查到// 遍历当前地址的链表do{si++; // 查找长度+1if (p->next != NULL){p = p->next;}// 如果找到,直接break跳出循环if (p->key == hashCode && 0 == strcmp(p->name, name)){hasFind = TRUE;printf("\n姓名:%s 关键字:%d 地址:%d 查找长度为:%d\n", p->name, hashCode, adr, si);break;}} while (p->next != NULL);if (!hasFind){printf("\n没有想要查找的人!\n");return;}}
}
完整代码下载
CSDN:https://download.csdn.net/download/weixin_44155115/85881567