课设题目:哈希表实现电话号码查找系统

 开发工具:VS 2017

 演示效果:呃,我也忘了成功没有了

  1. // MyHashTable.cpp : 定义控制台应用程序的入口点。  
    设计哈希表实现电话号码查询系统  
    //说明:一是从文件old.txt中读取的数据自己在程序运行前建立,  
    //      二是由系统随机生成数据,在程序运行由随机数产生器生成,并且将产生的记录保存到 new.txt文件。  
      
    //存在的问题:使用随机产生的文件,在显示时出现乱码  
      
      
    #include "stdafx.h"  
    #include<fstream>//文件流  
    #include<iostream>  
    #include <string>  
    using namespace std;  
      
    const int D[] = {3,5,8,11,13,14,19,21};//预定再随机数  
    const int HASH_MAXSIZE = 50;//哈希表长度  
      
    //记录信息类型  
    class DataInfo  
    {  
    public:  
        DataInfo();//默认构造函数  
        friend ostream& operator<<(ostream& out, const DataInfo& dataInfo); //重载输出操作符  
        //friend class HashTable;  
      
    //private:  
        string name;//姓名  
        string phone;//电话号码  
        string address;//地址   
        char sign;//冲突的标志位,'1'表示冲突,'0'表示无冲突  
    };  
      
    DataInfo::DataInfo():name(""), phone(""), address(""), sign('0')  
    {  
      
    }  
      
    ostream& operator<<(ostream& out, const DataInfo& dataInfo) //重载输出操作符  
    {  
        cout << "姓名:" << dataInfo.name << "   电话:" << dataInfo.phone   
             << "    地址:" << dataInfo.address << endl;  
        return out;  
    }  
      
    //存放记录的哈希表类型  
    class HashTable  
    {  
    public:  
        HashTable();//默认构造函数  
        ~HashTable();//析构函数  
        int Random(int key, int i);// 伪随机数探测再散列法处理冲突  
        void Hashname(DataInfo *dataInfo);//以名字为关键字建立哈希表      
        int Rehash(int key, string str);// 再哈希法处理冲突   注意处理冲突还有链地址法等  
        void Hashphone(DataInfo *dataInfo);//以电话为关键字建立哈希表         
        void Hash(char *fname, int n);// 建立哈希表  
        //fname 是数据储存的文件的名称,用于输入数据,n是用户选择的查找方式    
          
        int Findname(string name);// 根据姓名查找哈希表中的记录对应的关键码  
        int Findphone(string phone);// 根据电话查找哈希表中的记录对应的关键码  
        void Outhash(int key);// 输出哈希表中关键字码对应的一条记录  
        void Outfile(string name, int key);// 在没有找到时输出未找到的记录  
        void Rafile();// 随机生成文件,并将文件保存在 new.txt文档中  
        void WriteToOldTxt();//在运行前先写入数据      
      
    //private:  
            DataInfo *value[HASH_MAXSIZE];  
        int length;//哈希表长度  
    };  
      
    HashTable::HashTable():length(0)//默认构造函数  
    {  
        //memset(value, NULL, HASH_MAXSIZE*sizeof(DataInfo*));  
        for (int i=0; i<HASH_MAXSIZE; i++)  
        {  
            value[i] = new DataInfo();  
        }  
    }  
      
    HashTable::~HashTable()//析构函数  
    {  
        delete[] *value;  
    }  
      
    void HashTable::WriteToOldTxt()  
    {  
        ofstream openfile("old.txt");  
        if (openfile.fail())  
        {  
            cout << "文件打开错误!" << endl;  
            exit(1);  
        }  
      
        string oldname;  
            string oldphone;  
        string oldaddress;  
      
        for (int i=0; i<30; i++)  
        {  
            cout << "请输入第" << i+1 << "条记录:" << endl;          
            cin >> oldname ;  
            cin >> oldphone;  
            cin >> oldaddress;  
            openfile << oldname << "  " << oldphone << "  " << oldaddress << "," << endl;  
        }  
        openfile.close();  
    }  
      
      
    int HashTable::Random(int key, int i)// 伪随机数探测再散列法处理冲突  
    {//key是冲突时的哈希表关键码,i是冲突的次数,N是哈希表长度  
        //成功处理冲突返回新的关键码,未进行冲突处理则返回-1  
        int h;  
        if(value[key]->sign == '1')//有冲突  
        {  
            h = (key + D[i]) % HASH_MAXSIZE;  
            return h;  
        }  
        return -1;  
    }  
      
    void HashTable::Hashname(DataInfo *dataInfo)//以名字为关键字建立哈希表  
    {//利用除留取余法建立以名字为关键字建立的哈希函数,在发生冲突时调用Random函数处理冲突  
        int i = 0;    
        int key = 0;  
      
            for (int t=0; dataInfo->name[t]!='\0'; t++)     
        {         
            key = key + dataInfo->name[t];  
        }  
        key = key % 42;  
        while(value[key]->sign == '1')//有冲突  
        {  
            key = Random(key, i++);//处理冲突  
        }  
        if(key == -1) exit(1);//无冲突  
        length++;//当前数据个数加  
        value[key]->name = dataInfo->name;  
        value[key]->address = dataInfo->address;  
        value[key]->phone = dataInfo->phone;  
        value[key]->sign = '1';//表示该位置有值  
        //cout << value[key]->name << "  " << value[key]->phone << "  "  << value[key]->address << endl;  
    }  
      
    int HashTable::Rehash(int key, string str)// 再哈希法处理冲突  
    {//再哈希时使用的是折叠法建立哈希函数      
        int h;  
        int num1 = (str[0] - '0') * 1000 + (str[1] - '0') * 100 + (str[2] - '0') * 10 + (str[3] - '0');  
        int num2 = (str[4] - '0') * 1000 + (str[5] - '0') * 100 + (str[6] - '0') * 10 + (str[7] - '0');  
        int num3 = (str[8] - '0') * 100  + (str[9] - '0') * 10  + (str[10] - '0');  
        h = num1 + num2 + num3;  
        h = (h + key) % HASH_MAXSIZE;  
        return h;  
    }  
      
    void HashTable::Hashphone(DataInfo *dataInfo)//以电话为关键字建立哈希表  
    {//利用除留取余法建立以电话为关键字建立的哈希函数,在发生冲突时调用Rehash函数处理冲突  
        int key = 0;      
        int t;  
          
        for(t=0; dataInfo->phone[t] != '\0'; t++)  
        {     
            key = key + dataInfo->phone[t];  
        }  
        key = key % 42;  
        while(value[key]->sign == '1')//有冲突  
        {  
            key = Rehash(key, dataInfo->phone);  
        }  
        length++;//当前数据个数加  
        value[key]->name = dataInfo->name;  
        value[key]->address = dataInfo->address;  
        value[key]->phone = dataInfo->phone;     
        value[key]->sign = '1';//表示该位置有值   
    }  
      
    void HashTable::Outfile(string name, int key)//在没有找到时输出未找到的记录  
    {  
        ofstream fout;  
        if((key == -1)||(value[key]->sign == '0'))//判断哈希表中没有记录  
        {  
            fout.open("out.txt",ios::app);//打开文件  
      
            if(fout.fail())  
            {  
                cout << "文件打开失败!" << endl;  
                exit(1);  
            }  
            fout << name << endl;//将名字写入文件,有个问题,每次写入的时候总是将原来的内容替换了  
            fout.close();  
        }  
    }  
      
    void HashTable::Outhash(int key)//输出哈希表中关键字码对应的记录  
    {    
        if((key==-1)||(value[key]->sign=='0'))  
            cout << "没有找到这条记录!" << endl;  
        else  
        {         
            for(unsigned int i=0; value[key]->name[i]!='\0'; i++)  
            {  
                cout << value[key]->name[i];             
            }  
      
            for(unsigned int i=0; i<10; i++)  
            {  
                cout << " ";  
            }  
      
            cout << value[key]->phone;  
      
            for(int i=0; i<10; i++)  
            {  
                cout << " ";  
            }  
      
            cout << value[key]->address << endl;  
        }  
    }  
      
    void HashTable::Rafile()//随机生成文件,并将文件保存在new.txt文档中  
    {  
        ofstream fout;  
        fout.open("new.txt");//打开文件,等待写入  
        if(fout.fail())  
        {  
            cout << "文件打开失败!" << endl;  
            exit(1);  
        }  
        for(int j=0; j<30; j++)  
        {         
            string name = "";  
            for(int i=0; i<20; i++)//随机生成长个字的名字  
            {  
                name += rand() % 26 + 'a';//名字是由个字母组成             
            }  
            fout << name << "   ";//将名字写入文件  
      
            string phone = "";  
            for(int i=0; i<11; i++)//随机生成长位的电话号码  
            {  
                phone += rand() % 10 + '0';//电话号码是纯数字  
            }  
            fout << phone << "      ";//将电话号码写入文件  
      
            string address = "";  
            for(int i=0; i<29; i++)//随机生成长个字的名字  
            {  
                address += rand() % 26 + 'a';//地址是由个字母组成  
            }  
            address += ',';  
            fout << address << endl;//将地址写入文件  
        }  
        fout.close();  
    }  
      
    void HashTable::Hash(char *fname, int n)//建立哈希表  
    //fname是数据储存的文件的名称,用于输入数据,n是用户选择的查找方式  
    //函数输入数据,并根据选择调用Hashname或Hashphone函数进行哈希表的建立  
    {  
        ifstream fin;         
        int i;  
        fin.open(fname);//读文件流对象  
        if(fin.fail())  
        {  
            cout << "文件打开失败!" << endl;  
            exit(1);  
        }  
        while(!fin.eof())//按行读入数据  
        {  
            DataInfo *dataInfo = new DataInfo();  
            char* str = new char[100];        
            fin.getline(str, 100, '\n');//读取一行数据  
      
            if(str[0] == '*')//判断数据结束  
            {  
                break;  
            }  
      
            i = 0;//记录字符串数组的下标  
            //a-z:97-122     A-Z:65-90      
            //本程序的姓名和地址都使用小写字母  
            while((str[i] < 97) || (str[i] > 122))//读入名字  
            {  
                i++;  
            }  
      
            for(; str[i]!=' '; i++)  
            {             
                dataInfo->name += str[i];              
            }  
      
            while(str[i] == ' ')  
            {  
                i++;  
            }  
      
            for(int j=0; str[i]!=' '; j++,i++)//读入电话号码  
            {             
                dataInfo->phone += str[i];  
            }  
      
            while(str[i] == ' ')  
            {  
                i++;  
            }  
      
            for(int j=0; str[i]!=','; j++,i++)//读入地址  
            {             
                dataInfo->address += str[i];  
            }  
      
            if(n == 1)  
            {             
                Hashname(dataInfo);  
            }  
            else  
            {             
                Hashphone(dataInfo);//以电话为关键字  
            }  
      
            delete []str;  
            delete dataInfo;  
        }     
        fin.close();  
    }  
      
    int HashTable::Findname(string name)//根据姓名查找哈希表中的记录对应的关键码  
    {  
        int i = 0;  
        int j = 1;  
        int t;  
        int key = 0;  
          
        for(key=0, t=0; name[t] != '\0'; t++)  
        {  
            key = key + name[t];  
        }  
        key = key % 42;  
        while((value[key]->sign == '1') && (value[key]->name != name))  
        {    
            key = Random(key, i++);  
            j++;  
            if(j >= length) return -1;  
        }  
        return key;  
    }  
      
    int HashTable::Findphone(string phone)//根据电话查找哈希表中的记录对应的关键码  
    {    
        int key = 0;  
        int t;  
          
        for(t=0; phone[t] != '\0' ; t++)  
            {  
                    key = key + phone[t];  
            }  
        key = key % 42;  
        int j = 1;  
        while((value[key]->sign == '1') && (value[key]->phone != phone))  
        {  
            key = Rehash(key, phone);  
            j++;  
            if(j >= length)   
                    {  
                        return -1;  
                    }  
            }  
        return key;  
    }  
      
    void main()  
    {  
        //WriteToOldTxt();    
        int k;  
        int ch;   
        char *Fname;  
        HashTable *ht = new HashTable;  
        while(1)  
        {  
            system("cls");//cls命令清除屏幕上所有的文字  
            cout << "欢迎使用本系统!" << endl << endl;  
            cout << "请选择数据" << endl;  
            cout << "1.使用已有数据文件" << endl;  
            cout << "2.随机生成数据文件" << endl;  
            cout << "0.结束" << endl;  
            cout << "输入相应序号选择功能:";  
            cin >> k;  
            switch(k)  
            {  
            case 0:  
                return;  
            case 1:  
                Fname = "old.txt";//从数据文件old.txt(自己现行建好)中读入各项记录  
                break;  
            case 2:  
                ht->Rafile();  
                Fname = "new.txt";//由系统随机产生各记录,并且把记录保存到new.txt文件中  
                break;  
            default:  
                cout << "输入序号有误,退出程序。" << endl;   
                return;  
            }  
      
            do  
            {  
                system("cls");  
                cout << " 请选择查找方式" << endl;  
                cout << "1.通过姓名查找" << endl;  
                cout << "2.通过电话查找" << endl;  
                cout << "输入相应序号选择功能:";  
                cin >> ch;  
                if((ch != 1) && (ch != 2))  
                    cout << "输入序号有误!" << endl;  
            }while((ch != 1) && (ch != 2));  
      
            ht->Hash(Fname, ch);  
            while(ch == 1)  
            {  
                int choice;  
                cout << endl << "请选择功能" << endl;  
                cout << "1.输入姓名查找数据" << endl;  
                cout << "2.显示哈希表" << endl;  
                cout << "0.退出"<<endl;  
                cout << "输入相应序号选择功能:";  
                cin >> choice;  
                switch(choice)  
                {  
                case 1:   
                    {//注意此处应该加上大括号  
                        int key1;                     
                        string name;                      
                        cout << "请输入姓名:";  
                        cin >> name;                    
                        key1 = ht->Findname(name);  
                        ht->Outfile(name, key1);  
                        ht->Outhash(key1);     
                    }  
                    break;  
      
                case 2:   
                    {  
                        for(int i=0; i<HASH_MAXSIZE; i++)  
                        {  
                            if(ht->value[i]->sign!='0')  
                            {  
                                ht->Outhash(i);   
                            }  
                        }     
                    }                             
                    break;  
      
      
                default:  
                    cout << endl << "您的输入有误!" << endl;                  
                }  
      
                if(choice == 0)   
                {  
                    return;  
                }  
            }  
      
            while(ch == 2)  
            {  
                int choice;  
                cout << endl << "请选择功能" << endl;  
                cout << "1.输入电话查找数据" << endl;  
                cout << "2.显示哈希表"<<endl;  
                cout << "0.退出"<<endl;  
                cout << "输入相应序号选择功能:";  
                cin >> choice;  
                switch(choice)  
                {  
                case 1:   
                    {  
                        int key2;                     
                        string phone;                     
                        cout << "请输入11位的电话号码:";  
                          
                        do  
                        {  
                            cin >> phone;                       
                            if(phone.length() != 11)                      
                            {  
                                cout << "电话号码应为11位!\n请重新输入:";  
                            }  
                                  
                        }while(phone.length() != 11);  
                          
                        key2 = ht->Findphone(phone);  
                        ht->Outfile(phone, key2);  
                        ht->Outhash(key2);  
                    }  
                    break;  
      
                case 2:   
                    {  
                        for(int i=0; i<HASH_MAXSIZE; i++)  
                        {  
                            if(ht->value[i]->sign != '0')   
                            {  
                                ht->Outhash(i);   
                            }  
                        }  
                    }                 
                    break;  
      
                default:  
                     cout << endl << "您的输入有误!" << endl;                  
                }  
      
                if(choice == 0)   
                {  
                    return;  
                }  
            }  
      
            while((ch != 1) && (ch != 2))  
            {  
                cout << "您的输入有误!请输入相应需要选择功能:";  
            }  
        }  
        system("pause");      
    } 

     这是我的课设题目,应该没有太大问题:

课题概述

设计散列表实现电话号码查找系统。

要求能以姓名或是电话号码的形式查出对应的记录。

 

程序分析设计部分

    程序的功能

每个记录有下列数据项:用户名、电话号码、地址;
从键盘输入各记录,以用户名(汉语拼音形式)为关键字建立散列表;
要求给定一个电话号码,能查找出相关记录;

    需求分析

    首先要通过键盘输入相关的信息,一边输入一边往表里面添加相关的记录。

   以姓名为关键字(姓名是拼音的,取一个首字母),建立散列表。

   以电话号码为关键字建立第二个散列表,

能够根据姓名或者电话号码为关键字查找到相应的记录

系统操作演示部分

#include "stdafx.h"

#include <stdio.h>

#include<stdlib.h>

#include<string.h>

#define size 100

#define n 13


typedef struct node {


      int number;

      char address[size];

      char name[size];

      struct node *next;


}newnode, *anode;


void HashLink(newnode **p) {

      for (int i = 0; i < n;i++) {//n为最多查询的记录13

             p[i] = NULL;

      }

      printf("散列表初始化完毕!");

}


void HashAddName(newnode **p) {//添加记录,以姓名为关键字

      int i, v;  

      printf("请输入电话号码:(若无更多记录请输入-1)\n");

      scanf("%d", &v);

      while (v != -1) {

             anode e = (anode)malloc(sizeof(newnode));

             e->number = v;

             printf("请输入地址:\n");

             scanf("%s", e->address);

             printf("请输入姓名:(以拼音形式)\n");

             scanf("%s", e->name);

             i = e->name[0];//取名字的首字母

             i = i%n;

             e->next = p[i];//

             p[i] = e;

             printf("请输入电话号码:(若无更多记录请输入-1)\n");

             scanf("%d", &v);

      }

}

      void SearchHash(newnode **p) {

             //查询记录,也用链地址法

             char a[size];//定义一个char数组

             anode t;

             int i;

             printf("请输入要查询用户名:\n");

             scanf("%s", a);

             i = (int)a[0];

             i = i%n;

             t = p[i];

             while (t&&strcmp(t->name, a) != 0) {

                    t = t->next;

             }


             if (t == NULL) {

                    printf("您所查询的用户不存在!\n");

             }


             else {

                    printf("------------------------------------------\n");

                    printf("姓名:%s\n",t->name);

                    printf("电话:%d\n",t->number);

                    printf("地址:%s\n",t->address);

                    printf("------------------------------------------\n");

             }


      }


      void hashinput2(newnode **p) {//添加记录(以号码为关键字)


             int t, v;

            

             printf("请输入电话号码:(若无更多记录请输入- 1) \n");

             scanf("%d", &v);

             while (v != -1) {

                    anode e = (anode)malloc(sizeof(newnode));

                    e->number = v;


                    printf("请输入地址\n");


                    scanf("%s", e->address);


                    printf("请输入姓名:(以拼音形式)\n");


                    scanf("%s", e->name);


                    t = e->number%n;


                    e->next = p[t];


                    p[t] = e;


                    printf("请输入电话号码:(若无更多记录请输入- 1) \n");            

                    scanf("%d", &v);


             }


      }

            


void SearchPhone(newnode **p){//查询记录(以号码为关键字)链地址法


          int d, h;

             anode t;

             printf("请输入所要查询的电话号码:\n");

              scanf("%d", &d);

          h = d%n;

          t = p[h];

      while (t&&t->number != d) {


             t = t->next;

      }


      if (t == NULL) {

             printf("不好意思您所要查询的号码不存在哦~\n"); 

      }

      else {

             printf("------------------------------------------\n");


             printf("姓名:%s\n",t->name);


             printf("电话:%d\n",t->number);

             printf("地址:%s\n",t->address);

             printf("------------------------------------------\n");


      }

}

int main() {

      int j1;

      node *p[n];

      HashLink(p);//散列表初始化

      printf("欢迎进入~~!\n");

      printf("step1:添加记录\n");

      printf("step2:查询记录\n");

      printf("------------------------------------------\n");

      printf("请添加记录(以用户名为关键字)\n");

      HashAddName(p);

      printf("请添加记录(以电话号码为关键字)\n");

      hashinput2(p);

      printf("------------------------------------------\n");

      printf("请选择功能\n");

      printf("1.以用户名为关键字查询记录\n");

      printf("2.以电话号码为关键字查询记录\n");

      scanf("%d", &j1);

      switch (j1)

      {

      case 1:

             SearchHash(p);

             printf("请输入电话号码查询记录:\n");

      case 2:

             SearchPhone(p); break;

     

      }

      return 0;

}

 

 

  1. 代码演示部分

测试数据:

1、8870774 四川省成都市 TanMin

2、8475257 江西省赣州市 YangDan

3、8754455 北京市朝阳区 YanyiYin

 

 

    系统小结

      程序设计过程中遇到的问题及解决过程

       建立散列表时要建立相应的哈希函数,选用直接取余法:f(x):= x mod maxM ;对一个素数取模。这里maxM 为长度n=13。

       在设计关键字的时候原本想用中文姓名直接存,后来涉及到字符的存取比较麻烦。因此改用题目给出的用中文拼音形式。

       用电话号码查找时还是建立了第二张散列表,以电话号码为关键字。

       有多种方法解决冲突,如开放地址法等,最后选用链地址法解决冲突。

       涉及到要结束循环的问题,所以说需要先输入电话号码,以电话号码作为结束的条件。

 

  • 15
    点赞
  • 111
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值