zoukankan      html  css  js  c++  java
  • 有关统计单词频率的算法c语言实现

    转自:http://blog.csdn.net/junli0310/article/details/2281428

    从一文本中读取单词,统计其出现的频率,并按频率大小输出到另一文本中。这里的单词是分二种,一种是ASCII码大于0x20小于0X80字符,第 二种是小于0x20以及大于0x80的字符。这里我用的是哈希表,这样能很快查找读取的单词是否已经存在。排序我用的是二个循环,按理来说可以改进。

    下面是我的算法。有些地方还需要改进。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    #define FOOL int
    #define TURE 1
    #define FALSE 0
    #define MAXWORD 256
    #define hashnum 1024

    /*采用哈希表结点结构*/
    typedef struct Hash{
    int count;
    char str[1]; /*不一定为1,而是动态分配*/
    }Hash_table;

    Hash_table hash_table[hashnum];

    char buffer[256]; /*缓冲区大小,用来暂时存储单词*/
    int tail_prob; /*缓冲区结束位指针 */
    int Hcount = 0; /*用来计算有多少单词*/

    /******************************************************************/
    /** 初始化操作 **/
    /** **/
    void initial_buffer ()
    {
    for (tail_prob = 0; tail_prob < MAXWORD ;tail_prob++)
    {
    buffer[tail_prob++] = 0;
    }
    tail_prob = 0;
    }

    void initial_hashtable ()
    {
    unsigned int i;
    i = 0;
    while (i < hashnum)
    {
    hash_table[i].count = 0;
    i++;
    }
    }
    /******************************************************************/
    /** 关于缓冲区的操作 **/
    /** **/

    /*把一个字符拷贝到缓存区中*/
    void copytobuffer (char character)
    {
    if (tail_prob >= MAXWORD)
    {
    printf("Usag:this word is too long!");
    exit (-1);
    }
    buffer[tail_prob++] = character;
    }

    /*清除缓冲区*/
    void clear_buffer ()
    {
    while (tail_prob != 0)
    {
    buffer[--tail_prob] = 0;
    }
    }

    /**************************************************************/
    /** 找哈希表的关键字,这里使用的是把字符串的值相加再求与哈希表**/
    /**长度的余 **/
    unsigned int get_key (char *str)
    {
    unsigned result = 0;
    do
    {
    result = result + (*str);
    str++;
    }while (*str != NULL);
    result = result % hashnum;
    return result;
    }

    /***************************************************************/
    /**看哈希表中是否有对应的单词,有返回真 **/
    /** **/
    int find_match ()
    {
    int i;
    char *str;
    char *temp;
    int len1; /*缓冲区中单词的长度*/
    int len2; /*哈希表中单词的长度*/
    int index;

    str = buffer;
    index = get_key (buffer);
    temp = hash_table[index].str;
    len1 = strlen (buffer);
    len2 = strlen (temp);

    while (hash_table[index].count)
    {
    if (len1 == len2) /*些比较len1和len2是否相等,如果不等再比较*/
    {
    for (i = 0;i<len1 && *str == *temp;i++)
    {
    str++;
    temp++;
    }
    if (i != len2)
    {
    index = (index + 1) % hashnum;
    temp = hash_table[index].str;
    str = buffer;
    }
    else //能找到
    {
    hash_table[index].count++;
    return TRUE;
    }
    }
    else
    {
    index = (index + 1) % hashnum;
    temp = hash_table[index].str;
    str = buffer;
    }
    }
    }

    /***************************************************************/
    /** 根据缓冲区里面的字符生成哈希表 **/
    /** **/
    void addtoHash()
    {
    char str_temp[256];
    char *str;
    char *temp;
    int len;
    unsigned int index;
    int i;

    i=0;
    str = str_temp;
    strcpy (str,buffer);
    index = get_key (str);
    len = strlen(str);
    temp = hash_table[index].str;

    while (hash_table[index].count) /*找到没有被储存的结点*/
    {
    index = (index + 1) % hashnum;
    }
    hash_table[index].count++;
    while (i < len) /*复制字符串*/
    {
    *temp++ = *str++;
    i++;
    }
    }

    /***************************************************************/
    /** 排序后输出到out文件中 **/
    /** **/
    void Hash_sort(FILE *out)
    {
    int index;
    unsigned int symbol; /*最小值*/
    int num;
    int len;
    int i = 0;
    index = 0;

    /*排序输出到out文件中,共有Hcount个单词*/
    while (i < Hcount)
    {
    /*找到第一个遇见的频率非零的结点*/
    while (hash_table[index].count == 0)
    {
    index ++;
    }
    symbol = hash_table[index].count; /*充当最小值*/
    num = index;
    index++;
    while (index < hashnum)
    {
    if (hash_table[index].count < symbol && hash_table[index].count)
    {
    symbol = hash_table[index].count;
    num = index;
    }
    index ++;
    }
    /*找到了最小值*/
    len = strlen (hash_table[num].str);
    printf("%d ",hash_table[num].count);
    printf("%s/n",hash_table[num].str);
    fprintf(out,"%s,%d/n",hash_table[num].str,hash_table[num].count);

    hash_table[num].count = 0;
    i++;
    index = 0;
    }
    }


    /*****************************************************************
    /*找文件in中单词出现的频率,存储其单词以及其频率,调用find_match
    */
    /*输入的字符小于等于Ox20或者大于0x80时说明不是数字或者字母。但是*/
    /*也能组成一个单词 */
    void find_frquence(FILE *in,FILE *out)
    {
    char character;
    FOOL flag;
    flag = 1; /*开关语句*/

    initial_buffer();
    initial_hashtable ();

    /*当没有到文件结束时*/
    character = fgetc (in);
    do
    {
    if (character >0x20 && character < 0x80)
    {
    if (flag)
    {
    copytobuffer (character);
    }
    else /*新单词,且是字母和数字的组合*/
    {
    buffer[tail_prob] = '/0';/*表示结束*/
    if(find_match ()) /*如果能够找到,相对应的频率加1*/
    {
    // Tprob->count++;
    }
    else /*不能找到,则生成一个新的结点加入孩子兄弟链表中*/
    {
    addtoHash ();
    Hcount++;
    }
    clear_buffer ();
    copytobuffer (character);
    flag = !flag;
    }
    }
    else
    {
    if (character <= 0x20 || character >= 0x80)
    {
    if (flag)
    {
    buffer[tail_prob] = '/0';
    if (find_match ()) /*如果能够找到,则对应的频率加1,find_match实现频率加1*/
    {
    // Tprob->count++;
    }
    else /*不能找到,则到哈希表中*/
    {
    addtoHash ();
    Hcount++;
    }
    clear_buffer (); /*清除缓冲区*/
    copytobuffer (character);
    flag = !flag;
    }
    else
    {
    copytobuffer (character);
    }
    }
    }// if - else 结束
    }while ((character = fgetc (in)) != EOF);

    /*处理最后缓冲区所存储的单词*/
    if(find_match())
    {
    // Tprob->count++;
    }
    else
    {
    addtoHash();
    Hcount++;
    }

    /*排序并按从小到大输出到out文件中*/
    Hash_sort(out);
    }


    /**************************************************************/

    void main(int argc,char *argv[])
    {
    FILE *in;
    FILE *out;
    char temp_string1[256];
    char temp_string2[256];
    if(argc < 2)
    {
    printf ("Usag:please input the correct filename");
    exit (-1);
    }
    if (strlen (argv[1]) >256 || strlen (argv[2]) > 256)
    {
    printf (" Usag:the filename is too long!");
    exit (-1);
    }

    strcpy (temp_string1,argv[1]);
    strcpy (temp_string2,argv[2]);
    in = fopen (temp_string1,"rb");
    out = fopen (temp_string2,"w");

    /*找到各个单词,并且存储其频率,按频率顺序排列后输出到out中*/
    find_frquence (in,out);

    fclose (in);
    fclose (out);
    }



  • 相关阅读:
    多测师讲解htm_L标题标签001_高级讲师 肖sir
    Shell特殊变量介绍与实践 $0
    shell 变量定义技巧总结
    shell 环境变量的知识小结
    前端 chrome查看html样式基本操作
    shell 命令 env
    date 命令
    shell 命令 set命令
    shell export 命令
    前端 html span标签
  • 原文地址:https://www.cnblogs.com/phoenixzq/p/2254690.html
Copyright © 2011-2022 走看看