• 分析一个文本文件(英文文章)中各个词出现的频率,并且把频率最高的10个词打印出来。


    设计分析:

    遇到这样一个程序设计,首先解决的是文件读入的问题(我选择读入txt),用C中的文件指针很容易解决;

    第二,英文文章中由英文字母,标点符号,其他字符组成,要将他们分离,这就用到了词法分析,将每个单词分离出来并且分析;

    第三,统计单词个数(不一样的单词各有几个),排序,输出频率最高的10个。

    要解决的是文件读取后储存问题,就是放在结构体中,单词的种类和数量统计起来。可以用结构体数组,可以用链表。

    统计后排序的问题,如果将整个结构体或链表排序,那将是一件好大的工程,但是题目只是将频率最高的10个词打印出来,就像每天人们听歌,排行榜上的第一页是用户听得最多的歌曲。于是,我只是初始化了一个结构体数组,长度为10,将10个排序,然后用最后一个,也就是这10个中频率最小的与其他的比较,如果有频率比他高的,则插入到这个长度为10 的结构体数组中。插入之后还是顺序的。这样就节省了很多的工作量。

    数据结构:

    储存单词的数据结构:

    ①结构体

    typedef struct
    {
        char danci[19];//储存单词
        int count;//记录单词个数,后面出现几次
    }sq;

    ②链表

    struct Word

    {
     char danci[19];
     int count;
     struct Word *next;
    };

    找出频率最高的十个单词

    for(i=10;i<n;i++)
     {
      if(frequency_max[9].count<word[i].count)
      {
       int a=8;
       while(frequency_max[a].count<word[i].count&&a>=0)
       {
        a--;
       }
       
       for(j=9;j>a+1;j--)
       {
        frequency_max[j]=frequency_max[j-1];
       }
       if(a<0)
         frequency_max[0]=word[i];
       else
        frequency_max[j]=word[i];
      }
     }

    代码:

    #include<iostream>
    #include<iomanip>
    #include<time.h>
    using namespace std;
    #define M 20000
     //文章单词个数
    
    typedef struct 
    {
        char danci[19];//储存单词
        int count;//记录单词个数,后面出现几次
    }sq;
    
    void main()
    {    
        double start,finish;
        start=(double)clock();
        sq word[M];
        sq t_word;
        double s,f;
        int K,n=0,i,j;
        char infile[10];
        s=(double)clock();
        cout<<"***********请输入文件路径:***********"<<endl;
        cin>>infile;//文件路径输入    
        f=(double)clock();//
        cout<<"输入文件路径的时间:"<<(f-s)/1000<<"s"<<endl;
    
        FILE *fp;
        char ch;
        //fp=fopen("d://pro.txt","r");
        if((fp=fopen(infile,"r"))==NULL)
        {
            cout<<"无法打开文件!"<<endl;
            exit(0);
        }
        s=(double)clock();
        while(!feof(fp))
        {
            ch=getc(fp);
            if(ch==' '||ch==10)
            {//虑空
                continue;
            }
            if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))              //发现一个单词
            {
                K=0;
                t_word.count=1;
                while((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch=='\''))
                {
                    if(ch>='A'&&ch<='Z')
                        ch+=32;//转换成小写
                    t_word.danci[K++]=ch;
                    ch=getc(fp);
                }
                t_word.danci[K++]='\0';
                      
                //一个单词结束
                j=n;
                
                for(i=0;i<j;i++) //与前面的单词比较
                {
                    if(strcmp(t_word.danci,word[i].danci)==0)
                    {    
                        word[i].count++;
                        break;    
                    }
                
                }
    
                if(n==0||i==j)
                {
                    word[n]=t_word;
                    n++;
                }
                
            }
        }
        f=(double)clock();
        cout<<"读文件,分出单词并统计的时间:"<<(f-s)/1000<<"s"<<endl;
    
        s=(double)clock();
        //输出频率最高的十个单词
        sq frequency_max[10];
        sq temp;
        for(i=0;i<10;i++)
        {
            frequency_max[i]=word[i];//初始化频率最高的十个单词为前十个单词
        }
    //前十个排序
        
        for(j=0;j<10;j++)
            for (i=0;i<10-j;i++)
                if(frequency_max[i].count<frequency_max[i+1].count)
                {
                    temp=frequency_max[i];
                    frequency_max[i]=frequency_max[i+1];
                    frequency_max[i+1]=temp;
                }
        for(i=10;i<n;i++)
        {
            if(frequency_max[9].count<word[i].count)
            {
                int a=8;
                while(frequency_max[a].count<word[i].count&&a>=0)
                {
                    a--;
                }
                
                for(j=9;j>a+1;j--)
                {
                    frequency_max[j]=frequency_max[j-1];
                }
                if(a<0)
                        frequency_max[0]=word[i];
                else
                    frequency_max[j]=word[i];
            }
        }
        f=(double)clock();
        cout<<"冒泡排序,搜索频率最高的10个单词的时间:"<<(f-s)<<"ms"<<endl;
        for(i=0;i<10;i++)
        {
            cout<<setiosflags(ios::left)<<setw(10)<<frequency_max[i].danci<<frequency_max[i].count<<endl;
        }
        finish=(double)clock();
        cout<<"总运行时间:"<<(finish-start)/1000<<"s"<<endl;
    }

    运行截图:

    运用结构体数组存储:

    运用链表存储:


    总结:

    我用9M的文本文件测试,发现时间主要花费在文件的io上,由上面截图可以看出链表的效率更低,排序的时间非常少,几乎可以忽略不计。IO由于是与硬件之间的操作,所以花费时间比较多,链表由于需要地址操作,效率也没有数组高。

  • 相关阅读:
    蓝桥杯真题(1)
    蓝桥杯------历届真题
    第三届蓝桥杯 c/c++真题
    数据库三大范式个人理解,书上讲的太抽象
    c#线程池ThreadPool实例详解
    c#多线程thread实例详解
    C#中异步使用及回调
    c# 多线程的几种方式
    C#中委托的同步和异步有什么区别
    C#设计模式——单例模式的实现
  • 原文地址:https://www.cnblogs.com/zhaotian/p/3577149.html
Copyright © 2020-2023  润新知