问题描述:
验证好的散列函数能将关键字均匀地散布在0~M-1之间:
Ø
编写程序将
《
双城记
》
中的
10000+
个单词,散列到
0~M-1
之间。
Ø
统计每个单词的散列值的出现频率,并按下面图的格式输出。
Ø
分别取不同的
M
,直观看看哪个
M
比较合适。例如,
M
可以取
97
,
997
,
1997
等。
Ø
查找某单词是否在
《
双城记
》
中出现?随机查找
100
个单词,估算一次查找的平均比较次数。
注意点:
1、hashnode结构中word中如果使用char* word,要记得分配其空间,最好还是使用char word【20】
2、scanf()不会读入‘\n’,所以要加一个getchar(),
3、当使用h(k)=k mod m 的除法散列法时,m最好选取一个不接近2或10的整数幂的素数
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define M 97
typedef long long int lli;
typedef struct HashNode
{
int count; //数据域
struct HashNode* next; //指针域
char word[20];//单词
}HashNode;
typedef struct
{
HashNode *head;
}Hashplot;
Hashplot table[M];
//初始化
int init()
{
if(table==NULL) return 0;
for(int i=0;i<M;i++)
{
table[i].head = (HashNode*)malloc(sizeof(HashNode));
table[i].head->next=NULL;
}
return 1;
}
//判断是否为英文字母
int judge(char c)
{
if((c>='a')&&(c<='z')) return 1;
else if((c>='A')&&(c<='Z')) return 1;
else return 0;
}
//除法散列函数
int division_h(char* s)
{
int i=0;
lli key=0;
while(s[i]!='\0')
{
if(!judge(s[i]))
{
i++;
continue;
}
key=(key*128+s[i])%M;
i++;
}
return key;
}
//哈希表插入元素
void insert_hash(char* s)
{
int key=division_h(s);//散列函数
HashNode* pnode= (HashNode*)malloc(sizeof(HashNode));
//头结点后没有元素的情况
if(table[key].head->next==NULL)
{
strcpy(pnode->word,s);
pnode->count=1;
//头插入
pnode->next=table[key].head->next;
table[key].head->next=pnode;
}
else
{
pnode=table[key].head->next;
if(strcmp(pnode->word,s)==0)
{
pnode->count++;
return;
}
while(pnode->next!=NULL)
{
if(strcmp(pnode->word,s)==0)
{
pnode->count++;
return;
}
else pnode=pnode->next;
}
HashNode* tmp=(HashNode*)malloc(sizeof(HashNode));
strcpy(tmp->word,s);
tmp->count=1;
tmp->next=pnode->next;
pnode->next=tmp;
}
}
//处理字符串
void handle(char* str,char* s,int l)
{
int i=0;
//前面开始去除符号
while(!judge(str[i]))
{
i++;
}
strcpy(s,str+i);
//从后往前,去除符号
while(!judge(s[l-1]))
{
s[l-1]='\0';
l--;
}
}
//获取键值
int search_hash(char* str)
{
int goal=division_h(str);
HashNode* pnode=table[goal].head->next;
while(pnode !=NULL)
{
if(strcmp(str,pnode->word)==0)
return pnode->count;
else
pnode=pnode->next;
}
return 0;
}
int main()
{
freopen("A Tale of Two Cities - Charles Dickens.txt","r",stdin);
init();
char str[20];
while(scanf("%s",str)!=EOF)
{
int l=strlen(str);
char s[20];
handle(str,s,l);
getchar();
insert_hash(s);
}
//读入关键词
freopen("words.txt","r",stdin);
while(scanf("%s",str)!=EOF)
{
getchar();
int num=search_hash(str);
printf("%s %d\n",str,num);
}
}