哈希表实现的统计关键字频度

来源:互联网 发布:发条js调试工具 编辑:程序博客网 时间:2024/05/22 00:37
#include <stdio.h>#include <string.h>#include <iomanip.h> //参数化输入\输出#include <stdlib.h>#include <conio.h>//using namespace //名称空间#define TOTAL 40               //39个关键字#define MAXLEN 10              //关键字长度#define HASHLEN 41             //哈希表长度41#define M 40typedef struct             //哈希表 结构体   {char keyword[MAXLEN];     //关键字int count;             //记录频度int con;               //记录冲突次数}HASH;//全局变量int cont=0;               //统计关键词个数char KeyWords[TOTAL][MAXLEN]={ "asm","auto","break","case","cdecl","char",                               "const","continue","default","do","double",   "else","enum","extern","far","float","for",   "goto","huge","if","int","interrupt","long",   "near","pascal","register","return","short",   "signed","sizeof","static","struct","switch",   "typedef","union","unsigned","void","volatile",                               "while"};                //C语言中的39个关键字存入二维数组中,排好序的数组HASH HS[HASHLEN];      //建立结构体HS//函数声明void Show(int key);int Read(char *filename);   int isLetter(char ch);int isKeyWords(char *word);int FindHX(char *keyword);int CreatHX(char *keyword);int GetFreePos(int key);int GetKey(char *keyword);void main(){char orz;     int flag=1,i,count,key,has;char filename[128],word[MAXLEN];    while(flag){printf("\t\tA.读取一个文件\n");    printf("\t\tB.输出Hash表(关键字总数,冲突次数)\n");    printf("\t\tC.查询某关键字在Hash表中的情况\n");    printf("\t\tD.显示Hash表中的冲突关键字\n");    printf("\t\tE.显示C语言关键字的Hash函数值(作为对照)\n");    printf("\t\tF.退出\n\n");printf("\t\t请输入序号(A--F):");        scanf("%c",&orz);switch(orz) //选择  {    case 'a':case 'A':system("cls");                         //清屏函数                printf("请输入要读取的文件名(文件必须与程序在同一目录下):");    //比如输入:a.cppscanf("%s",&filename);Read(filename);    printf("\n按任意键返回...");    getch();    system("cls");break;    case 'b':case 'B':getchar();system("cls");printf("每次显示5行,请按回车键继续!\n");for(i=0;i<HASHLEN;i++){      Show(i);     if((i+1)%5==0)getchar();  //为了清晰,每次显示5行}    printf("关键字总数为: %d\n",cont);    printf("\n按任意键返回...");    getch();    system("cls");    break;    case 'c':case 'C':system("cls");printf("请输入你想要查找的关键字: ");    scanf("%s",&word);    printf("\n");    Show(FindHX(word));printf("\n按任意键返回...");    getch();    system("cls");    break;    case 'd':case 'D':system("cls");    printf("\t冲突关键字列表\n\n");    count=0;    for(i=0;i<HASHLEN;i++){    if(strlen(HS[i].keyword)>0){    key=GetKey(HS[i].keyword);    if(key!=i){    count++;    printf("\t关键字:%s",HS[i].keyword);    printf("\t哈希表当前位置:%d",i);    printf("\t冲突次数:%d\n",HS[i].con);}}}    if(count==0)     printf("没有冲突\n");    else         printf("\n\t\t\t冲突关键字共:%d个\n",count);printf("\n按任意键返回...");    getch();    system("cls");    break;    case 'e':case 'E':getchar();system("cls");printf(" C语言中的关键字和其在哈希表的位置:\n");    for(i=0;i<TOTAL;i++){has=GetKey(KeyWords[i]);printf("[%-2d]%-11s",has,KeyWords[i]);if((i+1)%5==0)    printf("\n");}    printf("\n");printf("\n按任意键返回...");    getch();    system("cls");break;    case 'f':case 'F':flag=0;break;default:    system("cls");}}}int Read(char *filename){char word[MAXLEN],ch,ch1;int i;FILE *read;                            //建立一个指像FILE类型结构体的指针变量    if((read=fopen(filename,"r"))==NULL)   //以只读方式读取文件,如果为空执行下面的语句{printf("\n文件不存在,请确认好再输入!");return -1;                     //跳出Read函数}while(!feof(read))          //feof()检测文件是否结束,到末尾函数值为“真”即非0{i=0;ch=fgetc(read);         //读取一个字符if (ch=='/')            //遇到‘/’就再读取一个字符{ch1=fgetc(read);if(ch1=='/')           //遇到“//”注释while(ch1!='\n'){ch1=fgetc(read);}else if (ch1=='*')    //遇见“/*”注释{ch1=fgetc(read);while(ch1!='*'){ch1=fgetc(read);if(ch1=='*'){ch=fgetc(read);if(ch=='/')break;}}}}while(isLetter(ch)==0&&feof(read)==0)ch=fgetc(read);     //如果不是字母就接着读取,关键字都是由字母组成的while(isLetter(ch)==1&&feof(read)==0){if(i==MAXLEN){while(isLetter(ch)==1&&feof(read)==0){ch=fgetc(read);       //超过MAXLEN的长度则一定不为关键字,把余下连一起的字母都读取}i=0;break;}else{word[i++]=ch;             //把读取到的字母存入word数组中ch=fgetc(read);}}word[i]='\0';if(isKeyWords(word)){CreatHX(word);}}fclose(read);printf("\n读取成功,文件中关键字已经存入hash表,请继续操作");}int isLetter(char ch) //判断是否是字母,因为关键字都是英文单词{//if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))if((ch>='a'&&ch<='z'))return 1;           //是字母就返回1elsereturn 0;           //不是字母就返回0}int FindHX(char *keyword)   //查找哈希表,分块查找{int key,find,tem=0;if(!isKeyWords(keyword))    //用于查找制定关键字时判断是否为关键字return -1;key=GetKey(keyword);if(strcmp(HS[key].keyword,keyword)==0)return key;for(find=key+1;find<HASHLEN;find++){                            //线性探查法顺序查找哈希表中是否已存在关键字tem++;                   //统计冲突次数if(strcmp(HS[find].keyword,keyword)==0){HS[find].con=tem;        //若有相等的就把冲突的次数存入数组的con中return find;}}for(find=0;find<key;find++)   //后面的找不到再从前面开始找{tem++;if(strcmp(HS[find].keyword,keyword)==0){HS[find].con=tem;return find;}}return -1;}int CreatHX(char *keyword)     //建立哈希表,加个*是因为word是一个数组{int key;if(!isKeyWords(keyword))   //不是关键字跳出此函数return -1;             key=GetKey(keyword);       //计算哈希值,根据所给哈希函数计算得出的结果if(strlen(HS[key].keyword)>0) //判断关键字表中该位置是否存在关键字,strlen用于计算()内的字符串长度{      //已经存在有关键字if(strcmp(HS[key].keyword,keyword)==0){  //再判断哈希表中该位置的关键字是否相同HS[key].count++;               //相同就频度加1return 1;                      //跳出函数}key=FindHX(keyword);  //不相同,继续查找if(key<0)             //没有找到相等的keyword{key=GetFreePos(GetKey(keyword));if(key<0)                 //哈希表满或者计算的哈希值有问题return -1;strcpy(HS[key].keyword,keyword);  //将关键字插入哈希表}if(key<0)return -1;HS[key].count++;}else  //该位置为空,直接将关键字插入该位置中{strcpy(HS[key].keyword,keyword);HS[key].count++;}return 1;}int GetFreePos(int key)  //在哈希表中给关键字找个位置插进去{int find,tem=0;if(key<0||key>=HASHLEN)      return -1;for(find=key+1;find<HASHLEN;find++)  //先找后面的位置{tem++;if(strlen(HS[find].keyword)==0)  //若这个地方为空{    HS[find].con=tem;            //把冲突的次数存入con中    return find; }}for(find=0;find<key;find++)          //若后面没有地方可以插入,再找前面的位置{tem++;if(strlen(HS[find].keyword)==0){HS[find].con=tem;return find;}}return -1; //哈希表已满}void Show(int key){if(key<0||key>=HASHLEN){printf("关键字不存在!\n");return;}if(strlen(HS[key].keyword)==0){printf("哈希表位置: %d  记录是空的!\n",key);return;}printf("哈希表位置: %d   关键字: %-11s出现次数: %d\n",key,HS[key].keyword,HS[key].count);cont++;}int GetKey(char *keyword)  //哈希函数{  //Hash函数为:Hash(Key)=[(Key的首字母序号)*100+(Key的尾字母序号)] Mod 41return ( keyword[0]*100+keyword[strlen(keyword)-1] ) % 41; }int isKeyWords(char *word){ int low,high,mid;  low=0;high=M-1;  while(low <= high)  { mid=(low+high)/2;    if(strcmp(word,KeyWords[mid])==0) return(1);if(strcmp(word,KeyWords[mid])==-1) high=mid-1;                              else low=mid+1;  }  return(0);}/*int isKeyWords(char *word)    //判断是否关键字{int i;for(i=0;i<TOTAL;i++)if(strcmp(word,KeyWords[i])==0)return 1; return 0;}*/

 
原创粉丝点击