大二数据结构实验之散列表实现通讯录(C++)

散列法的实验研究

【问题描述】

  1. 基本要求:设每个记录有下列数据项:电话号码、用户名、地址;从键盘输入各记录,分别以电话号码和用户名为关键字建立散列表;采用一定的方法解决冲突;查找并显示给定电话号码的记录;查找并显示给定用户名的记录。

  2. 进一步完成内容:
    系统功能的完善:
    设计不同的散列函数,比较冲突率;
    在散列函数确定的前提下,尝试各种不同类型处理冲突的方法,考察平均查找长度的变化。

#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std; 

#define MAXSIZE  20
#define HASHSIZE 50         //定义表长
#define SUCCESS 1  
#define UNSUCCESS -1  
#include<iostream>

typedef int Status;     
int num1 = 0;               //记录的个数
int num2 = 0;
//记录
typedef struct{   
   char name[MAXSIZE];      //姓名
   char address[MAXSIZE];   //地址
   char tel[MAXSIZE];       //电话号码
}DataType;         

//HashTable1:以电话号码为关键字
typedef struct{     
   DataType *elem1[HASHSIZE];   //数据元素存储基址
   int count1;                  //当前数据元素个数
   int size1;                   //当前容量
}HashTable1;  

//HashTable2:以姓名为关键字
typedef struct{        
   DataType *elem2[HASHSIZE];   //数据元素存储基址
   int count2;                  //当前数据元素个数
   int size2;                   //当前容量
}Hashtable2;  

//比较两个数组是否相等,若相等返回1,否则返回-1 
Status Compare(char a1[MAXSIZE], char a2[MAXSIZE]){    
if(strcmp(a1, a2) == 0) return 1;   
else return -1;  
}  

//遍历用户的信息
void ShowData(DataType *d){         
system("cls");  
    cout << "姓名\t地址\t电话号码" << endl;  
for(int i = 0; i < num1 + num2; i++){  
if(!d[i].name[0] == '\0')   //姓名非空时
        cout<< d[i].name << "\t" << d[i].address << "\t" << d[i].tel << endl;  
    }  
system("pause");  
system("cls");  
}  

//一次探测
int Hash1(char name[MAXSIZE]){  
int i = 0, p; 
    p = (int)name[0];  
while(name[i] != '\0')  
    {  
        p += (int)name[i]; 
i++;  
    } 
    p = p % HASHSIZE;  
return p;  
} 

int Hash2(char tel[MAXSIZE]){  
int i, p = 0;   
while(i != MAXSIZE){        
    p += (tel[i] - '0');    
i++;  
    } 
    p = p % HASHSIZE;  
return p;  
}  

//冲突处理函数
Status CollisionSolution(int p, int c){  
int i, q;  
    i = c / 2 + 1;  
while(i < HASHSIZE){  
if(c % 2 == 0){  
    c++;  
    q = (p + i * i) % HASHSIZE;//倘若c为偶数,函数公式为:(余数+i*i)%表长,返回合理值
    if(q >= 0) return q;  
    else i = c / 2 + 1;  
    }  
    else{
    q = (p - i * i) % HASHSIZE;//若c为奇数,函数公式为:(余数-i*i)%表长,返回合理值
    c++;  
    if(q >= 0) return q;  
    else i = c / 2 + 1;  
       }  
    }  
return UNSUCCESS;  
}  

//以姓名为关键字,建立相应的哈希表
void CreateHashTable1(HashTable1* H, DataType* a, int m){  
int i, p = -1, c = 0, pp;  
    cout << "以姓名为关键字建立哈希表" << endl;  
for(i = 0; i < m; i++){  
    c = 0;                              //记录冲突次数的变量
    p = Hash1(a[i].name);  
    pp = p;  
    while(H->elem1[pp] != NULL){        //若不为空,即产生冲突,调用冲突处理函数
    pp = CollisionSolution(p, c);   //若哈希地址冲突,进行冲突处理
    c++;  
    if(pp < 0){   
                cout << "第" << i + 1 << "个记录无法解决冲突" << endl; 
    continue;                   //无法解决冲突,跳入下一循环
    }  
    }  
    H->elem1[pp] = &(a[i]);             //求得哈希地址,将信息存入
    H->count1++;                        //表当前数据个数+1  
        cout << "第" << i + 1 << "个记录冲突次数为" << c << endl;  
    }  
}  

//以电话号码为关键字,建立相应的哈希表
void CreateHashTable2(Hashtable2* H, DataType* a, int m){  
int i, p = -1, c = 0, pp;  
    cout << "以电话号码为关键字建立哈希表" << endl;  
for(i = 0;i < m; i++){  
    c = 0;                              //记录冲突次数的变量
    p = Hash2(a[i].tel);  
    pp = p;  
    while(H->elem2[pp] != NULL){        //若不为空,即产生冲突,调用冲突处理函数
    pp = CollisionSolution(p, c);   //若哈希地址冲突,进行冲突处理
    c++;  
    if(pp < 0){  
                cout << "第" << i + 1 << "个记录无法解决冲突" << endl; 
    continue;                   //无法解决冲突,跳入下一循环
    }  
    }  
    H->elem2[pp] = &(a[i]);                 //求得哈希地址,将信息存入
    H->count2++;                            //表当前数据个数+1  
    cout << "第" << i + 1 << "个记录冲突次数为" << c << endl;  
    }  
}  

//创建通讯录
void Create(HashTable1* H1, DataType* a,Hashtable2* H2)    //创建新的通讯录
{  
system("CLS");  
memset(a->tel,0,sizeof(a->tel));  
    cout << "输入要添加的个数:";
    cin>> num1;    
    for(int i = 0; i < num1; i++){          //输入创建的用户信息
        cout << "请输入第" << i + 1 << "个记录的姓名:";  
cin>> a[i].name;
        cout << "请输入第" << i + 1 << "个记录的地址:";  
        cin>> a[i].address; 
        cout << "请输入第" << i + 1 << "个记录的电话号码:";
        cin>> a[i].tel;
    }  

    cout << "添加成功" << endl;  

    CreateHashTable1(H1, a, num1);  
    CreateHashTable2(H2, a, num1);  

system("pause");  
system("cls");  
}

//增加新的通讯录记录
void AddData(DataType* a, DataType *b, HashTable1* H1, Hashtable2* H2){  
system("cls"); 
    memset(b->tel, 0, sizeof(b->tel));                       
    cout << "请输入要添加的个数:";
    cin>> num2; 

    for(int i = 0; i < num2; i++){          //输入创建的用户信息
        cout << "请输入第" << i + 1 << "个记录的姓名:";
        cin>> b[i].name;  
for(int j = 0; j < MAXSIZE; j++){  
a[i + num1].name[j] = b[i].name[j];  
        }  
        cout << "请输入第" << i + 1 << "个记录的地址:"; 
cin>> b[i].address;
for(int j = 0; j < MAXSIZE; j++){  
a[i + num1].address[j] = b[i].address[j];  
        }  
        cout << "请输入第" << i + 1 << "个记录的电话号码:";
        cin>> b[i].tel;   
for(int j = 0; j < MAXSIZE; j++){  
a[i + num1].tel[j] = b[i].tel[j];  
        }  
    }  
    cout << "添加成功" << endl; 

CreateHashTable1(H1, b, num2);  
CreateHashTable2(H2, b, num2);  

system("pause");  
system("cls");  
}  

//在通讯录里查找姓名关键字,c用来记录冲突次数,若查找成功,显示信息
void Search(HashTable1* H1, DataType *a, Hashtable2* H2){     
int i;
    int c = 0;  
int p, pp;  
    char NAME[20];                    //定义要查找的名字的字符数组
system("cls");  
int l;  
    cout << "1.按姓名查找" << endl;  
    cout << "2.按电话号码查找" << endl;  
    cout << "请输入你的选项:";  
cin>> l;  
switch(l){  
case 1:  
    do{
    cout << "请输入要查找记录的姓名:";
    cin>> NAME; 
    p = Hash1(NAME);                //调用一次探测函数
    pp = p;   
    while((H1->elem1[pp] != NULL) && (Compare(NAME, H1->elem1[pp]->name) == -1)){
        pp = CollisionSolution(p, c);   //倘若一探测结果和所要查找的结果不同,调用二次探测函数
    c++;                            //冲突次数增加
        }  
        if(H1->elem1[pp] != NULL && Compare(NAME, H1->elem1[pp]->name) == 1){//探测到结果后将信息输出
        cout << "姓名:" << H1->elem1[pp]->name << endl;
        cout << "地址:" << H1->elem1[pp]->address << endl; 
                    cout << "电话号码:" << H1->elem1[pp]->tel << endl; 
                    cout << "查找过程冲突次数为" << c << endl; 
                }  
    else cout << "无此记录" << endl; 
    cout << "是否继续查找?1.继续 0.退出" << endl;  
    cin>> i;  
}while(i != 0);  
system("pause");  
system("cls");  
break;  

case 2:  
do{
    memset(NAME, 0, sizeof(NAME));  //初始化
    cout << "请输入要查找记录的电话号码:";
                cin>> NAME;   
    p = Hash2(NAME);                //调用一次探测函数
    pp=p;  
    while((H2->elem2[pp] != NULL) && (Compare(NAME, H2->elem2[pp]->tel) == -1)){
    pp = CollisionSolution(p, c);   //倘若一探测结果和所要查找的结果不同,调用二次探测函数
    c++;                            //冲突次数增加
        }  
    if(H2->elem2[pp] != NULL && Compare(NAME, H2->elem2[pp]->tel) == 1){  //探测到结果后将信息输出
        cout << "姓名:" << H2->elem2[pp]->name << endl;
        cout << "地址:" << H2->elem2[pp]->address << endl; 
                    cout << "电话号码:" << H2->elem2[pp]->tel << endl; 
                    cout << "查找过程冲突次数为" << c << endl;
                }  
    else cout << "无此记录" << endl;  
    cout << "是否继续查找?1.继续 0.退出" << endl;  
        cin>> i;  
}while(i != 0);  
    system("cls");  
break;  

default:  
break;  
    }  
}  

//在通讯录里修改某人信息
void Modify(HashTable1 *H1, DataType* a){ 
int p, pp;  
    char NAME[20];                      //想要修改的姓名数组
system("cls");  
    cout << "请输入你所要修改的原用户名:";  
cin>> NAME; 
    p = Hash1(NAME);                    //调用一次探测函数
    pp = p;  
while((H1->elem1[pp] != NULL) && (Compare(NAME, H1->elem1[pp]->name) == -1))    
    pp = CollisionSolution(p, 0);  //倘若一探测结果和所要查找的结果不同,调用二次探测函数
if(H1->elem1[pp] != NULL && Compare(NAME, H1->elem1[pp]->name) == 1){  //探测到结果后修改信息
    int m;  
    do{
    cout << "修改信息" << endl;  
    cout << "1.修改姓名" << endl;  
    cout << "2.修改地址" << endl;  
    cout << "3.修改电话号码" << endl;  
    cout << "请选择你想要选择的选项,输入0结束修改此用户信息" << endl;  
    cin>> m;  
    if(m == 1){  
        int p, n=0, m, i;  
                cout << "请输入修改后记录的姓名:";
                cin>> H1->elem1[pp]->name;  
            char t[20];  
        for(int i = 0; i < MAXSIZE; i++){  
        t[i] = H1->elem1[pp]->name[i];  
        }  
        p = Hash1(t);  
        m = p;  
        while(H1->elem1[m] != NULL){//若不为空,即产生冲突,调用冲突处理函数
        m = CollisionSolution(p, n);  //若哈希地址冲突,进行冲突处理
            n++;  
            if(m < 0){  
            cout << "冲突无法解决" << endl;  
        break;  
        }  
        }  
        H1->elem1[m] = H1->elem1[pp];  //求得哈希地址,将信息存入
    }  
    if(m == 2){  
    cout << "请输入修改后记录的地址:";
                cin>> H1->elem1[pp]->address; 
    }  
    if(m == 3){  
                cout << "请输入修改后记录的电话号码:";
                cin>> H1->elem1[pp]->tel;  
    }  
    }while(m != 0);  
        cout << "修改成功" << endl;  
    }  
    else cout << "此人不存在,修改不成功!" << endl;  
system("CLS");  
}  

//在通讯录里查找姓名关键字,若查找成功,显示信息然后删除
void Delete(HashTable1* H1, DataType* a){ 
int i;  
do{
    int m, p, pp;  
    char NAME[20];  
    m = 0;  
    system("cls");  
        cout << "请输入要删除记录的姓名:";  
    m++;    
        cin>> NAME;
    p = Hash1(NAME);  
    pp = p;  

    while((H1->elem1[pp] != NULL) && (Compare(NAME, H1->elem1[pp]->name) == -1))
        pp = CollisionSolution(p, 0);  //倘若一探测结果和所要查找的结果不同,调用二次探测函数
    if(H1->elem1[pp] != NULL && Compare(NAME, H1->elem1[pp]->name) == 1){//探测到结果后删除信息
    for(int i = 0; i < num1 + num2; i++){  
    if(Compare(NAME, a[i].name) == 1) a[i].name[0] = '\0';  
            }  
    H1->elem1[pp]->name[0] = '\0';//将所要删的用户的电话号码清空
    H1->elem1[pp]->address[0] = '\0';  
    H1->elem1[pp]->tel[0] = '\0';  

            cout << "删除成功" << endl;  
    }  
    else cout << "此人不存在,删除不成功!" << endl;  
        cout << "是否继续删除?1.继续0.退出" << endl;  
cin>> i;  
}while(i != 0);  
system("cls");  
}  

int main(){  
int c, i = 0;  
    DataType a[MAXSIZE];
    DataType b[MAXSIZE];  
    HashTable1 *H1;
    Hashtable2 *H2;  

    H1 = (HashTable1*)malloc(sizeof(HashTable1));   //申请空间
    for(i = 0; i < HASHSIZE; i++){                  //初始化哈希表
    H1->elem1[i] = NULL;  
    H1->size1 = HASHSIZE;  
    H1->count1 = 0;  
    }  
    H2 = (Hashtable2*)malloc(sizeof(Hashtable2));   //申请空间
    for(i = 0; i < HASHSIZE; i++){                  //初始化哈希表
        H2->elem2[i] = NULL;  
    H2->size2 = HASHSIZE;  
        H2->count2 = 0;  
    }

while (1){  
    int m;  
    cout << "*****************************通讯录******************************" << endl;
    cout << "*                 【1】.  创建通讯录                            *" << endl;    
    cout << "*                 【2】.  添加用户信息                          *" << endl;  
    cout << "*                 【3】.  显示所有用户信息                      *" << endl;  
    cout << "*                 【4】.  查找用户信息                          *" << endl;  
    cout << "*                 【5】.  删除用户信息                          *" << endl;  
    cout << "*                 【6】.  修改用户信息                          *" << endl;  
    cout << "*                 【7】.  退出程序                              *" << endl;  
    cout<< "*****************************************************************" << endl;  
    cout << "请输入操作序号:";  
    cin>> m;  
    switch(m){  
        case 1:
                Create(H1, a, H2);
                break; 
    case 2:    
    AddData(a, b, H1, H2) ;  
    break;  
    case 3:  
    ShowData(a);  
    break;  
    case 4:  
    c = 0;  
    Search(H1, a, H2);  
    break;  
    case 5:   
    Delete(H1, a);  
    break;  
    case 6:  
        c = 0;  
    Modify(H1, a);  
    break;  
    case 7:  
    return 0;  
    break;  
    default:  
    cout << "输入错误,请重新输入!" << endl;  
    }  
    }  
    system("pause");  
    return 0;  
}  

猜你喜欢

转载自blog.csdn.net/wying_0/article/details/78025006