哈希表的实例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define Size 11
typedef struct{
 char name[30];
    char address[20];
 //float  num;
 char num[30];
 int c;//统计比较次数
}record;
typedef struct{
 record data[Size];
 int count;
 int size;
}Hashtable;
void init(Hashtable &h)
{
 for(int i=0;i<Size;i++)
 {h.data[i].num[0]=0;
 h.data[i].c=0;}//!
 h.size=Size;
 h.count=0;
}
int exchange(char str[])
{
 int i,n,sum=0;
 n=strlen(str);
 for(i=0;i<n;i++)
  sum=sum+str[i]-'0';
 return sum;
}
int HashSearch1(Hashtable &h,char *str,int &p) //线性探测
{
 int i,j,k=exchange(str);
 j=k%Size;
 if(strcmp(str,h.data[j].num)==0)
 {
  return j;
  h.data[j].c++;//!
 }//没有发生冲突,比较一次查找成功
 if(h.data[j].num[0]==0)
 {
  p=j;
  return 0;
 }
 else
 {
  h.data[j].c++;//!
  i=(j+1)%Size;//第1次解决冲突
  while(h.data[i].num[0]!=0&&i!=j) 
  {   
   if(strcmp(str,h.data[i].num)==0)
   {
    h.data[j].c++;//!
    return i;
   }//发生冲突,比较若干次查找成功
   i=(i+1)%Size;    //向后探测一个位置
  }
  if (i==j)
   printf("溢出\n");
  else      
  {
   p=i;
   h.data[j].c++;//!
   return 0;//查找不成功
  }
 }
}
int HashSearch2(Hashtable &h,char *str,int &p)
{
 int i,j,t=1,d=1;
 int k=exchange(str);
 j=k%Size;
 if(strcmp(str,h.data[j].num)==0)
 { 
  h.data[j].c++;//!
     return j;
 }  //没有发生冲突,比较一次查找成功
 if(h.data[j].num[0]==0)
 {
  p=j;
  return 0;
 }
 else
 {
  i=(j+d)%Size;//第1次解决冲突
  while(h.data[i].num[0]!=0&&i!=j) 
  {  
      if(strcmp(str,h.data[i].num)==0)
   {
        h.data[j].c++;//!
        return i;
   }
   if(t>0)
    t=-1*d*d;
   else
   {
    d=d+1;
    t=-1*d*d ;
   }
   i=(j+t+Size)%Size;    //探测一个新的位置
   while(i<0)
   {
    h.data[j].c++;//!
    i=(i+Size)%Size;     
  } }
      if (i==j)
       printf("溢出\n");
      else
   {
       p=i;
       h.data[j].c++;//!
       return 0;//查找不成功时插入
   }
  
 }
}
void disp(Hashtable h)
{
 printf("电话簿中所有电话记录如下:\n");
 for(int i=0;i<Size;i++)
 {
  if(h.data[i].num[0])
   printf("-.%7s s     %s\n",i,h.data[i].name,h.data[i].address,h.data[i].num);
 }
}
//
int compasl(Hashtable h)
{
 int sum=0;
 for(int i=0;i<Size;i++)
  sum+=h.data[i].c;
 return sum;
}
int menu()
{
 int num;
 while(1)
 {
  system("cls");
  printf("\n---------电话管理系统模拟(哈希表实现)---------\n");
  printf("\n**********************************************\n");
  printf("\n  0.退出电话簿             1.已存在的电话记录  \n");
  printf("\n  2.添加记录到电话簿1      3.添加记录到电话簿2 \n");
  printf("\n  4.查找电话簿1通讯人      5.查找电话簿2通讯人 \n");
  printf("\n  6.电话簿1查找ASL         7.电话簿2查找ASL    \n");
  printf("\n**********************************************\n");
  printf("\n----------------------------------------------\n");
  printf("\n请您选择操作(0--7):\n");
  scanf("%d",&num);
  if(num<0||num>7)
   printf("您的选择有误,请重新选择!\n");
  break;
 }
 return num;
}
void main()
{
 Hashtable h1,h2;
 int i,j,n,a,m,flag=1;
 char num[30];
 char name[30],address[50];
 init(h1);init(h2);
 while(1)
 {
  j=menu();
  switch(j){
  case 0:printf("(@ @) 谢谢使用,再见! (^ ^)\n");
   exit(0);
   getch();
   break;
  case 1:
   if(flag){
   FILE *fp;
   if((fp=fopen("1234.txt","r+"))==NULL)
   {
    puts("成功导入电话记录!");
    exit(0);
   }
         fscanf(fp,"%d",&n);
         for(i=0;i<n;i++)
   {
          fscanf(fp,"%s%s%s",name,address,num);
             HashSearch1(h1,num,a);
      
         strcpy(h1.data[a].num,num);
               strcpy(h1.data[a].address,address);
               strcpy(h1.data[a].name,name);
               h1.count++;
      
   }
   puts("\t成功将电话记录导入电话簿1!");
   disp(h1);
   fclose(fp);
   if((fp=fopen("1234.txt","r+"))==NULL)
   {
    puts("导入电话记录失败");
    exit(0);
   }
         fscanf(fp,"%d",&n);
         for(i=0;i<n;i++)
   {
          fscanf(fp,"%s%s%s",name,address,num);
             HashSearch2(h2,num,a);
      
         strcpy(h2.data[a].num,num);
               strcpy(h2.data[a].address,address);
               strcpy(h2.data[a].name,name);
               h2.count++;
      
   }
   puts("\t成功将电话记录导入电话簿2!");
   disp(h2);
   fclose(fp);
   printf("按任意键继续!\n");
   getch();}
   flag=0;
   break;
  case 2:
   printf("添加电话记录到电话簿1:\n");
   printf("请输入您要添加电话记录的数目:\n");
         scanf("%d",&n);
         for(i=0;i<n;i++)
   {
          printf("请输入第%d条电话记录的姓名、地址和电话号码(用空格隔开)\n",i+1);
          scanf("%s%s%s",name,address,num);
             if(HashSearch1(h1,num,a))
       {
              printf("已存在");
              i--;
       }
             else
       {
         strcpy(h1.data[a].num,num);
               strcpy(h1.data[a].address,address);
               strcpy(h1.data[a].name,name);
               h1.count++;
       }
   }
   disp(h1);
   printf("按任意键继续!\n");
   getch();
   break;
  case 3:printf("添加电话记录到电话簿2:\n");
   printf("请输入您要添加电话记录的数目\n");
         scanf("%d",&n);
         for(i=0;i<n;i++)
   {
          printf("请输入第%d条电话记录的姓名、地址和电话号码(用空格隔开)\n",i+1);
          scanf("%s%s%s",name,address,num);
             if(HashSearch2(h2,num,a))
       {
              printf("已存在");
              i--;
       }
             else
       {
         strcpy(h2.data[a].num,num);
               strcpy(h2.data[a].address,address);
               strcpy(h2.data[a].name,name);
               h2.count++;
       }
   }
   disp(h2);
   printf("按任意键继续!\n");
   getch();
   break;
  case 4:disp(h1);
   printf("请输入您要在电话簿1中查找的人的电话号码:\n");
   scanf("%s",num);
   printf("\n");
   if(m=HashSearch1(h1,num,a))
   {
           printf("查找的结果为:\n");
             printf("您要查找的人的姓名、地址和电话号码分别为:\n%s,%s,%s\n",h1.data[m].name,h1.data[m].address,h1.data[m].num);
   }
         else
    printf("对不起,没有您要找的人!\n");
   printf("按任意键继续!\n");
   getch();
   break;
  case 5:disp(h2);
   printf("请输入您要在电话簿2中查找的人的电话号码:\n");
   scanf("%s",num);
   printf("\n");
  if(m=HashSearch2(h2,num,a))
   {
           printf("查找的结果为:\n");
             printf("您要查找的人的姓名、地址和电话号码分别为:\n%s,%s,%s\n",h2.data[m].name,h2.data[m].address,h2.data[m].num);
   }
         else
    printf("对不起,没有您要找的人!\n");
   printf("按任意键继续!\n");
   getch();
   break;
  case 6:printf("在电话簿1中查找的ASL为:\n");
   printf("%d %d\n",compasl(h1),h1.count);
   printf("按任意键继续!\n");
   getch();
   break;
  case 7:printf("在电话簿2中查找的ASL为:\n");
         printf("%d %d\n",compasl(h2),h2.count);  
   printf("按任意键继续!\n");
   getch();
   break;
  }
 }
}


下面是课程设计的报告:

一、课程设计的目的与要求

    1. 目的: 应用数据结构和算法来设计相应的程序,培养学生问题求解模块的框架设计和详细设计、相关程序实现和调试能力,完成创新能力和实践能力的训练。

    2. 要求: 用高级程序设计语言C编码,用VC++开发平台调试。

二、设计正文

(一)  课程设计题目

    设计哈希表实现电话号码查询系统

(二)  需求分析

 设每个记录有下列数据项:电话号码、用户名、地址;

 (1)数据导入(从文件中读取各记录,分别以电话号码为关键字建立哈希表);

 (2)从键盘读记录,并插入到哈希表中;

 (3)查找并显示给定电话号码的记录;

 (4)将电话号码记录保存在文件中;

 (5)尝试各种不同类型处理冲突的方法,考察平均查找长度的变化。

分析:由于题目要求以电话号码为关键字建表,考虑到电话号码长短不一,如果直接以表示电话号码的字符串为关键字,可能会造成一定的麻烦。故而,利用一个函数将表示电话号码的字符串转换成其相应的数字,然后把这些数字之和作为关键字即可将上述麻烦解除。

(三)  概要设计

     为了实现上述程序的功能,需要定义下列抽象数据类型:

     ADT hashtable {

         数据对象:哈希表中存储的个条电话记录;

         数据关系:表中相邻元素之间有前去和后继的关系;

         基本操作:

            init(Hashtable &h)

              操作结果:初始化了哈希表;

        int exchange(char str[])

          操作结果:球取关键字;

        int HashSearch1(Hashtable &h,char *str,int &p)

          操作结果:在表中线性探测数据,返回数据的插入位置;

int HashSearch2(Hashtable &h,char *str,int &p)

  操作结果:在表中二次探测数据,返回数据的插入位置;

void disp(Hashtable h)

  操作结果:显示出哈希表中储存的电话记录;

}ADT hashtable

将每个人的信息作为一条记录,包括电话号码、用户名、地址,还有一个整型变量用来记录冲突的次数,便于计算ASL,然后哈希表由记录数组、表现存量、容量组成,具体数据类型见下:

typedef struct {

   char name[30];

    char address[20];

   char num[30];

 }record;

 

typedef struct{

   record data[Size];

   int count;

   int size;

}Hashtable;

   

    关键字处理-----利用一个函数将表示电话号码的字符串转换成其相应的数字,然后把这些数字之和作为关键字。具体函数见下:

 int exchange(char str[])

 {

   int i,n,sum=0;

   n=strlen(str);

   for(i=0;i<n;i++)

       sum=sum+str[i]-'0';

   return sum;

 }

 最后就是用两种方法建表,分别用线性和二次探测的方法来处理冲突。

 本程序所有函数清单:

 void init(Hashtable &h);//哈希表的初始化

 int exchange(char str[]);//求取关键字

 int HashSearch1(Hashtable &h,char *str,int &p);//线性探测处理冲突

 int HashSearch2(Hashtable &h,char *str,int &p);//二次探测处理冲突

 void disp(Hashtable h);//显示哈希表

 int menu();//主菜单

 void main();//主函数

各函数之间的调用关系是:

 

主函数main()

      

 

 

 

菜单函数menu()

 

 

 

 

 

 

 

 

 

 


 

 

线性探测解决冲突hashserch1()

查找用户

考察ASL1

二次探测解决冲突hashsearch2()

查找用户

考察ASL

显示电话簿disp()

 

(四)  详细设计

 1)为了实现上述程序的功能,需要定义下述数据类型:

   typedef struct{

   char name[30];

    char address[20];

   //float  num;

   char num[30];

   int c;//统计比较次数

 }record;      //记录

 

 typedef struct{

   record data[Size];

   int count;

   int size;

 }Hashtable;    //哈希表

 2)一些主要的函数:

 int exchange(char str[])    //关键字处理函数

 {

   int i,n,sum=0;

   n=strlen(str);

   for(i=0;i<n;i++)

       sum=sum+str[i]-'0';

   return sum;

 }

 int HashSearch1(Hashtable &h,char *str,int &p) //线性探测

 {

   int i,j,k=exchange(str);

   j=k%Size;

   if(strcmp(str,h.data[j].num)==0)

   {

       return j;

       h.data[j].c++;//!

   }//没有发生冲突,比较一次查找成功

   if(h.data[j].num[0]==0)

   {

       p=j;

       return 0;

   }

   else

   {

       h.data[j].c++;//!

       i=(j+1)%Size;//第1次解决冲突

       while(h.data[i].num[0]!=0&&i!=j) 

       {     

          if(strcmp(str,h.data[j].num)==0)

          {

              h.data[j].c++;//!

              return i;

          }//发生冲突,比较若干次查找成功

          i=(i+1)%Size;    //向后探测一个位置

       }

       if (i==j)

          printf("溢出\n");

       else        

       {

          p=i;

          h.data[j].c++;//!

          return 0;//查找不成功

       }

   }

}

 

int HashSearch2(Hashtable &h,char *str,int &p) //二次探测

{

   int i,j,t=1,d=1;

   int k=exchange(str);

   j=k%Size;

   if(strcmp(str,h.data[j].num)==0)

   { 

       h.data[j].c++;//!

       return j;

   }  //没有发生冲突,比较一次查找成功

   if(h.data[j].num[0]==0)

   {

       p=j;

       return 0;

   }

   else

   {

       i=(j+d)%Size;//第1次解决冲突

       while(h.data[i].num[0]!=0&&i!=j) 

       {  

           if(strcmp(str,h.data[j].num)==0)

          {

               h.data[j].c++;//!

               return i;

          }

          if(t>0)

              t=-1*d*d;

          else

          {

              d=d+1;

              t=-1*d*d ;

          }

          i=(j+t+Size)%Size;    //探测一个新的位置

          while(i<0)

          {

              h.data[j].c++;//!

              i=(i+Size)%Size;             

          }

           if (i==j)

              printf("溢出\n");

           else

          {

              p=i;

              h.data[j].c++;//!

              return 0;//查找不成功时插入

          }

        }

    }

  }

(五)  调试分析

本实验的运行环境是VC++。按照要求,应该事先导入一些记录,以下为本实验的测试数据:

4

侯进斌 北京 6627584

王璐 太原 6650370

 唐磊 天津 6626074

 高启波 太原 6651805

 然后按照菜单中的提示操作即可

 

(六)  使用说明

  程序名为hashtable.exe,运行环境为VC++。由于菜单中有详细的操作提示,您只要按照上面的提示一步一步进行操作即可。

(七)测试数据

  程序运行后将会出现以下菜单:

 

 

 

               

   选择1,立即会显示下面窗口,显示已存在的记录:      

 

    再选操作2,可以向电话簿1里添加记录,如下:

 

  操作3,向电话簿2中添加记录,如下:

 

  然后还可以进行查询操作,选4,可以在电话簿1中查询您想要的找的人的信息:

 

 同理,选5还可以在电话簿2中作相应的查询:

 

 如果您想比较着看一下在电话簿1中查找的速度(专业术语:ASL),可以选择操作6:

 

同理还可以查看电话簿2的这项功能:

 

如果您想结束操作,直接选0,即可退出该系统:

  

     以上就是本系统的主要功能。

三、课程设计总结或结论

1.完成的工作

该实验的所有要求:哈希表的创建,用两种不同的方法处理冲突,考察各种处理冲突方法的ASL;

2.未完成的工作

无;

3.所需做的改进

应该尝试更多的处理冲突的方法

一些代码的效率很低,有待改进

四、参考文献

《数据结构》(C语言版)  清华大学出版社 严蔚敏 吴伟民 编著

 


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值