利用哈希表统计关键字出现频率

           
问题描述:
验证好的散列函数能将关键字均匀地散布在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);
    }

}

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NightHacker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值