第一次個人項目【詞頻統計】——關鍵程序思路詳述
阿新 • • 發佈:2018-03-30
個人項目 在一起 文件讀取 conn 好的 函數 orm get insert
考慮使用平衡二叉樹實現單詞和詞組數目的統計。
二叉樹節點定義:
1 struct tnode { 2 char *word; 3 int count; 4 int height; //record node‘s height 5 struct tnode *left; 6 struct tnode *right; 7 };
節點中的成員char *word既可以存儲單詞,也可以存儲詞組。比較好的體現了該數據結構的復用屬性。
【判斷字符數邏輯】
逐字符讀取文件,如果該字符在32-126之間,則字符總數+1。
【判斷行數邏輯】
逐字符讀取,如果該字符為‘\n’,則總行數+1,單個文件讀取結束後總函數再+1(因為文件結束符為EOF,不是‘\n’)。
【判斷單詞數邏輯】
遍歷單詞樹,采用遞歸的方式計算總單詞數。
1 long count_tree(struct tnode *root) { 2 if (root == NULL) return 0; 3 else return count_tree((*root).left) + count_tree((*root).right) + root->count; 4 }
【判斷單詞邏輯】
設置單詞開始標誌符bool isWordStart,然後根據標誌符和當前讀入的字符綜合判斷後續操作。不是單詞開始且讀到了字符,則開始記錄單詞。單詞開始且讀到的是字符或者數字,則繼續記錄,如果單詞開始且讀到了非字母數字字符則停止記錄並並標誌符置為false.
// 讀到單詞起始字母 if (!isWordStart && isCharacter(charTemp)) { isWordStart = true; lengthofStr = 1; str[0] = charTemp; } // 讀單詞(字母或者數字) else if (isWordStart && isNumorCharacter(charTemp)) { str[lengthofStr++] = charTemp; } // 單詞讀完後讀到第一個分隔符 else if (isWordStart && !isNumorCharacter(charTemp)) { isWordStart= false; str[lengthofStr] = ‘\0‘; }
【單詞樹的動態維護】
由於最後輸出要輸出同類型詞組排序最小的單詞,因此在插入單詞樹時需要動態維護節點存儲的單詞。
【詞組樹的判斷邏輯】
設置一個臨時變量存儲上次讀到的單詞。
如果是當前讀到的單詞總數為1,則不插入詞組樹,否則將該次讀到的單詞和上次讀到的單詞用空格分隔符拼接在一起,插入詞組樹。
// 若單詞符合要求則插入樹 if (lengthofStr >= 4 && isCharacter(str[1]) && isCharacter(str[2]) && isCharacter(str[3])) { //將單詞插入單詞樹 numofAllWord++; root = insert_balance(root, str); //總共只掃描到一個單詞,不插入詞組樹 if (numofAllWord == 1) { str_copy(str_before, str); } //總共掃描到至少兩個單詞,插入詞組樹 else { phrase = str_connectwithSpace(str_before, str); rootofPhrase = insert_balance_phrase(rootofPhrase, phrase); str_copy(str_before, str); } }
核心計數函數:
void getInformationofOneFile(char *filename, long &numofChararcter, long &numofLine, tnode *&root, tnode *&rootofPhrase) { FILE *fp = fopen(filename, "r"); if (fp == NULL) { return; } char str[STRING_MAX_LEN], str_before[STRING_MAX_LEN], *phrase = NULL; long numofAllCharacter = 0; //單篇文章所有ascii字符數目 long numofAllWord = 0; //單篇文章所有詞組數目 bool isWordStart = false; bool isEmptyFile = false; int lengthofStr = 0; char charTemp; do { charTemp = fgetc(fp); if (charTemp == EOF &&numofAllCharacter == 0) { isEmptyFile = true; break; } numofAllCharacter++; if (charTemp >= 32 && charTemp <= 126) numofChararcter++; if (charTemp == ‘\n‘) numofLine++; // 讀到單詞起始字母 if (!isWordStart && isCharacter(charTemp)) { isWordStart = true; lengthofStr = 1; str[0] = charTemp; } // 讀單詞(字母或者數字) else if (isWordStart && isNumorCharacter(charTemp)) { str[lengthofStr++] = charTemp; } // 單詞讀完後讀到第一個分隔符 else if (isWordStart && !isNumorCharacter(charTemp)) { isWordStart = false; str[lengthofStr] = ‘\0‘; // 若單詞符合要求則插入樹 if (lengthofStr >= 4 && isCharacter(str[1]) && isCharacter(str[2]) && isCharacter(str[3])) { //將單詞插入單詞樹 numofAllWord++; root = insert_balance(root, str); //總共只掃描到一個單詞,不插入詞組樹 if (numofAllWord == 1) { str_copy(str_before, str); } //總共掃描到至少兩個單詞,插入詞組樹 else { phrase = str_connectwithSpace(str_before, str); rootofPhrase = insert_balance_phrase(rootofPhrase, phrase); str_copy(str_before, str); } //[DEBUG][DEBUG][DEBUG][DEBUG][DEBUG][DEBUG] //cout << numofAllWord << endl; //travel_tree(rootofPhrase); } } } while (charTemp != EOF); if (!isEmptyFile) numofLine++; //numofLine++; fclose(fp); }
第一次個人項目【詞頻統計】——關鍵程序思路詳述