哈希表

哈希表(Hash Table)是一种根据关键字直接访问内存存储位置的数据结构。通过哈希表,数据元素的存放位置和数据元素的关键字之间建立起某种对应关系,建立这种对应关系的函数称为哈希函数。


1.哈希函数的构造方法
假设要存储的数据元素个数为n,设置一个长度为m(m≥n)的连续存储单元,分别以每个数据元素的关键字 Ki(0<= i <=n-1) 为自变量,通过哈希函数 hash(Ki) 把 Ki 映射为内存单元的某个地址 hash(ki),并将该数据元素存储在该内存单元中。

从数学的角度来看,哈希函数实际上是关键字到内存单元的映射,因此我们希望用哈希函数通过尽量简单的运算,使得通过哈希函数计算出的哈希地址尽量均匀地被映射到一系列的内存单元中。

构造哈希函数有三个要点:

第一,运算过程要尽量简单高效,以提高哈希表的插入和检索效率;

第二,哈希函数应该具有较好的散列性,以降低哈希冲突的概率;

第三,哈希函数应具有较大的压缩性,以节省内存。
2.什么是冲突?怎么解决冲突?
在构造哈希表时,存在这样的问题,对于两个不同的关键字,通过我们的哈希函数计算哈希地址时却得到了相同的哈希地址

1)开放定址法

它是一类以发生哈希冲突的哈希地址为自变量,通过某种哈希函数得到一个新的空闲内存单元地址的方法(如图),开放定址法的哈希冲突函数通常是一组;
2)链表法

当未发生冲突时,则直接存放该数据元素;当冲突产生时,把产生冲突的数据元素另外存放在单链表中。

电话号码查询系统(哈希表结构)

1.数据类型定义

typedef struct Imfo{char name[20];char num[20];Imfo* nextData;
}Imfo;
typedef struct node{Imfo* nextData;//利用链表法处理冲突
}HashTable[Max_num];

2.哈希函数

int HashFunction(Imfo Data){//哈希函数,构造储存地址int s=0;s=(Data.num[3]-'0')+(Data.num[4]-'0')+(Data.num[5]-'0')+(Data.num[6]-'0')+(Data.num[7]-'0');return s%47;
}

3.初始化空哈希表

int InitHash(HashTable &s){//初始化一个空的哈希表for(int i=0;i<50;i++){s[i].nextData=NULL;//给nextData赋初值,方便设置条件}flag=1;//标志哈希表的建立printf("创建成功!\n");return OK;
}

4.初步储存5个联系人信息

int CreatHash(HashTable &s){//初始化建立一个五位的哈希表if(flag==0){printf("未建立电话簿,请先建立!\n");return ERROR;}printf("请输入~\n");for(int i=0;i<5;i){Imfo*p=(Imfo*)malloc(sizeof(Imfo));scanf("%s",p->name);scanf("%s",p->num);if(addHash(s,p)==-1);else i++;}printf("保存成功!\n");return 1;}

5.用头插法中插入元素

int addHash(HashTable &s,Imfo* Data){//向哈希表中插入元素int k=HashFunction(*Data);Imfo*p=s[k].nextData;while(p){if(!strcmp(p->num,Data->num)){printf("%s %s 该号码已存在!不能录入系统!\n",Data->name,Data->num);return -1;}p=p->nextData;}Data->nextData=s[k].nextData;s[k].nextData=Data;//利用头接法将新节点链如哈希表return OK;
}

6.向哈希表中增加一个元素

int addOneHash(HashTable &s){//向电话簿中添加一个联系人if(flag==0){printf("未建立电话簿,请先建立!\n");return ERROR;}Imfo*q=(Imfo*)malloc(sizeof(Imfo));printf("输入联系人姓名:");scanf("%s",q->name);printf("输入联系人电话:");scanf("%s",q->num);int k=HashFunction(*q);Imfo*p=s[k].nextData;while(p){if(!strcmp(p->num,q->num)){printf("%s %s 该号码已存在!不能录入系统!\n",q->name,q->num);return -1;}p=p->nextData;}q->nextData=s[k].nextData;s[k].nextData=q;printf("添加成功!\n");return OK;
}

7.删除一个元素

int delOneHash(HashTable &s){//删除电话簿中一个联系人if(flag==0){printf("未建立电话簿,请先建立!\n");return ERROR;}Imfo*q=(Imfo*)malloc(sizeof(Imfo));Imfo*t=(Imfo*)malloc(sizeof(Imfo));;printf("输入联系人姓名:");scanf("%s",q->name);printf("输入联系人电话:");scanf("%s",q->num);int k=HashFunction(*q);Imfo*p=s[k].nextData;t=s[k].nextData;if(!t)printf("电话簿没有该联系人!\n");if(!s[k].nextData->nextData&&!strcmp(s[k].nextData->num,q->num)){s[k].nextData=NULL;printf("删除成功!\n");return OK;}//该地址只有一个节点,s[k].nextData->nextData=null,且该节点就是需要删除的节点else if(!s[k].nextData->nextData&&strcmp(s[k].nextData->num,q->num)){printf("电话簿没有该联系人!\n");return ERROR;}//该地址只有一个节点,s[k].nextData->nextData=null,但该节点不是需要删除的节点if(s[k].nextData->nextData&&!strcmp(s[k].nextData->num,q->num)){s[k].nextData=s[k].nextData->nextData;printf("删除成功!\n");return OK;}//该地址不只有一个节点,s[k].nextData->nextData!=null,且该节点就是需要删除的节点while(p){if(!strcmp(p->num,q->num)){break;}t=p;p=p->nextData;}//p为移动节点,用来做判断条件,t为p的前驱节点,用来删除p所用if(!p){printf("电话簿没有该联系人!\n");return ERROR;}else{if(!p->nextData)t->nextData=NULL;//如果需要查找的节点是该链最后一个,直接使t->nextData=NULLelse t->nextData=p->nextData;free(p);//释放pprintf("删除成功!\n");}return OK;
}

8.查询哈希表中的元素

int SearchHash(HashTable s){//根据输入的关键字,查询联系人信息,并打印if(flag==0){printf("未建立电话簿,请先建立!\n");return ERROR;}Imfo T;printf("输入查询的电话号码:");scanf("%s",T.num);int k=HashFunction(T);Imfo*p=s[k].nextData;while(p){if(!strcmp(p->num,T.num)){printf("查找完毕!该联系人信息为:姓名:%s 电话号码:%s \n",p->name,p->num);return OK;}p=p->nextData;}printf("没有找到该联系人\n");return ERROR;
}

完整的代码:

#include <iostream>
#include<stdio.h>
#define OK 1
#define ERROR 0
#include<malloc.h>
#include<string.h>
using namespace std;
#define Max_num 50
typedef struct Imfo{char name[20];char num[20];Imfo* nextData;
}Imfo;
typedef struct node{Imfo* nextData;
}HashTable[Max_num];
int flag=0;//标记电话薄已经建立
int HashFunction(Imfo Data);//哈希函数,构造储存地址
int InitHash(HashTable &s);//初始化一个空的哈希表
int CreatHash(HashTable &s);//初始化建立一个五位的哈希表
int addHash(HashTable &s,Imfo* Data);//向哈希表中插入元素
int addOneHash(HashTable &s);//向电话簿中添加一个联系人
int delOneHash(HashTable &s);//删除电话簿中一个联系人
int SearchHash(HashTable s);//根据输入的关键字,查询联系人信息,并打印
int ModifyHash(HashTable &s);//改变联系人信息(需要先删除旧的信息在添加新的信息)
int showHash(HashTable s);//打印哈希表
int OperateMenu();//建立菜单,提示操作代码
int main()
{HashTable s;int i=1;while(i){switch(OperateMenu()){case 1:InitHash(s);break;case 2:CreatHash(s);break;case 3:showHash(s);break;case 4:SearchHash(s);break;case 5:addOneHash(s);break;case 6:delOneHash(s);break;case 7:ModifyHash(s);break;case 0:i=0;}}
}int InitHash(HashTable &s){//初始化一个空的哈希表for(int i=0;i<50;i++){s[i].nextData=NULL;//给nextData赋初值,方便设置条件}flag=1;//标志哈希表的建立printf("创建成功!\n");return OK;
}
int HashFunction(Imfo Data){//哈希函数,构造储存地址int s=0;s=(Data.num[3]-'0')+(Data.num[4]-'0')+(Data.num[5]-'0')+(Data.num[6]-'0')+(Data.num[7]-'0');return s%47;
}
int CreatHash(HashTable &s){//初始化建立一个五位的哈希表if(flag==0){printf("未建立电话簿,请先建立!\n");return ERROR;}printf("请输入~\n");for(int i=0;i<5;i){Imfo*p=(Imfo*)malloc(sizeof(Imfo));scanf("%s",p->name);scanf("%s",p->num);if(addHash(s,p)==-1);else i++;}printf("保存成功!\n");return 1;}
int addHash(HashTable &s,Imfo* Data){//向哈希表中插入元素int k=HashFunction(*Data);Imfo*p=s[k].nextData;while(p){if(!strcmp(p->num,Data->num)){printf("%s %s 该号码已存在!不能录入系统!\n",Data->name,Data->num);return -1;}p=p->nextData;}Data->nextData=s[k].nextData;s[k].nextData=Data;//利用头接法将新节点链如哈希表return OK;
}
int SearchHash(HashTable s){//根据输入的关键字,查询联系人信息,并打印if(flag==0){printf("未建立电话簿,请先建立!\n");return ERROR;}Imfo T;printf("输入查询的电话号码:");scanf("%s",T.num);int k=HashFunction(T);Imfo*p=s[k].nextData;while(p){if(!strcmp(p->num,T.num)){printf("查找完毕!该联系人信息为:姓名:%s 电话号码:%s \n",p->name,p->num);return OK;}p=p->nextData;}printf("没有找到该联系人\n");return ERROR;
}
int addOneHash(HashTable &s){//向电话簿中添加一个联系人if(flag==0){printf("未建立电话簿,请先建立!\n");return ERROR;}Imfo*q=(Imfo*)malloc(sizeof(Imfo));printf("输入联系人姓名:");scanf("%s",q->name);printf("输入联系人电话:");scanf("%s",q->num);int k=HashFunction(*q);Imfo*p=s[k].nextData;while(p){if(!strcmp(p->num,q->num)){printf("%s %s 该号码已存在!不能录入系统!\n",q->name,q->num);return -1;}p=p->nextData;}q->nextData=s[k].nextData;s[k].nextData=q;printf("添加成功!\n");return OK;
}
int delOneHash(HashTable &s){//删除电话簿中一个联系人if(flag==0){printf("未建立电话簿,请先建立!\n");return ERROR;}Imfo*q=(Imfo*)malloc(sizeof(Imfo));Imfo*t=(Imfo*)malloc(sizeof(Imfo));;printf("输入联系人姓名:");scanf("%s",q->name);printf("输入联系人电话:");scanf("%s",q->num);int k=HashFunction(*q);Imfo*p=s[k].nextData;t=s[k].nextData;if(!t)printf("电话簿没有该联系人!\n");if(!s[k].nextData->nextData&&!strcmp(s[k].nextData->num,q->num)){s[k].nextData=NULL;printf("删除成功!\n");return OK;}//该地址只有一个节点,s[k].nextData->nextData=null,且该节点就是需要删除的节点else if(!s[k].nextData->nextData&&strcmp(s[k].nextData->num,q->num)){printf("电话簿没有该联系人!\n");return ERROR;}//该地址只有一个节点,s[k].nextData->nextData=null,但该节点不是需要删除的节点if(s[k].nextData->nextData&&!strcmp(s[k].nextData->num,q->num)){s[k].nextData=s[k].nextData->nextData;printf("删除成功!\n");return OK;}//该地址不只有一个节点,s[k].nextData->nextData!=null,且该节点就是需要删除的节点while(p){if(!strcmp(p->num,q->num)){break;}t=p;p=p->nextData;}//p为移动节点,用来做判断条件,t为p的前驱节点,用来删除p所用if(!p){printf("电话簿没有该联系人!\n");return ERROR;}else{if(!p->nextData)t->nextData=NULL;//如果需要查找的节点是该链最后一个,直接使t->nextData=NULLelse t->nextData=p->nextData;free(p);//释放pprintf("删除成功!\n");}return OK;
}
int ModifyHash(HashTable &s){//改变联系人信息(需要先删除旧的信息在添加新的信息)if(flag==0){printf("未建立电话簿,请先建立!\n");return ERROR;}if(!delOneHash(s))return ERROR;addOneHash(s);return OK;
}
int showHash(HashTable s){//打印哈希表if(flag==0){printf("未建立电话簿,请先建立!\n");return ERROR;}int c=1;printf("电话号码全部信息为:\n");for(int i=0;i<50;i++){if(s[i].nextData!=NULL){printf("%d:姓名:%s 电话号码:%s\n",c++,s[i].nextData->name,s[i].nextData->num);Imfo*p=s[i].nextData->nextData;while(p){printf("%d:姓名:%s 电话号码:%s\n",c++,p->name,p->num);p=p->nextData;}}
}return OK;
}
int OperateMenu(){//建立菜单,提示操作代码int num;printf("                           *---------------------------------------*\n");printf("                                   1:创建一个空的电话薄!\n");printf("                                   2:初始化输入5个信息!\n");printf("                                   3:打印电话薄的全部信息!\n");printf("                                   4:查询联系人信息!\n");printf("                                   5:添加一个联系人信息!\n");printf("                                   6:删除一个联系人信息!\n");printf("                                   7:修改联系人的电话信息!\n");printf("                                   0:选择其他指令退出系统!\n");printf("                           *---------------------------------------*\n");scanf("%d",&num);for(int i=0;;i++){if(num<0||num>7){printf("指令错误!请输入正确的指令~\n");return -1;}else if(num==0){return num;break;}else if(num==1){return num;break;}else if(num==2){return num;break;}else if(num==3){return num;break;}else if(num==4){return num;break;}else if(num==5){return num;break;}else if(num==6){return num;break;}else if(num==7){return num;break;}}
}

电话号码查询系统(数据结构之哈希表)相关推荐

  1. C语言电话号码查询系统[2023-01-16]

    C语言电话号码查询系统[2023-01-16] 一.课程设计(论文)题目 电话号码查询系统 说明: 设计哈希表,实现电话号码查询系统. 二.本次课程设计(论文)应达到的目的 C语言.面向对象程序设计. ...

  2. 【数据结构课程设计报告】电话号码查询系统(Java实现)

    数据结构课程设计报告 电话号码查询系统 数据结构课程设计报告 一.需求分析 二.系统功能划分及设计 1.存储结构设计 2.系统的功能架构设计 3.模块设计 3.代码实现 一.需求分析 问题描述:路径规 ...

  3. 哈希表实现电话号码查询系统(c++)

    问题描述:设计哈希表实现电话号码查询系统,实现下列功能: (1) 假定每个记录有下列数据项:电话号码.用户名.地址. (2) 一是从数据文件old.txt(自己现行建好)中读入各项记录,二是由系统随机 ...

  4. 数据结构个人电话号码查询系统实验报告

    实验目的及要求 目的:通过设计一个<个人电话号码查询系统>,进一步熟悉一些二叉树的概念.以及基本知识和技能,利用所学的基本知识和技能解决简单的面向对象的程序设计问题.实现根据用户输入的信息 ...

  5. 设计散列表实现通讯录查找系统_[源码和文档分享]利用哈希表实现电话号码查询系统...

    第一章 需求分析 1.1 问题描述 设计一个电话号码查询系统,为来访的客⼈提供各种信息查询服务. 1.2 基本要求 设计每个记录有下列数据项:电话号码.用户名.地址 从键盘输入个记录,分别以电话号码和 ...

  6. 《程序设计综合设计》课程设计--电话号码查询系统

    2.问题描述 1.设每个记录有下列数据项:电话号码.用户名.地址: 2.从键盘输入各记录,分别以电话号码和用户名为关键字建立哈希表: 3.查找并显示给定电话号码的记录: 4.查找并显示给定用户名的记录 ...

  7. 输入手机号查询信息C语言,简单个人电话号码查询系统.doc

    课程设计任务书 2011-2012学年第1学期 电子与信息工程系 专业 班级 课程设计名称: 数据结构课程设计 设计题目: 简单个人电话号码查询系统 完成期限:自2012 年 1月2日至2012 年 ...

  8. 图书馆管理系统(C、数据结构、哈希表、文件IO)

    目录 技术路线 实现效果展示 ​程序主体 1.头文件部分 2.自定义函数定义部分 3.main函数部分 注意 技术路线 数据结构.哈希表.文件IO 通过C语言进行程序设计,有用到数据结构中的哈希表,通 ...

  9. 【数据结构】哈希表的概念及应用

    [数据结构]哈希表的概念及应用 前言 1.写出哈希表的基本概念 2.列出常用的哈希函数构造方法,并阐述各自的特点. 直接定址法 除留余数法 数字分析法 其他构造整数关键字的哈希函数的方法: 平方取中法 ...

最新文章

  1. VS2005编译QT4.8.2
  2. BERT:代码解读、实体关系抽取实战
  3. nginx安装配置http、tcp代理
  4. 求圆和椭圆上任意角度的点的坐标
  5. 傻子都能看懂的马拉车Manacher
  6. Python序列循环移位的3种方法
  7. 生活杂记 - 丢东西
  8. “sudo: apt-get:找不到命令”的解决方法
  9. 初窥JQuery-Jquery简介
  10. JavaSE基础———对象数组和集合Collection
  11. ORB SLAM 2 demo 复现
  12. 洛谷试炼场 普及常见模板
  13. 风景照片转水彩画效果PS动作
  14. html5小白——html5基础(简单个人博客模板)
  15. 《有效的单元测试》第三章
  16. Windows 7 一键恢复 - 联想拯救系统
  17. mysql 本月第一天_mysql日期 获取本月第一天 获取下个月的第一天
  18. Android计步器算法实现
  19. 笔记本电脑键盘失灵拯救方法总结
  20. mysql jdbc驱动 批量更新_jdbc批量插入,删除,更新

热门文章

  1. 牛逼吧,微信状态竟然也能赚钱
  2. 场效应管 | N-mos内部结构详解
  3. 如何创建小程序商店?
  4. 【安徽省机器人大赛单片机与嵌入式赛道竞赛】C平台作品
  5. jffs2制作与烧写
  6. 使用jupyter进行数据预处理-数据清洗
  7. 商场使用室内地图的5大好处
  8. Lombok will not run during this compilation
  9. CPU的工作电压(核心电压,I/O电压)
  10. steam搬砖项目讲解