c++ 統計英文文本中每個單詞的詞頻並且按照詞頻對每行排序

前幾天寫了Apriori算法之後效率很差,在網上查了很多資料,另外的最大模式挖掘算法一般有FP-Growth 和 Ecalt 算法,這兩種效率比較高而FP-Growth算法構建FP-Tree的過程非常複雜,後來在網上找到了另外一種效率更優化且結構更簡單的算法,那就是北大鄧志鴻老師的PPV算法,看了論文以後覺得這確實是一個好的算法,因此打算加以實現。在實現的第一步就卡住了。在構造PPV-TREE/ FP-TREE 的第一步都是要統計每個事務的頻度並且對項集中按照頻度進行排序,雖然只是簡單的兩句話,可是當實現的時候就沒有說的這麼簡單了。我也用了一天的時間來實現這第一步。。。。。確實有些事不動手不知道難。在如何實現的問題上也經過了很多的思考,最初打算用map 來實現,後來爲了鍛鍊下就改用了Trie樹的方式,如果數據大最好的方式應該是map/reduce的成名函數 wordCount。好了下面直接上代碼.

  1. #ifndef TRIE_H  
  2. #define TRIE_H  
  3.   
  4. #include <fstream>  
  5.   
  6. class trie{  
  7.       
  8.     public:  
  9.         trie(std::string fname,char spl):filename(fname), sp(spl),root(NULL){}  
  10.         ~trie();  
  11.         void insert(std::string);  
  12.         int search(std::string);  
  13.         void openfile();  
  14.         std::string getFname();  
  15.         char getsp();  
  16.     private:  
  17.         struct node{  
  18.             char key;  
  19.             int count;  
  20.             node();  
  21.             node *child[26];  
  22.         };  
  23.         node *root;  
  24.         std::ifstream in;  
  25.         std::string filename;  
  26.         char sp;  
  27. };  
  28. #endif //end tire define  


  1. #include <iostream>  
  2. #include <cassert>  
  3. #include "trie.h"  
  4.   
  5. using namespace std;  
  6.   
  7. trie::node::node()  
  8. {  
  9.     count = 0;  
  10.     for(int i = 0; i<26; ++i)  
  11.         child[i] = NULL;  
  12. }  
  13.   
  14.   
  15. trie::~trie()  
  16. {  
  17.     if(in)  
  18.         in.close();  
  19.     delete root;  
  20. }  
  21.   
  22. void trie::openfile()  
  23. {  
  24.     in.open(filename.c_str());  
  25.     string line;  
  26.     assert(in != NULL);  
  27.   
  28.     while(getline(in, line)){  
  29.         string tmp;  
  30.   
  31.         while(line.find(sp) != -1)  
  32.         {  
  33.             tmp = line.substr(0,line.find(sp));  
  34.             insert(tmp);  
  35.             line = line.substr(line.find(sp)+1, line.size()-1);  
  36.         }     
  37.     }  
  38.   
  39.     insert(line);  
  40. }  
  41.   
  42. //trie 樹的插入過程,排除含有非英文字母的單詞,並且統計單詞出現的頻度  
  43. void trie::insert(string word){  
  44.     if(root == NULL)  
  45.     {  
  46.         root =new node;  
  47.     }  
  48.       
  49.     int index;  
  50.     node *loc = root;  
  51.     int pos = 0;   
  52.     while(loc != NULL && word[pos] != '\0')  
  53.     {  
  54.         if(word[pos] >='A' && word[pos] <= 'Z')  
  55.             index = word[pos] - 'A';  
  56.         else if(word[pos]>= 'a' && word[pos]<='z')  
  57.             index = word[pos] - 'a';  
  58.         else   
  59.             return;  
  60.           
  61.         if(loc->child[index] == NULL)  
  62.         {  
  63.             loc->child[index] = new node;  
  64.         }  
  65.         ++pos;  
  66.         loc =loc->child[index];  
  67.     }  
  68.   
  69.     ++(loc->count);  
  70. }  
  71.   
  72. string trie::getFname()  
  73. {  
  74.     return filename;  
  75. }  
  76.   
  77. char trie::getsp()  
  78. {  
  79.     return sp;  
  80. }  
  81.   
  82. //查找某個單詞出現的頻度,如果不存在返回-1  
  83. int trie::search(string word)  
  84. {  
  85.     node *loc = root;  
  86.     assert(root != NULL);  
  87.     int index = 0;  
  88.   
  89.     while(loc && word[index] != '\0')  
  90.     {  
  91.         int pos;  
  92.         if(word[index]>='A' && word[index]<='Z')  
  93.             pos = word[index] - 'A';  
  94.         else if(word[index]>='a' && word[index]<='z')  
  95.             pos = word[index] - 'a';  
  96.         else   
  97.             return  -1;  
  98.         loc = loc->child[pos];  
  99.         ++index;  
  100.     }  
  101.   
  102.     if(loc ==NULL)  
  103.         return -1;  
  104.   
  105.     return loc->count;  
  106. }  

  1. #ifndef SORT_DATA  
  2. #define SORT_DATA  
  3. #include "trie.h"  
  4. #include <vector>  
  5. #include <fstream>  
  6.   
  7. class sort_data{  
  8.     public:  
  9.         sort_data(trie *itree, int sup):tree(itree),support(sup){filename = itree->getFname(); split = itree->getsp();}  
  10.         ~sort_data();  
  11.         void openfile();  
  12.         void count_data();  
  13.     private:      
  14.         void sorts();  
  15.         int partion(int *a, int *b,int begin, int end);  
  16.         void quicksort(int *a, int *b, int begin,int end);  
  17.         std::vector<std::string> spl;  
  18.         trie *tree;  
  19.         std::string filename;  
  20.         std::ifstream in;  
  21.         std::ofstream out;  
  22.         int support;  
  23.         char split;  
  24. };  
  25. #endif //end define  

  1. // 整體功能是對一個文本中單詞進行詞頻統計,並且對該文本的每行進行排序,如果有相同單詞則合併爲一個  
  2. // 如果有兩個單詞詞頻相同那麼按照字典序進行排序。輸出文件名稱爲輸入文件名字+你定義的support  
  3. #include "sort_data.h"  
  4. #include "trie.h"  
  5. #include <iostream>  
  6. #include <cassert>  
  7. #include <sstream>  
  8. #include <map>  
  9.   
  10. using namespace std;  
  11.   
  12. sort_data::~sort_data()  
  13. {  
  14.     in.close();  
  15.     out.close();  
  16. //  delete tree;  
  17. }  
  18.   
  19. void sort_data::openfile()  
  20. {  
  21.     in.open(filename.c_str());    
  22.     assert(in != NULL);  
  23.       
  24.     stringstream ss;  
  25.     ss<<support;  
  26.   
  27.     string tmp = filename + ss.str();  
  28.   
  29.     out.open(tmp.c_str());  
  30. }  
  31.   
  32. //將文本的每一行進行拆分,將每個單詞放到vector<string> spl 中  
  33. void sort_data::count_data()  
  34. {  
  35.     string line;  
  36.   
  37.     while(getline(in,line))  
  38.     {  
  39.         spl.clear();  
  40.         string tmp;  
  41.   
  42.         while(line.find(split) != -1)  
  43.         {  
  44.             tmp = line.substr(0,line.find(split));  
  45.             spl.push_back(tmp);  
  46.             line = line.substr(line.find(split)+1,line.size()-1);  
  47.         }  
  48.           
  49.         spl.push_back(line);  
  50.         sorts();  
  51.     }  
  52. }  
  53.   
  54. //對排序後的單詞進行去重和按照字典序排列的過程,使用了map<string, int>  
  55. void sort_data::sorts()  
  56. {  
  57.     int n = spl.size();  
  58.     int a[n];  
  59.     int tmp = 0;  
  60.   
  61.     for(int i = 0;i<n; ++i)  
  62.     {  
  63.         if(tree->search(spl[i])>=support)  
  64.         {  
  65.             a[tmp] = i;  
  66.             ++tmp;  
  67.         }  
  68.     }  
  69.       
  70.     int b[tmp];  
  71.     int c[tmp];  
  72.       
  73.     for(int k = 0; k<tmp;++k)  
  74.     {  
  75.         c[k] = k;     
  76.     }  
  77.   
  78.     for(int j = 0; j<tmp; ++j)  
  79.     {  
  80.         int in = a[j];  
  81.         b[j] = tree->search(spl[in]);  
  82.     }  
  83.     quicksort(b,c,0,tmp-1);  
  84.   
  85.     for(int i = 0; i<tmp; ++i)  
  86.     {  
  87.        int j = c[i];  
  88.          j = a[j];  
  89.     }  
  90.   
  91.     map<string, int> qop;  
  92.     string line;  
  93.     int cp = 0;  
  94.     if(tmp == 1)  
  95.     {  
  96.         int i = a[0];  
  97.         line = spl[i]+'\n';  
  98.     }  
  99.       
  100.     else{  
  101.     while(cp<tmp){  
  102.         int i;  
  103.         if(cp+1 == tmp)  
  104.         {  
  105.             i = c[cp];  
  106.             i = a[i];  
  107.             line =line +spl[i]+'\n';  
  108.             break;  
  109.         }  
  110.   
  111.         if(b[cp]>b[cp+1])  
  112.         {  
  113.             i = c[cp];  
  114.             i = a[i];  
  115.             line = line+spl[i]+' ';  
  116.             ++cp;  
  117.         }  
  118.   
  119.         else  
  120.         {  
  121.             while(cp+1 != tmp && (b[cp] == b[cp+1]))  
  122.             {  
  123.                 i = c[cp];  
  124.                 i = a[i];  
  125.                 string s = spl[i];  
  126.                 ++qop[s];  
  127.                 ++cp;  
  128.             }  
  129.              i = c[cp];  
  130.              i = a[i];  
  131.              string s =spl[i];  
  132.              ++qop[s];  
  133.              ++cp;  
  134.             for(map<string,int>::iterator it = qop.begin(); it != qop.end(); ++it)  
  135.             {  
  136.                 line = line+it->first+' ';  
  137.             }  
  138.             qop.clear();  
  139.         }  
  140.     }  
  141.     line = line + '\n';  
  142.     }  
  143.       
  144.     out<<line;  
  145.     out<<endl;  
  146. }  
  147.   
  148. //對每一行出現次數大於support的單詞進行排序過程,a爲詞頻數組,b爲伴隨數組  
  149. int sort_data::partion(int *a,int *b,int begin, int end)  
  150. {  
  151.     int index = a[end];  
  152.     int start = begin;  
  153.     for(int i = begin; i<end; ++i)  
  154.     {  
  155.         if(a[i]>= index)  
  156.         {  
  157.             swap(a[start],a[i]);  
  158.             swap(b[start],b[i]);  
  159.             ++start;  
  160.         }  
  161.     }  
  162.     swap(a[start],a[end]);  
  163.     swap(b[start],b[end]);  
  164.     return start;  
  165. }  
  166.   
  167. void sort_data::quicksort(int *a,int *b,int begin,int end)  
  168. {  
  169.     if(begin<end)  
  170.     {  
  171.         int i = partion(a,b,begin,end);  
  172.   
  173.         quicksort(a,b,begin,i-1);  
  174.         quicksort(a,b,i+1,end);  
  175.     }  
  176. }  

  1. #include "trie.h"  
  2. #include <iostream>  
  3. #include "sort_data.h"  
  4.   
  5. using namespace std;  
  6.   
  7. int main()  
  8. {  
  9.     trie tr("in.txt"' ');  
  10.   
  11.     tr.openfile();  
  12.     cout<<tr.search("balancing")<<endl;  
  13.   
  14.     sort_data sort(&tr, 5);  
  15.   
  16.     sort.openfile();  
  17.     sort.count_data();  
  18.     return 0;  
  19. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章