[算法]大文本文件中找词频最高的10个词

问题描述:一个大的英文文本,找到其中出现次数最高的10个单词

思路:

 大文本文件肯定是一边读入一边统计,并且要去掉标点符号,以空白分离单词。

 要找高频词汇,肯定是要所有的单词都要遍历一次的,关键就是怎么遍历了。为了时间效率高一点,可以采用类似二叉排序树的方法,单词以字母为序,比如abc排在edf前面,也排在acd前面。

每读入一个词就进行二叉树排序树的查找操作,找到了节点的统计字段加1,找不到插入。其次,还要维护大小为10数组存储当前出现次数最高的词和它们的出现次数,按降序排列。每在二叉排序树中成功查找到该次,更新该词的出现次数后,与前10数组进行比较,如果这个词已经出现前10数组那就直接更新对应的值,如果这个词没有出现,则删除最有一个,然后插入。

伪代码:

先定义几个数据结构:

typedef struct{

int count=0;    //统计出现次数

string content='';  //单词的拼写

} word;

typedef struct{    //二叉排序树的一个节点的结构

word node:null;   //单词的统计

biNode *left:null;  //左孩子

biNode *right:null; //右孩子 

} biTNode,*biTree;

word topTenWord[1..10] ;  //记录当前出现次数最高的10单词,按照从高到低排序,初始每个元素内容为word{null,0};

假设二叉树的查找算法search已经实现,查找成功更新词的出现次数不成功插入,返回插入的点或是找到的点。

算法

word[10] Count(filename){

//输入:文件的名称

//输出:前十的词频的数组

binaryTree=createBinaryTree();   //先建立一个二叉排序树

totalWordCount=0;  //文章里面的单词数

firstWorld= readfrom(filename);

topTenWord[1]={firstWorld,1};   //先把第一个词读入,这样可以避免越界检查

 while(oneword=readfrom(filename)){  //读入词

     totalWordCount++; 

   biTNode *p=search(bianryTree,oneworld); 

     if (p.node.count>topTenWord.last.count) {     //新词的出现次数比前10数组里面最小的出现次数大

       //从后往前找,找到第一个比它大或者等于它的

      i=10; 

       while(topTenWord[i].count<p.node.count) i--;   //不用判断越界,因为不会越界,i最多走到1.

       if (topTenWord[i].content==p.node.content){  //同一个词 

        topTenWord[i].count++;

      }

      else{

         for(j=9;j>i;j--){

          topTenWord[j+1]=topTenWord[j]; 

        } 

        topTenWord[i+1]=p.node;  //将当前单词复制过来,复制内容,不是复制指针

      } 

   } 

 //计算频率

for (i=1;i<=10;i++) {

 topTenWord[i]=topTenWord[i]/totalWordCount;

return topTenWorld; 

 

时间效率应该是nlog(n). 

posted @ 2012-04-22 10:19  orchid  阅读(9313)  评论(0编辑  收藏  举报