基于散列表的电话号码查询系统 完整版
数据结构毕业设计论文题目整理

数据结构课程设计题目1.飞机订票系统(限1 人完成)(顺序或链式存储)任务:通过此系统可以实现如下功能:录入:可以录入航班情况(数据可以存储在一个数据文件中,数据结构、具体数据自定)查询:可以查询某个航线的情况(如,输入航班号,查询起降时间,起飞抵达城市,航班票价,票价折扣,确定航班是否满仓);可以输入起飞抵达城市,查询飞机航班情况;订票:(订票情况可以存在一个数据文件中,结构自己设定)可以订票,如果该航班已经无票,可以提供相关可选择航班;退票:可退票,退票后修改相关数据文件;客户资料有姓名,证件号,订票数量及航班情况,订单要有编号。
修改航班信息:当航班信息改变可以修改航班数据文件要求:根据以上功能说明,设计航班信息,订票信息,客户信息的存储结构,设计程序完成功能;2.宿舍管理查询软件(限1 人完成)任务:为宿舍管理人员编写一个宿舍管理查询软件, 程序设计要求:采用交互工作方式建立数据文件,包括学生信息、宿舍信息、住宿信息,学生信息按关键字(姓名、学号)进行排序(排序方法自选,不能相同);查询: (用二分查找实现以下操作)按姓名查询按学号查询(用顺序查找实现以下操作)按房号查询3.校园导航问题(限1 人完成)设计要求:设计你的学校的平面图,至少包括10个以上的场所,每两个场所间可以有不同的路,且路长也可能不同,找出从任意场所到达另一场所的最佳路径(最短路径)。
要求:能增加场所4.图书借阅管理系统(限1 人完成)(顺序或链式存储)主要分为两大功能:1)图书管理(增加图书、查询图书、删除图书、图书借阅、还书);2)会员管理(增加会员、查询会员、删除会员、借书信息);5.学生成绩管理(限1 人完成)(顺序或链式存储)包括:课程信息,学生信息等;能增加课程或学生。
实现功能:输入、输出、插入、删除、查找、显示、保存、排序、退出。
6.活期储蓄帐目管理(限1 人完成)活期储蓄处理中,储户开户、销户、存入、支出活动频繁,系统设计要求:1)能比较迅速地找到储户的帐户,以实现存款、取款记账;2)能比较简单,迅速地实现插入和删除,以实现开户和销户的需要。
散列表实现电话号码查找系统

printf(" haha !!%s\n",person[j].name);
printf("input person %d tel:",i+1);
scanf("%d",&person[j].tel);
scanf("%d",&choice);
}
else{
switch(choice){
case 1:INPUT();break;
case 2:DISPLAY();break;
case 3:SORT();break;
case 0:EXIT(0);break;
}
else{ printf("apple!\n");
for(j=y+1;j<=y+5;j++){
if(person[j].name[0]=='\0'){
strcpy(person[j].name,a);//把字符数组a复制给散列表;
y=x%29;
if(person[y].name!='\0'&&person[y].tel!='\0'&&person[y].addr!='\0'){ //判断是否有信息;
if(strcmp(person[y].name,a)==0){
{
printf(" 1---input telephoto infoumantion.\n");
printf(" 2---display all students informantion.n\n");
(完整word版)哈希表实现电话号码查询系统

(完整word版)哈希表实现电话号码查询系统哈希表实现电话号码查询系统一目的利用《数据结构》课程的相关知识完成一个具有一定难度的综合设计题目,利用C/C++语言进行程序设计,并规范地完成课程设计报告。
通过课程设计,巩固和加深对线性表、栈、队列、字符串、树、图、查找、排序等理论知识的理解;掌握现实复杂问题的分析建模和解决方法(包括问题描述、系统分析、设计建模、代码实现、结果分析等);提高利用计算机分析解决综合性实际问题的基本能力。
二需求分析1、程序的功能1)读取数据①读取原电话本存储的电话信息。
②读取系统随机新建电话本存储的电话信息。
2)查找信息①根据电话号码查询用户信息。
②根据姓名查询用户信息。
3)存储信息查询无记录的结果存入记录文档。
2、输出形式1)数据文件“old.txt”存放原始电话号码数据。
2)数据文件“new.txt”存放有系统随机生成的电话号码文件。
3)数据文件“out.txt”存放未查找到的电话信息。
4)查找到相关信息时显示姓名、地址、电话号码。
3、初步测试计划1)从数据文件“old.txt”中读入各项记录,或由系统随机产生各记录,并且把记录保存到“new.txt”中。
2)分别采用伪随机探测再散列法和再哈希法解决冲突。
3)根据姓名查找时显示给定姓名用户的记录。
4)根据电话号码查找时显示给定电话号码的用户记录。
5)将没有查找的结果保存到结果文件Out.txt中。
6)系统以菜单界面工作,运行界面友好,演示程序以用户和计算机的对话方式进行。
三概要设计1、子函数功能int Collision_Random(int key,int i)//伪随机数探量观测再散列法处理冲突void Init_HashTable_by_name(string name,string phone,string address) //以姓名为关键字建立哈希表int Collision_Rehash(int key,string str)//再哈希法处理冲突void Init_HashTable_by_phone(string name,string phone,string address) //以电话号码为关键字建立哈希表void Outfile(string name,int key)//在没有找到时输出未找到的记录,打开文件out.txt并将记录储存在文档中void Outhash(int key)//输出哈希表中的记录void Rafile()//随机生成数据,并将数据保存在new.txtvoid Init_HashTable(char*fname,int n)//建立哈希表int Search_by_name(string name)//根据姓名查找哈希表中的记录int Search_by_phone(string phone)//根据电话号码查找哈希表中的记录2、函数调用图四详细设计1、主函数流程图2、“伪随机探测再散列处理冲突”伪代码若对应位置上已经存在其他数据,则新的关键字=(原关键字+伪随机数)%哈希表长。
(完整word版)哈希表实现电话号码查询报告

《数据结构》课程设计报告书题目:哈希表存储的电话号码查询专业:学号:学生姓名:指导教师:完成日期:目录1.实训题目………………………………………………1。
1实训要求…………………………………………. 1。
2需求分析…………………………………………。
2.系统设计………………………………………………2。
1总体设计………………………………………….. 2。
2详细设计…………………………………………。
2。
2。
1程序头文件…………………………………。
2。
2.2学生信息类及哈希表类……………………。
.2.2.3主函数流程…………………………………。
. 3。
系统实现………………………………………………。
3.1编码………………………………………………。
3。
2测试………………………………………………。
4。
归纳总结……………………………………………….4.1实训中遇到的问题以及解决办法………………。
.4.2感想和心得体会…………………………………。
5。
参考资料………………………………………………1.实训题目1.1实训要求⏹设每个记录有以下数据项:用户名、电话、地址;⏹从键盘输入各记录,以电话号码为关键字建立哈希表;⏹采用链地址法方法解决冲突;⏹能够查找并显示给定电话号码的相关记录。
1。
2需求分析本次实验要求采用哈希表完成信息的查找和储存,哈希表即为散列表。
本程序采用学生信息管理为例,设每个学生有电话号码,学生姓名,家庭住址三个信息。
通过建立哈希表储存信息,信息储存在节点中,并通过以电话号码为关键字完成查找,并显示出该学生的姓名,电话号码以及家庭住址.当哈希表中的数据与输入的数据发生冲突时,使用节点向后移一位的方法来解决冲突。
2.系统设计2.1总体设计本系统通过设计学生信息类和哈希表类来完成整个系统。
通过学生信息类实现从键盘输入学生的姓名,电话号码以及家庭地址.将学生的信息储存在建立的哈希节点内,通过多个链表保存,相同信息的保存在同一个节点内。
数据结构课程设计-通讯录查询系统的设计与实现

通讯录查询系统的设计与实现一、需求分析1、问题描述为某个单位建立一个员工通讯录管理系统,可以方便查询每一个员工的电话与地址。
设计散列表存储,设计并实现通讯录查找系统。
2、基本要求a.每个记录有下列数据项:电话号码、用户名、地址;b.从键盘输入各记录,分别以电话号码为关键字建立散列表;c.采用二次探测再散列法解决冲突;d.查找并显示给定电话号码的记录;e.通讯录信息文件保存。
二、概要设计1.数据结构本程序需要用到两个结构体,分别为通讯录message以及哈希表HxList2.程序模块本程序包含两个模块,一个是实现功能的函数的模块,另一个是主函数模块。
系统子程序及功能设计本系统共有三个子程序,分别是:int Hx(long long key,int data)//哈希函数void BulidHx(HxList &L)//建立通讯录int Search(HxList &L)//查找3.各模块之间的调用关系以及算法设计主函数调用BulidHx以及Search函数。
函数BulidHx调用函数Hx。
三、详细设计1.数据类型定义typedef struct{char *name;char *add;long long phonenumber;}message;typedef struct{message *list;int number;//记录数}HxList;2.系统主要子程序详细设计a. 建立通讯录void BulidHx(HxList &L)//建立通讯录{FILE *f = fopen("E:\\tongxunlu.txt", "w");char buf[20]={0},str[20]={0};long long key;cout<<"输入要建立的记录数:";cin>>L.number;L.number+=1;L.list=new message[L.number];//分配哈希表的存储空间for(int i=0;i<L.number;i++){L.list[i].phonenumber=-1;}L.list[L.number-1].name=NULL;L.list[L.number-1].add=NULL;cout<<"输入记录信息(电话号码用户名地址)"<<endl; for(int i=0;i<L.number-1;i++){cin>>key>>buf>>str;int pose=Hx(key,L.number);//获取理论上的存储位置if(L.list[pose].phonenumber==-1){}else{//用二次探测再散列法解决冲突//1^2 -1^2 2^2 -2^2int di,count=1;xunhuan: if(count%2==0)di=-(count/2)*(count/2);elsedi=((count/2)+1)*((count/2)+1);int site=Hx(key+di,L.number);if(site>=0){if(L.list[site].phonenumber==-1){pose=site;}else{count++;goto xunhuan;}}else{site=L.number-abs(site);if(L.list[site].phonenumber==-1){pose=site;}else{count++;goto xunhuan;}}}L.list[pose].phonenumber=key;fprintf(f,"%lld",key);fprintf(f," ");L.list[pose].name=new char[strlen(buf)+1];strcpy(L.list[pose].name,buf);fprintf(f,"%s",buf);fprintf(f," ");L.list[pose].add=new char[strlen(str)+1];strcpy(L.list[pose].add,str);fprintf(f,"%s",str);fprintf(f,"\n");}}b.查找int Search(HxList &L)//查找{long long key;cout<<"输入要查找记录的关键字(电话号码):";cin>>key;int pose=Hx(key,L.number);//计算理论上的位置if(L.list[pose].phonenumber==key){}else{int count=1,di;//二次探测再散列,查找xunhuan: if(count%2==0){di=-(count/2)*(count/2);}else{di=((count/2)+1)*((count/2)+1);}int site=Hx(key+di,L.number);if(site>=0){if(L.list[site].phonenumber==key){pose=site;}else{count++;if(L.list[site].phonenumber==-1){cout<<"没有找到"<<endl;return -1;//没有找到}goto xunhuan;}}else{site=L.number-abs(site);if(L.list[site].phonenumber==key){pose=site;}else{count++;if(L.list[site].phonenumber==-1){cout<<"没有找到"<<endl;return -1;//没有找到}goto xunhuan;}}}if(L.list[pose].phonenumber==key){cout<<"电话号码\t"<<"用户名\t"<<"地址"<<endl;cout<<L.list[pose].phonenumber<<"\t"<<L.list[pose].name<<"\t"<<L.list[pose].add< <endl;return pose;}}四、测试与分析1.显示主菜单,运行程序可以显示出如下界面。
散列表的设计与实现

散列表的设计与实现1程序最终实现结果及分析散列表实现的电话查找系统。
各功能模块的详细介绍。
1.1功能模块1实现结果1.1.1详细设计模块名称:密码登录验证功能说明:该模块主要是通过密码进入主菜单密码输入有三次机会,三次输入错误自动结束程序。
输入参数:密码为任一字符串。
输出:密码正确提示进入系统。
不正确提示错误。
1.1.2界面设计及测试结果1.2.1详细设计模块名称:一次性添加所有用户信息功能说明:该模块包括选择要添加的个数。
先输入个数之后再输入各用户信息。
输入参数:依次为:用户名,电话号码,地址。
各个参数都是字符串类型。
1.2.2界面设计及测试结果1.3.1详细设计模块名称:显示一次性添加的所有用户信息功能说明:该模块主要是读取用户一次性输入的所有用户信息。
输出:按用户名,电话号码,地址的顺序显示一行记录。
输出各条记录。
1.3.2界面设计及测试结果1.4功能模块4实现结果1.4.1详细设计模块名称:以用户名建立哈希表(链地址解决冲突)功能说明:该模块用于以姓名建立哈希表并且用链地址解决冲突。
输入参数:按用户名,电话号码,地址的依次顺序在记录数组中提到。
各个参数都为字符串类型。
输出:字符串消息提示。
所调用其他功能构件及被调用的其他功能构件:我们调用了hashUser类(以用户名建立散列表的哈希类)的put方法,逐条放入记录建立散列表。
1.4.2界面设计及测试结果1.5功能模块5实现结果1.5.1详细设计模块名称:以电话号码建立哈希表(链地址解决冲突) 。
功能说明:该模块用于以电话号码建立哈希表并且用链地址解决冲突。
输入参数:按电话号码,用户名,地址的依次顺序在记录数组中提到。
各个参数都为字符串类型。
输出:字符串消息提示。
所调用其他功能构件及被调用的其他功能构件:我们调用了hashTel类(以电话号码建立散列表的哈希类)的put方法,逐条放入记录建立散列表。
1.6功能模块6实现结果1.6.1详细设计模块名称:查找并显示给定用户名的记录功能说明:该模块以用户名查找信息在执行该步骤之前先执行(3).输入参数:用户名,类型为字符串。
数据结构课程设计-利用散列表做一个电话号码查找系统

数据结构课程设计-利⽤散列表做⼀个电话号码查找系统【基本要求】(1)设每个记录有下列数据项:电话号码、⽤户名、地址;(2)从键盘输⼊各记录,分别以电话号码和⽤户名为关键字建⽴散列表;(3)采⽤⼀定的⽅法解决冲突;(4)查找并显⽰给定电话号码的记录;(5)查找并显⽰给定⽤户名的记录。
【选做内容】(1)系统功能的完善;(2)设计不同的散列函数,⽐较冲突率; (3)在散列函数确定的前提下,尝试各种不同类型处理冲突的⽅法,考察平均查找长度的变化。
⽤的C++开发,基本实现了3种哈希函数+3种解决冲突的⽅法。
因为要求同时有姓名散列与按号码散列,所以⽤了flag标记每次的散列类型,针对不同的要求对散列函数做了个别优化。
哈希表类的结构如下1class HashTable{2public:3 HashTable(int size = MAXSIZE-1);4 ~HashTable(){ delete[]E; delete[]tag; delete[]E2; delete[]tag2; }5int hash1(string name, int flag);//哈希函数1 除数求余法6int hash2(string tel);//哈希函数2 折叠法7int hash3(string tel);//哈希函数3 数字分析法8int solve1(int hashVal, int flag);//线性探测法解决冲突9int solve2(int hashVal, int flag);//⼆次探测法解决冲突10 Node* solve3(int hashVal, int flag);//拉链法解决冲突11 User input();//往电话薄中添加⽤户12void creat(int flag); //创建散列表13void show(int flag); //列出电话薄所有元素14void search(int flag,string at); //搜索指定⽤户15void searchByNode(int flag, string at); //拉链法搜索指定⽤户16void insert(int flag, User newUser); //插⼊17void del(int flag, string by);//删除18void save(int flag);//将电话薄保存⾄本地⽂件19int length; //要创建的电话本长度20 Node** ht;21private:22 User* E; //⽤户数组按姓名散列23 User* E2; //⽤户数组2 按电话号码散列24int* tag; //标记散列表1每个桶的存储状态 0为空 1为实25int* tag2;//标记散列表2每个桶的存储状态26int flag; //1表⽰是按姓名 2表⽰按电话号码新建的哈希表27int maxSize; //哈希表最⼤长度28int f;//⽐例因⼦主要⽤于折叠法29 };View CodeUser类的结构class User{public:string name;string tel;string address;bool operator==(const User&target){if (this->name == &&this->address == target.address&&this->tel == target.tel)return true;elsereturn false;}};哈希函数1int HashTable::hash1(string name,int flag) //除留求余法{int hashValue; long a = 0;switch (flag){case1:for (int i = 0; i < name.length(); i++)a += int(name[i]);hashValue = a%maxSize;break;case2:int temp = atof(name.c_str());hashValue = temp%maxSize;break;}return hashValue;};哈希函数2int HashTable::hash2(string tel) //折叠法--移位法{int hashValue;int temp; //移位法求和temp = atof(tel.substr(0, 3).c_str()) + atof(tel.substr(3, 3).c_str())+ atof(tel.substr(6, 3).c_str()) + atof(tel.substr(9, 2).c_str());//取计算之后的数的最后三位if (temp >= 999){char p[10];sprintf(p, "%d", temp);string lastThree = p;lastThree = lastThree.substr(lastThree.length() - 3, 3);hashValue = atof(lastThree.c_str());return hashValue;}hashValue = temp;return hashValue;};哈希函数3int HashTable::hash3(string tel)//数字分析法做哈希函数{int hashValue;hashValue = atof(tel.substr(8, 3).c_str()); //因为电话号码⼀般后4位不同return hashValue;};解决冲突的⽅法1.线性探测法int HashTable::solve1(int hashVal,int flag) //线性探查法处理冲突{int output = hashVal;switch (flag){case1:for (int j = 1; j < MAXSIZE; j++){output = (hashVal + j) % MAXSIZE;if (tag[output] == 0){tag[output] = 1;return output;}}return -1;break;case2:for (int j = 1; j < MAXSIZE; j++){output = (hashVal + j) % MAXSIZE;if (tag2[output] == 0){tag2[output] = 1;return output;}}return -1;default:break;}};2.⼆次探查法int HashTable::solve2(int hashVal, int flag) //⼆次探查法解决冲突{int i = hashVal; //i为初始桶号int k = 0; //k为探查次数int odd = 0; //odd为控制加减的标志int save; //缓存上⼀次的桶号switch (flag){case1:while (tag[i]==1){if (odd == 0){k++; save = i;i = (i + 2 * k-1) % MAXSIZE;odd = 1;}else{i = (save - 2 * k+1) % MAXSIZE;odd = 0;if (i<0){i = i + MAXSIZE;}}}return i;break;case2:while (tag2[i] == 1){if (odd == 0){k++; save = i;i = (i + 2 * k - 1) % MAXSIZE;odd = 1;}else{k++;i = (save - 2 * k + 1) % MAXSIZE;odd = 0;if (i<0){i = i + MAXSIZE;}}}return i;break;default:break;}};3.拉链法Node* HashTable::solve3(int hashVal, int flag)//拉链法解决冲突{int i = hashVal; //第i条链Node*p = ht[i]; //该链上的头指针while (p!=NULL)p = p->next;//往后遍历直到找到⼀个空节点⽤于存放userreturn p;};所有代码如下1 #include <iostream>2 #include <string>3 #include <fstream>45using namespace std;67const int MAXSIZE = 12;//默认最⼤表长89101112//存储项13class User{14public:15string name;16string tel;17string address;18bool operator==(const User&target)19 {20if (this->name == &&this->address == target.address&&this->tel == target.tel) 21return true;22else23return false;24 }25 };2627//⽤于拉链法28struct Node{29 User user;30 Node* next;31 };32class HashTable{33public:34 HashTable(int size = MAXSIZE-1);35 ~HashTable(){ delete[]E; delete[]tag; delete[]E2; delete[]tag2; }36int hash1(string name, int flag);//哈希函数1 除数求余法37int hash2(string tel);//哈希函数2 折叠法38int hash3(string tel);//哈希函数3 数字分析法39int solve1(int hashVal, int flag);//线性探测法解决冲突40int solve2(int hashVal, int flag);//⼆次探测法解决冲突41 Node* solve3(int hashVal, int flag);//拉链法解决冲突42 User input();//往电话薄中添加⽤户43void creat(int flag); //创建散列表44void show(int flag); //列出电话薄所有元素45void search(int flag,string at); //搜索指定⽤户46void searchByNode(int flag, string at); //拉链法搜索指定⽤户47void insert(int flag, User newUser); //插⼊48void del(int flag, string by);//删除49void save(int flag);//将电话薄保存⾄本地⽂件50int length; //要创建的电话本长度51 Node** ht;52private:53 User* E; //⽤户数组按姓名散列54 User* E2; //⽤户数组2 按电话号码散列55int* tag; //标记散列表1每个桶的存储状态 0为空 1为实56int* tag2;//标记散列表2每个桶的存储状态57int flag; //1表⽰是按姓名 2表⽰按电话号码新建的哈希表58int maxSize; //哈希表最⼤长度59int f;//⽐例因⼦主要⽤于折叠法60 };6162 HashTable::HashTable(int size)63 {64 maxSize = size; //⽤作除数65 E = new User[MAXSIZE];66 E2 = new User[MAXSIZE];67 tag = new int[MAXSIZE];68 tag2 = new int[MAXSIZE];69for (int i = 0; i < MAXSIZE; i++)70 {71 tag[i] = 0;72 tag2[i] = 0;73 }74 f = maxSize / 512; //⽤于折叠法产⽣的哈希值过⼤保留3位数的地址范围为0~51175 ht = new Node*[maxSize]; //存放节点的⼀维数组拉链法76 };7778int HashTable::hash1(string name,int flag) //除数求余法79 {80int hashValue; long a = 0;81switch (flag)82 {83case1:84for (int i = 0; i < name.length(); i++)85 a += int(name[i]);86 hashValue = a%maxSize;87break;88case2:89int temp = atof(name.c_str());90 hashValue = temp%maxSize;91break;9293 }94return hashValue;95 };9697int HashTable::hash2(string tel) //折叠法--移位法98 {99int hashValue;100int temp; //移位法求和101 temp = atof(tel.substr(0, 3).c_str()) + atof(tel.substr(3, 3).c_str())102 + atof(tel.substr(6, 3).c_str()) + atof(tel.substr(9, 2).c_str());103//取计算之后的数的最后三位104if (temp >= 999)105 {106char p[10];107 sprintf(p, "%d", temp);108string lastThree = p;109 lastThree = lastThree.substr(lastThree.length() - 3, 3);110 hashValue = atof(lastThree.c_str());111return hashValue;112 }113 hashValue = temp;114return hashValue;115 };116117int HashTable::hash3(string tel)//数字分析法做哈希函数118 {119int hashValue;120 hashValue = atof(tel.substr(8, 3).c_str()); //因为电话号码⼀般后4位不同121return hashValue;122 };123124int HashTable::solve1(int hashVal,int flag) //线性探查法处理冲突125 {126int output = hashVal;127switch (flag)128 {129case1:130for (int j = 1; j < MAXSIZE; j++)131 {132 output = (hashVal + j) % MAXSIZE;133if (tag[output] == 0)134 {135 tag[output] = 1;136return output;137 }138 }139return -1;140break;141case2:142for (int j = 1; j < MAXSIZE; j++)143 {144 output = (hashVal + j) % MAXSIZE;145if (tag2[output] == 0)146 {147 tag2[output] = 1;148return output;149 }150 }151return -1;152default:153break;154 }155156 };157158int HashTable::solve2(int hashVal, int flag) //⼆次探查法解决冲突159 {160int i = hashVal; //i为初始桶号161int k = 0; //k为探查次数162int odd = 0; //odd为控制加减的标志163int save; //缓存上⼀次的桶号164switch (flag)165 {166case1:167while (tag[i]==1)168 {169if (odd == 0)170 {171 k++; save = i;172 i = (i + 2 * k-1) % MAXSIZE;173 odd = 1;174 }175else176 {177 i = (save - 2 * k+1) % MAXSIZE;178 odd = 0;179if (i<0)180 {181 i = i + MAXSIZE;182 }183 }184 }185return i;186break;187case2:188while (tag2[i] == 1)189 {190if (odd == 0)191 {192 k++; save = i;193 i = (i + 2 * k - 1) % MAXSIZE;194 odd = 1;195 }196else197 {198 k++;199 i = (save - 2 * k + 1) % MAXSIZE;200 odd = 0;201if (i<0)202 {203 i = i + MAXSIZE;204 }205 }206 }207return i;208break;209default:210break;211 }212213 };214215/*216Node* HashTable::solve3(int hashVal, int flag)//拉链法解决冲突217218{219 int i = hashVal; //第i条链220221 Node*p = ht[i]; //该链上的头指针222 while (p!=NULL)223 p = p->next;//往后遍历直到找到⼀个空节点⽤于存放user 224 return p;225};226227void HashTable::searchByNode(int flag, string at)//调⽤拉链法搜索228{229 int i = hash1(at,1);230 Node** ht = new Node*[maxSize]; //存放节点的⼀维数组231 Node*p = ht[i]; //该链上的头指针232 while (p!=NULL&&p->!=at)233 {234 p = p->next;235 }236};237*/238 User HashTable::input()239 {240 User user;241 cout << "请输⼊姓名:" << endl;242 cin >> ;243 cout << "请输⼊电话号码:" << endl;244 cin >> user.tel;245 cout << "请输⼊地址:" << endl;246 cin >> user.address;247return user;248 };249250void HashTable::creat(int flag)251 {252switch (flag)253 {254case1: //按姓名哈希创建哈希表255for (int i = 0; i < length; i++)256 {257 User newUser = input();258int val = hash1(,1);259if (tag[val] == 1)260 val = solve1(val,1);//线性探测法解决冲突261 E[val] = newUser;262 tag[val] = 1;263 }264break;265case2: //按电话号码哈希创建哈希表266for (int i = 0; i < length; i++)267 {268 User newUser = input();269int val = hash1(newUser.tel,2);270if(tag2[val] == 1)271 val = solve1(val,2);//线性探测法解决冲突272 E2[val] = newUser;273 tag2[val] = 1;274 }275break;276 }277 };278void HashTable::show(int flag)279 {280switch (flag)281 {282case1:283for (int i = 0; i < MAXSIZE; i++)284 {285if (tag[i] == 1)286 cout << E[i].name << "" << E[i].tel << "" << E[i].address << " 位于: " << i << endl; 287 }288break;289case2:290for (int i = 0; i < MAXSIZE; i++)291 {292if (tag2[i] == 1)293 cout << E2[i].name << "" << E2[i].tel << "" << E2[i].address << " 位于: " << i << endl; 294 }295break;296 }297298 };299300void HashTable::search(int flag,string at) //at表⽰索引内容301 {302int i = 0;303switch (flag)304 {305case1: //调⽤线性探测法查找姓名306 i = hash1(at,1);307if (tag[i] == 1 && E[i].name != at)308 i = solve1(i, 2);309if (i < 0 || tag2[i] == 0)310 {311 cout << "查⽆此⼈!" << endl;312return;313 }314if (tag[i] == 1 && E[i].name == at)315 cout << E2[i].name << "" << E2[i].tel << "" << E2[i].address << endl;316break;317case2: //调⽤⼆次探测法查找电话号码318 i = hash2(at);319if (tag2[i] == 1&&E2[i].tel!=at)320 i = solve2(i,2);321if (i < 0||tag2[i]==0)322 {323 cout << "查⽆此⼈!" << endl;324return;325 }326if (tag2[i] == 1 && E2[i].tel==at)327 cout << E2[i].name << "" << E2[i].tel << "" << E2[i].address << endl;328break;329 }330 };331332void HashTable::insert(int flag, User newUser){333int i = -1;334switch (flag)335 {336case1:337 i = hash1(,1);338if (tag[i] == 1||E[i]==newUser)339 i = solve1(i, 1);340if (i < 0)341 {342 cout << "表满!插⼊失败!" << endl;343return;344 }345if (tag[i] == 0)346 {347 E[i] = newUser;348 tag[i] = 1;349 length++;350 cout << "插⼊成功" << endl;351 }352case2:353 i = hash1(newUser.tel,2);354if (tag2[i] == 1 || E2[i] == newUser)355 i = solve1(i, 2);356if (i < 0)357 {358 cout << "表满!插⼊失败!" << endl;359return;360 }361if (tag2[i] == 0)362 {363 E2[i] = newUser;364 tag2[i] = 1;365 length++;366 cout << "插⼊成功" << endl;367 }368default:369break;370 }371 };372373void HashTable::del(int flag, string by) //by表⽰按照何种标签进⾏删除374 {375int i = -1;376int select;//选择是否删除377switch (flag)378 {379case1: //调⽤线性探测法查找姓名380 i = hash1(by,1);381if (tag[i] == 1 && E[i].name != by)382 i = solve1(i, 2);383if (i < 0 || tag2[i] == 0)384 {385 cout << "查⽆此⼈!" << endl;386return;387 }388if (tag[i] == 1 && E[i].name == by)389 {390 cout << E2[i].name << "" << E2[i].tel << "" << E2[i].address << endl; 391 cout << "是否删除 0.删了 1.算了" << endl;392 cin >> select;393if (select == 0)394 tag[i] = 0;//伪删除395 }396break;397case2: //调⽤⼆次探测法查找电话号码398 i = hash2(by);399if (tag2[i] == 1 && E2[i].tel != by)400 i = solve2(i, 2);401if (i < 0 || tag2[i] == 0)402 {403 cout << "查⽆此⼈!" << endl;404return;405 }406if (tag2[i] == 1 && E2[i].tel == by)407 {408 cout << E2[i].name << "" << E2[i].tel << "" << E2[i].address << endl; 409 cout << "是否删除 0.删了 1.算了" << endl;410 cin >> select;411if (select == 0)412 tag2[i] = 0;//伪删除413 }414break;415 }416 };417418void HashTable::save(int flag)419 {420 fstream out1("电话薄(姓名散列).txt", ios::out);421 fstream out2("电话薄(号码散列).txt", ios::out);422switch (flag)423 {424case1:425for (int i = 0; i < maxSize; i++)426 {427if (tag[i] == 1)428 out1 << E[i].name << "" << E[i].tel << "" << E[i].address << endl; 429 }430 cout << "已存⾄电话薄(姓名散列).txt" << endl;431return;432break;433case2:434for (int i = 0; i < maxSize; i++)435 {436if (tag2[i] == 1)437 out2 << E2[i].name << "" << E2[i].tel << "" << E2[i].address << endl; 438 }439 cout << "已存⾄电话薄(号码散列).txt" << endl;440return;441break;442default:443break;444 }445446 };hashtable.h1 #include <iostream>2 #include <string>3 #include <fstream>4 #include "hashtable.h"5using namespace std;67//菜单8void menu()9 {10 cout << " ****************************" << endl;11 cout << "|| 0.建表 ||" << endl;12 cout << "|| 1.查看 ||" << endl;13 cout << "|| 2.搜索 ||" << endl;14 cout << "|| 3.添加 ||" << endl;15 cout << "|| 4.删除 ||" << endl;16 cout << "|| 5.保存 ||" << endl;17 cout << "|| 6.退出 ||" << endl;18 cout << " ****************************" << endl;1920 }2122int main()23 {24 User user;25int size;//第⼀次创建的数据量⼤⼩26int select;//主菜单选项27int select_;//⼦菜单选项28 cout << "欢迎使⽤电话簿" << endl;29 HashTable ht;30while (1)31 {32 menu();33 cin >> select;34switch (select)35 {36case0:37 cout << "第⼀次使⽤,请输⼊要新建的电话本⼤⼩:" << endl;38 cin >> size;39 ht.length = size;40 cout << "1.姓名散列 2.电话号码散列" << endl;41 cin >> select_;42 ht.creat(select_);43break;44case1:45 cout << "1.姓名散列 2.电话号码散列" << endl;46 cin >> select_;47 ht.show(select_);48break;49case2:50 cout << "1.按姓名查找 2.按电话号码查找" << endl;51 cin >> select_;52if (select_==1)53 {54 cout << "输⼊姓名" << endl;55string name;56 cin >> name;57 ht.search(1, name);58 }59else if (select_ == 2)60 {61 cout << "输⼊号码" << endl;62string tel;63 cin >> tel;64 ht.search(2, tel);65 }66else67 cout << "不合法操作" << endl;68break;69case3:70 user = ht.input();71 cout << "1.插⼊到姓名散列表 2.插⼊到电话号码散列" << endl;72 cin >> select_;73 ht.insert(select_,user);74break;75case4:76 cout << "1.根据姓名删除 2.根据电话号码删除" << endl;77 cin >> select_;78if (select_ == 1)79 {80 cout << "输⼊姓名" << endl;81string name;82 cin >> name;83 ht.del(1, name);84 }85else if (select_ == 2)86 {87 cout << "输⼊号码" << endl;88string tel;89 cin >> tel;90 ht.del(2, tel);91 }92else93 cout << "不合法操作" << endl;94break;95case5:96 cout << "1.保存姓名散列表到本地 2.保存电话号码散列表到本地" << endl;97 cin >> select_;98 ht.save(select_);99case6:100return0;101 }102 }103 }main.cpp通过这次课程设计,总结如下1. C++技艺不精,语法不熟悉,⽐如模版类与运算符重载,指针更是不⼤熟练。
(完整版)设计散列表实现通讯录查找系统

设计散列表实现通讯录查找系统#include<stdio.h>#include<stdlib.h>#include<string>#include <windows.h>#define MAXSIZE 20 //电话薄记录数量#define MAX_SIZE 20 //人名的最大长度#define HASHSIZE 53 //定义表长#define SUCCESS 1#define UNSUCCESS -1#define LEN sizeof(HashTable)typedef int Status;typedef char NA[MAX_SIZE];typedef struct{//记录NA name;NA tel;NA add;}Record;typedef struct{//哈希表Record *elem[HASHSIZE]; //数据元素存储基址int count; //当前数据元素个数int size; //当前容量}HashTable;Status eq(NA x,NA y){//关键字比较,相等返回SUCCESS;否则返回UNSUCCESS if(strcmp(x,y)==0)return SUCCESS;else return UNSUCCESS;}Status NUM_BER; //记录的个数void getin(Record* a){//键盘输入各人的信息printf("输入要添加的个数:\n");scanf("%d",&NUM_BER);for(i=0;i<NUM_BER;i++){printf("请输入第%d个记录的用户名:\n",i+1);scanf("%s",a[i].name);printf("请输入%d个记录的电话号码:\n",i+1);scanf("%s",a[i].tel);printf("请输入第%d个记录的地址:\n",i+1);scanf("%s",a[i].add); //gets(str2);??????}}void ShowInformation(Record* a)//显示输入的用户信息{int i;for( i=0;i<NUM_BER;i++)printf("\n第%d个用户信息:\n 姓名:%s\n 电话号码:%s\n 联系地址:% s\n",i+1,a[i].name,a[i].tel,a[i].add);}void Cls(Record* a){printf("*");system("cls");}long fold(NA s){//人名的折叠处理char *p;long sum=0;NA ss;strcpy(ss,s);//复制字符串,不改变原字符串的大小写strupr(ss);//将字符串ss转换为大写形式p=ss;while(*p!='\0')sum+=*p++;printf("\nsum====================%d",sum);return sum;}int Hash1(NA str){//哈希函数int m;n=fold(str);//先将用户名进行折叠处理m=n%HASHSIZE; //折叠处理后的数,用除留余数法构造哈希函数return m; //并返回模值}int Hash2(NA str){//哈希函数long n;int m;n = atoi(str);//把字符串转换成整型数.m=n%HAreturn m; //并返回模值}Status collision(int p,int &c){//冲突处理函数,采用二次探测再散列法解决冲突int i,q;i=c/2+1;while(i<HASHSIZE){if(c%2==0){c++;q=(p+i*i)%HASHSIZE;if(q>=0) return q;else i=c/2+1;}else{q=(p-i*i)%HASHSIZE;c++;if(q>=0) return q;else i=c/2+1;}}return UNSUCCESS;}void benGetTime();void CreateHash1(HashTable* H,Record* a){//建表,以人的姓名为关键字,建立相应的散列表//若哈希地址冲突,进行冲突处理benGetTime();int i,p=-1,c,pp;for(i=0;i<NUM_BER;i++){c=0;p=Hash1(a[i].name);pp=p;while(H->elem[pp]!=NULL) {pp=collision(p,c);if(pp<0){printf("第%d记录无法解决冲突",i+1);//需要显示冲突次数时输出continue;}//无法解决冲突,跳入下一循环}H->elem[pp]=&(a[i]); //求得哈希地址,将信息存入H->count++;printf("第%d个记录冲突次数为%d。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<iostream> //cout,cin语句的头文件#include<stdlib.h> //清屏函数头文件:使用csl时调用system#include<string> //字符串头文件#include<stdio.h>#include<fstream>#define MAXSIZE 100 //电话薄记录的数量#define MAX_SIZE 50 //用户名、电话号码、地址的最大长度#define HASHSIZE 400 //定义表长#define SUCCESS 1 //查找#define UNSUCCESS -1#define LEN sizeof(HashTable) // 哈希表的长度using namespace std;typedef int Status;//typedef用来定义类型的别名。
此处用status作为int别名,目的表达int 变量是一个状态变量。
typedef char NA[MAX_SIZE]; //NA作为char的别名typedef struct{ // 自定义一个记录用户名、电话号码、联系地址的结构体的别名recordNA name,tel,add,way;}Record;Record a[HASHSIZE];typedef struct{ //散列表Record *elem[HASHSIZE]; //数据元素存储地址int count; //数据元素个数int size; //容量}HashTable;Status eq(NA x,NA y){ //关键字比较,相等返回SUCCESS;否则返回UNSUCCESSif(strcmp(x,y)==0)//2个字符串的大小比较s1=s2,strcmp(s1,s2) == 0; s1>s2, strcmp(s1,s2) == 1; s1<s2, strcmp(s1,s2) == -1;return SUCCESS;elsereturn UNSUCCESS;}Status NUM_BER; //记录的个数void getin(Record* a){ // 键盘输入联系人的信息,Record*调用Record函数;a是参数cout<<"请输入要添加的联系人的个数:\n";cin>>NUM_BER;int i;for(i=0;i<NUM_BER;i++){cout<<"请输入第"<<i+1<<"个记录的用户名:\n";cin>>a[i].name;cout<<"请输入第"<<i+1<<"个记录的电话号码:\n";cin>>a[i].tel;cout<<"请输入第"<<i+1<<"个记录的地址:\n";cin>>a[i].add;}}void ShowInformation(Record* a)//显示输入的用户信息{int i;for( i=0;i<NUM_BER;i++)cout<<"\n第"<<i+1<<"个用户信息:\n 姓名:"<<a[i].name<<"\n 电话号码:"<<a[i].tel<<"\n 联系地址:"<<a[i].add<<"\n--------\n";}long fold(NA s) //人名的折叠处理:将关键字分割成位数相同的几部分,最后一部分位数可以不同,然后取这几部分的叠加和(去除进位)作为散列地址{char *p;long sum=0;NA ss;strcpy(ss,s);//复制字符串,不改变原字符串的大小写strupr(ss);//将字符串ss转换为大写形式p=ss;while(*p!='\0')sum+=*p++;return sum;}int Hash1(NA str){//哈希函数long n;int m;n=fold(str);//先将用户名进行折叠处理m=n%HASHSIZE; //折叠处理后的数,用除留余数法构造哈希函数return m; //并返回模值}int Hash2(NA str){//哈希函数long n;int m;n = atoi(str);//把字符串转换成整型数.m=n%HASHSIZE; //用除留余数法构造哈希函数return m; //并返回模值}Status collision(int p,int &c){ // 冲突处理函数,采用二次探测再散列法解决冲突int i,q;i=c/2+1;while( i < HASHSIZE ){if(c%2==0){c++;q=(p+i*i)%HASHSIZE;if(q>=0) return q;else i=c/2+1;}else{q=(p-i*i)%HASHSIZE;c++;if(q>=0) return q;else i=c/2+1;}}return UNSUCCESS;}int searchHash( HashTable * &H, NA key, int &p, int &c ,int way ){if( way == 1 ){p=Hash1( key );while(H->elem[p]!=NULL && !eq( key, H->elem[p]->name ) )//若哈希地址冲突,进行冲突处理collision( p ,++c );if( eq( key, H->elem[p]->name ) )return 1;elsereturn 0;}else{p=Hash2( key );while(H->elem[p]!=NULL && !eq( key, H->elem[p]->tel ) )//若哈希地址冲突,进行冲突处理collision( p ,++c );if( eq( key, H->elem[p]->tel ) )return 1;elsereturn 0;}}// 建表,若哈希地址冲突,进行冲突处理void CreateHash(HashTable* H ,Record* a){cout<<"\n 〓〓〓〓〓〓建立散列表〓〓〓〓〓〓〓";cout<<"\n ⑴. 以姓名建立散列表(再散列法解决冲突) ";cout<<"\n ⑵. 以电话号码建立散列表(再散列法解决冲突) ";cout<<"\n ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆";cout<<"请输入选择:";int num,i,p=-1,c;cin>>num;for(i=0;i<NUM_BER;i++){c=0;if( num==1 ){p=Hash1( a[i].name );while(H->elem[p]!=NULL && !eq( a[i].name, H->elem[p]->name ) )//若哈希地址冲突,进行冲突处理collision( p ,++c );}else{p=Hash2( a[i].tel );while(H->elem[p]!=NULL && !eq( a[i].tel, H->elem[p]->tel ) )//若哈希地址冲突,进行冲突处理collision( p ,++c );}H->elem[p]=a+i; //求得哈希地址,将信息存入H->count++;cout<<"第"<<i+1<<"个记录冲突次数为"<<c<<"。
\n";//需要显示冲突次数时输出}cout<<"\n建表完成!\n此哈希表容量为"<<HASHSIZE<<",当前表内存储的记录个数为"<<H->count<<".\n";}// 查找用户名和电话号码的记录;void SearchHash ( HashTable* H,int &c){//在通讯录里查找关键字,若查找成功,显示信息//c用来记录冲突次数,查找成功时显示冲突次数NA type;int p;cout<<"\n 〓〓〓〓〓〓查找并显示用户信息记录〓〓〓〓〓〓〓";cout<<"\n ⑴. 查找并显示给定用户名的记录";cout<<"\n ⑵. 查找并显示给定电话号码的记录";cout<<"\n ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆";cout<<"请输入选择:";int num;cin>>num;switch(num){case 1:cout<<"\n请输入要查找的用户名:\n";cin>>type;searchHash( H, type, p, c, 1);if( eq( type, H->elem[p]->name )==1){cout<<"\n查找成功!以下是您需要要查找的信息:\n\n";cout<<"姓名:"<<H->elem[p]->name<<"\n电话号码:"<<H->elem[p]->tel<<"\n 联系地址:"<<H->elem[p]->add<<"\n";}elsecout<<"\n对不起,该用户不存在\n";break;case 2:cout<<"\n请输入要查找电话号码:\n";cin>>type;searchHash( H, type, p, c, 2);if( eq( type, H->elem[p]->tel )==1){cout<<"\n查找成功!以下是您需要要查找的信息:\n\n";cout<<"姓名:"<<H->elem[p]->name<<"\n电话号码:"<<H->elem[p]->tel<<"\n 联系地址:"<<H->elem[p]->add<<"\n";}elsecout<<"\n对不起,该用户不存在\n";break;default:cout<<"输入错误,请重新输入!";}}void Save(){ //保存ifstream in;ofstream out;out.open("123.txt");printf("\n保存成功!");for(int i=0; i<NUM_BER; i++ ){out<<"姓名:"<<a[i].name<<"\n电话号码:"<<a[i].tel<<"\n联系地址:"<<a[i].add<<"\n";}return;}void main_menu(){int c,flag=1;////定义一个布尔型变量flag并初始化为真(true)HashTable *H;H=(HashTable*)malloc(LEN);for(int i=0;i<HASHSIZE;i++)H->elem[i]=NULL;H->size=HASHSIZE;H->count=0;while (1){ // while使电话查询系统执行后返回主菜单的界面system("cls");cout<<"\n 〓〓〓〓〓〓↖(^ω^)↗欢迎使用电话号码查找系统〓〓〓〓〓〓〓";cout<<"\n ⑴. 添加用户信息";cout<<"\n ⑵. 读取所有用户信息";cout<<"\n ⑶. 建立散列表(再散列法解决冲突) ";cout<<"\n ⑷. 查找并显示给定用户的记录";cout<<"\n ⑸. 保存";cout<<"\n ⑹. 退出";cout<<"\n 提示:进行4操作前请先进行3操作 .否则无法查找成功!";cout<<"\n ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆";cout<<"\n\n请选择:";int num;cin>>num;switch(num){case 1:getin(a);system("pause");break;case 2:ShowInformation(a);system("pause");break;case 3:CreateHash (H,a); /* 建立散列表*/system("pause");break;case 4:c=0;SearchHash (H,c);system("pause");break;case 5:Save();system("pause");break;case 6:return ;break;default:cout<<"输入错误,请重新输入!";cout<<"\n";}}}int main(int argc, char* argv[]){main_menu();//执行结束后清屏,显示主菜单return 0;}。