問題描述:一個大的英文文本,找到其中出現次數最高的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).