问题描述
设计与实现一个通讯录管理系统,实现按姓名、电话号、QQ 号查找。
功能要求
- 要求能够管理通讯录,即具有通讯录的建立、增、删、改记录功能;
- 要求实现在指定通讯录中按姓名、电话号、QQ 号查找功能。
系统描述
信息结构
通讯录查找子系统
二分查找(QQ号)
先给QQ号排序
void sort_QQ(SqList &p)//qq排序
{
int i,j,w;
ElemType *temp;
for(i=0; i<n; i++)
for(j=i+1; j<n; j++)
{
w=i;
if(strcmp(p.data[w]->QQnum,p.data[j]->QQnum)>0)//若data[w]字符串大于data[j]
w=j;
if(i!=w)
{
temp=p.data[i];
p.data[i]=p.data[j];
p.data[j]=temp;
}
}
}
然后再用二分法查找
int Search_QQ(SqList p,char *key)//二分法查找qq号
{
int low=0,high=p.length-1,mid;
while(low<=high)
{
mid=(low+high)/2;
if(strcmp(key,p.data[mid]->QQnum)==0)
return mid;
else if(strcmp(key,p.data[mid]->QQnum)<0)
high=mid-1;
else
low=mid+1;
}
return -1;
}
二叉排序树查找手机号
先新建一个二叉排序树,一个一个插入节点
void InsertBST(BSTree &T,ElemType *e)//二叉排序树插入节点
{
BSTree S;
if(!T)
{
S=new BSTNode;
S->data=e;
S->lchild=S->rchild=NULL;
T=S;
}
else if(strcmp(e->phonenum,T->data->phonenum)<0)
InsertBST(T->lchild,e);
else if(strcmp(e->phonenum,T->data->phonenum)>0)
InsertBST(T->rchild,e);
}
void CreatBST(BSTree &T,Linklist head)//新建二叉排序树
{
T=NULL;
Linklist p=head->next;
ElemType *e=&p->data;
while(p)
{
InsertBST(T,e);
p=p->next;
e=&p->data;
}
}
二叉排序树的递归搜索
BSTree Search_BST(BSTree T,KeyType key)//二叉排序树递归搜索
{
if((!T)||!strcmp(key,T->data->phonenum))
return T;
else if(strcmp(key,T->data->phonenum)<0)
return Search_BST(T->lchild,key);
else
return Search_BST(T->rchild,key);
}
散列表查找姓名
先创建一个散列表
HashLL Create_Hash(Linklist head)
{
HashLL H=new HashLN[300],q;
Linklist p=head->next;
int i;
for(i=0; i<171; i++)
{
H[i].data=NULL;
H[i].next=NULL;
}
while(p)
{
i=p->data.name[0]-'0'+p->data.name[1]-'0'+p->data.name[2]-'0'-150;//hash---处理姓名前三位
if(H[i].data!=NULL)
{
q=new HashLN;
q->data=&(p->data);
q->next=H[i].next;
H[i].next=q;
}
else
H[i].data=&(p->data);
p=p->next;
}
return H;
}
然后以姓名为关键字构建散列函数进行查找
```c
ElemType* Search_name(HashLL H,char *name)
{
int i;
HashLL p,N=new HashLN;
ElemType *e;
i=name[0]-'0'+name[1]-'0'+name[2]-'0'-150;//hash---处理姓名前三位
N->data=NULL;
if(H[i].data==NULL)
{
cout<<"查无此人!"<<endl;
return N->data;
}
if(strcmp(H[i].data->name,name)==0)
return H[i].data;
else
{
p=H[i].next;
while(p)
{
if(strcmp(p->data->name,name)==0)
return p->data;
p=p->next;
}
cout<<"查无此人!"<<endl;
return N->data;
}
}
通讯录编辑子系统
这部分用文件读写就可实现,主要就是文件的增删改查。
这部分就不加提示了。
如果有问题可以评论区问我。
实验源码
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<iomanip>
#define MAXSIZE 1000
using namespace std;
typedef char *KeyType;
/*---------------------------------------信息结构--------------------------------------*/
typedef struct
{
char name[20];
char phonenum[20];
char QQnum[20];
char company[50];
char address[100];
} ElemType,*Phone;
/*---------------------------------------信息结构--------------------------------------*/
typedef struct LNode
{
ElemType data;
struct LNode *next;
} LNode,*Linklist;
typedef struct
{
Phone *data;
int length;
} SqList;
/*----------------------------树结构-----------------------------------*/
typedef struct BSTNode
{
ElemType *data;
struct BSTNode *lchild,*rchild;
} BSTNode,*BSTree;
/*----------------------------树结构-----------------------------------*/
/*---------------------------hash表----------------------------------*/
typedef struct HashLN
{
ElemType *data;
struct HashLN *next;
} HashLN,*HashLL;
/*---------------------------hash表----------------------------------*/
int n;
int m_num(int n,char *file)//计算文件中信息个数
{
FILE *fp;
long length;//计算文件字节数
if((fp = fopen(file,"rb")) != NULL)
fp = fopen(file,"rb");
fseek(fp,0L,2);
length = ftell(fp);
fclose(fp);
return length/n;
}
void FILEREAD(char *file,Linklist &head)//循环按块读取
{
FILE *fp;
Linklist r,p,q;
head=new LNode;
head->next=NULL;
r=head;
if((fp=fopen(file,"rb"))==NULL)
return;
while(!feof(fp))
{
q=r;
p=new LNode;
fread(&p->data,sizeof(ElemType),1,fp);
r->next=p;
r=p;
}
q->next=NULL;
delete p;
fclose(fp);
}
void printelem(ElemType e)
{
//cout<<" 姓名 电话号 QQ号 单位 住址"<<endl;
cout<<"| "<<setw(20)<<e.name;
cout<<setw(20)<<e.phonenum;
cout<<setw(20)<<e.QQnum;
cout<<setw(20)<<e.company;
cout<<setw(20)<<e.address<<" |";
cout<<endl;
}
SqList Link_Sq(Linklist head)//建立链表
{
SqList ph;
ph.data=new Phone[n];
Linklist p=head->next;
int i=0;
while(p)
{
ph.data[i]=&p->data;
i++;
p=p->next;
}
ph.length=n;
return ph;
}
void sort_QQ(SqList &p)//qq排序
{
int i,j,w;
ElemType *temp;
for(i=0; i<n; i++)
for(j=i+1; j<n; j++)
{
w=i;
if(strcmp(p.data[w]->QQnum,p.data[j]->QQnum)>0)//若data[w]字符串大于data[j]
w=j;
if(i!=w)
{
temp=p.data[i];
p.data[i]=p.data[j];
p.data[j]=temp;
}
}
}
void InitLink(Linklist &head)//初始化
{
head=new LNode;
head->next=NULL;
}
void ADD(Linklist &head,char *file)//插入信息
{
char flag='1';
Linklist r=head,p;
while(r->next)
r=r->next;
while(flag!='0')
{
p=new LNode;
cout<<"请输入姓名 : ";
cin>>p->data.name;
cout<<"请输入手机号: ";
cin>>p->data.phonenum;
cout<<"请输入QQ号 : ";
cin>>p->data.QQnum;
cout<<"请输入单位 : ";
cin>>p->data.company;
cout<<"请输入地址 : ";
cin>>p->data.address;
r->next=p;
r=p;
cout<<"停止请按0,否则请按回车。"<<endl;
getchar();
flag=getchar();
}
p->next=NULL;
}
void Traverse_Link(Linklist head)//初始界面
{
cout<<n<<endl;
Linklist p=head->next;
cout<<" ________________________________________________________________________________________________________"<<endl;
cout<<"| |"<<endl;
cout<<"| 姓名 电话号 QQ号 单位 住址 |"<<endl;
while(p)
{
printelem(p->data);
p=p->next;
}
cout<<"|________________________________________________________________________________________________________|"<<endl;
}
void WRITEFILE_LINK(Linklist head,char *file)//按块写入文件
{
FILE *fp=fopen(file,"wb");
Linklist p=head->next;
while(p)
{
fwrite(&p->data,sizeof(ElemType),1,fp);
p=p->next;
}
fclose(fp);
}
void Correct(ElemType *e)
{
int n,flag=1;
char c[20];
while(flag)
{
cout<<"*****请选择******"<<endl;
cout<<"* 1,姓名 *"<<endl;
cout<<"* 2,电话号 *"<<endl;
cout<<"* 3,QQ号 *"<<endl;
cout<<"* 4,单位 *"<<endl;
cout<<"* 5,地址 *"<<endl;
cout<<"* 6,退出修改 *"<<endl;
cout<<"*****************"<<endl;
cin>>n;
switch(n)
{
case 1:
cout<<"请输入:";
cin>>c;
strcpy(e->name,c);
break;
case 2:
cout<<"请输入:";
cin>>c;
strcpy(e->phonenum,c);
break;
case 3:
cout<<"请输入:";
cin>>c;
strcpy(e->QQnum,c);
break;
case 4:
cout<<"请输入:";
cin>>c;
strcpy(e->company,c);
break;
case 5:
cout<<"请输入:";
cin>>c;
strcpy(e->address,c);
break;
case 6:
flag=0;
}
}
}
void Delete(Linklist head,char *name)//删除指定信息
{
Linklist p,q=head;
p=head->next;
while(p&&strcmp(p->data.name,name)!=0)//姓名不相等,以及查找没有到尾
{
q=p;
p=p->next;
}
if(p)
{
q->next=p->next;
delete p;
cout<<"删除成功!"<<endl;
}
else
cout<<"查无此人!"<<endl;
}
int Search_QQ(SqList p,char *key)//二分法查找qq号
{
int low=0,high=p.length-1,mid;
while(low<=high)
{
mid=(low+high)/2;
if(strcmp(key,p.data[mid]->QQnum)==0)
return mid;
else if(strcmp(key,p.data[mid]->QQnum)<0)
high=mid-1;
else
low=mid+1;
}
return -1;
}
BSTree Search_BST(BSTree T,KeyType key)//二叉排序树递归搜索
{
if((!T)||!strcmp(key,T->data->phonenum))
return T;
else if(strcmp(key,T->data->phonenum)<0)
return Search_BST(T->lchild,key);
else
return Search_BST(T->rchild,key);
}
void InsertBST(BSTree &T,ElemType *e)//二叉排序树插入
{
BSTree S;
if(!T)
{
S=new BSTNode;
S->data=e;
S->lchild=S->rchild=NULL;
T=S;
}
else if(strcmp(e->phonenum,T->data->phonenum)<0)
InsertBST(T->lchild,e);
else if(strcmp(e->phonenum,T->data->phonenum)>0)
InsertBST(T->rchild,e);
}
void CreatBST(BSTree &T,Linklist head)//新建二叉排序树
{
T=NULL;
Linklist p=head->next;
ElemType *e=&p->data;
while(p)
{
InsertBST(T,e);
p=p->next;
e=&p->data;
}
}
HashLL Create_Hash(Linklist head)
{
HashLL H=new HashLN[300],q;
Linklist p=head->next;
int i;
for(i=0; i<171; i++)
{
H[i].data=NULL;
H[i].next=NULL;
}
while(p)
{
i=p->data.name[0]-'0'+p->data.name[1]-'0'+p->data.name[2]-'0'-150;//hash---处理姓名前三位
if(H[i].data!=NULL)
{
q=new HashLN;
q->data=&(p->data);
q->next=H[i].next;
H[i].next=q;
}
else
H[i].data=&(p->data);
p=p->next;
}
return H;
}
ElemType* Search_name(HashLL H,char *name)
{
int i;
HashLL p,N=new HashLN;
ElemType *e;
i=name[0]-'0'+name[1]-'0'+name[2]-'0'-150;//hash---处理姓名前三位
N->data=NULL;
if(H[i].data==NULL)
{
cout<<"查无此人!"<<endl;
return N->data;
}
if(strcmp(H[i].data->name,name)==0)
return H[i].data;
else
{
p=H[i].next;
while(p)
{
if(strcmp(p->data->name,name)==0)
return p->data;
p=p->next;
}
cout<<"查无此人!"<<endl;
return N->data;
}
}
void Change()
{
int a,flag=1;
Linklist head;
char file[20]="通讯录.txt",name[20],c='1';
FILEREAD(file,head);
ElemType *w;
HashLL H=Create_Hash(head);
while(flag)
{
cout<<" ____________________________________ "<<endl;
cout<<"| |"<<endl;
cout<<"| 通 讯 录 编 辑 |"<<endl;
cout<<"| |"<<endl;
cout<<"| 1.建立通讯录 |"<<endl;
cout<<"| 2.增加记录 |"<<endl;
cout<<"| 3.修改记录 |"<<endl;
cout<<"| 4.删除记录 |"<<endl;
cout<<"| 5.查看通讯录 |"<<endl;
cout<<"| 6.返回主菜单 |"<<endl;
cout<<"|____________________________________|"<<endl;
cin>>a;
switch(a)
{
case 1:
InitLink(head);
ADD(head,file);
break;
case 2:
ADD(head,file);
break;
case 3:
while(c!='0')
{
cout<<"请输入姓名:";
cin>>name;
w=Search_name(H,name);
printelem(*w);
Correct(w);
cout<<"是否继续(0/1)"<<endl;
getchar();
c=getchar();
}
c='1';
break;
case 4:
while(c!='0')
{
cout<<"请输入姓名:";
cin>>name;
Delete(head,name);
cout<<"是否继续(0/1)"<<endl;
getchar();
c=getchar();
}
c='1';
break;
case 5:
Traverse_Link(head);
break;
case 6:
WRITEFILE_LINK(head,file);
flag=0;
break;
}
}
}
void Search()
{
int a,flag=1,x;
Linklist head;
ElemType *e;
char phonenum[20];
char QQ[20],name[20];
char file[20]="通讯录.txt";
FILEREAD(file,head);
SqList p=Link_Sq(head);
BSTree T,temp;
HashLL H=Create_Hash(head);
while(flag)
{
cout<<" ____________________________________ "<<endl;
cout<<"| |"<<endl;
cout<<"| |"<<endl;
cout<<"| 通 讯 录 查 找 |"<<endl;
cout<<"| |"<<endl;
cout<<"| 1.按姓名查找 |"<<endl;
cout<<"| 2.按qq号查找 |"<<endl;
cout<<"| 3.按电话号查找 |"<<endl;
cout<<"| 4.返回主菜单 |"<<endl;
cout<<"|____________________________________|"<<endl;
cin>>a;
switch(a)
{
case 1:
cout<<"请输入姓名:";
cin>>name;
e=Search_name(H,name);
if(e!=NULL)printelem(*e);
break;
case 2:
cout<<"请输入QQ:";
cin>>QQ;
sort_QQ(p);
x=Search_QQ(p,QQ);
if(x!=-1)
printelem(*p.data[x]);
else
cout<<"没找到!"<<endl;
break;
case 3:
cout<<"请输入电话号:";
cin>>phonenum;
CreatBST(T,head);
temp=Search_BST(T,phonenum);
if(temp)
printelem(*temp->data);
else
cout<<"查无此人!"<<endl;
break;
case 4:
flag=0;
}
}
}
void menu()
{
char file[20]="通讯录.txt";
n=m_num(sizeof(ElemType),file);
int a,flag=1;
while(flag)
{
cout<<" ____________________________________ "<<endl;
cout<<"| |"<<endl;
cout<<"| 通 讯 录 管 理 |"<<endl;
cout<<"| |"<<endl;
cout<<"| 1.通讯录编辑 |"<<endl;
cout<<"| 2.通讯录查找 |"<<endl;
cout<<"| 3.返回主菜单 |"<<endl;
cout<<"|____________________________________|"<<endl;
cin>>a;
switch(a)
{
case 1:
Change();
break;
case 2:
Search();
break;
case 3:
flag=0;
break;
}
}
}
int main()
{
menu();
return 0;
}