很多時候,學習總是止於實現,因為有很多這樣或者那樣的問題。即便是你理解了這種結構,但是實現起來卻是另外一番天地,實踐,看源碼,然后繼續實現是現階段我應該完成的事情。
這次來學習一下字典樹。
字典樹,就是對樹結構的一種特殊處理。對於英文詞典來說,26個英文字母可以任意組合,那么這個樹必然是26叉的。那么這個樹有啥子作用,
1.字典樹在串的快速檢索中的應用。
給出N個單詞組成的熟詞表,以及一篇全用小寫英文書寫的文章,請你按最早出現的順序寫出所有不在熟詞表中的生詞。在這道題中,我們可以用字典樹,先把熟詞建一棵樹,然后讀入文章進行比較,這種方法效率是比較高的。
2. 字典樹在“串”排序方面的應用
給定N個互不相同的僅由一個單詞構成的英文名,讓你將他們按字典序從小到大輸出用字典樹進行排序,采用數組的方式創建字典樹,這棵樹的每個結點的所有兒子很顯然地按照其字母大小排序。對這棵樹進行先序遍歷即可。
3. 字典樹在最長公共前綴問題的應用
對所有串建立字典樹,對於兩個串的最長公共前綴的長度即他們所在的結點的公共祖先個數,於是,問題就轉化為最近公共祖先問題。
在看別人代碼的過程中,我出現了很多疑問。第一個是封裝類中類方法的調用,應該是分為靜態類方法和實例類方法。實例類方法是需要先實例化的。另外一個問題是struct和class 在C++中的區別,區別不大只是缺省關鍵詞public和private時,struct是pub,而class是pri。
// // main.cpp // yy // // Created by MadMarical on 15/11/25. // Copyright (c) 2015年 com. All rights reserved. // #include <iostream> #include <string> #include <vector> #include <algorithm> #include <stdexcept> using namespace std; struct Node { bool isWord;//判斷當前字母是否為單詞的最后一個字母標識 Node *next[26];//26叉 Node() { isWord = false; for(int i = 0;i != 26; ++ i) { next[i] = NULL;//清空26叉 } } }; class DicTree { public: Node *root;//根節點 DicTree() { root = NULL;//在構造函數中初始化 } void Insert(string str) { if (!root) { root = new Node;//如果root現在不空,需要重新開辟一個根節點 } Node *head = root;//根節點不能變,找一個新的指針指向根節點方便操作 for(long int i = 0;i != str.length(); ++ i) { int num = str[i] - 'a';//獲取當前字母應該存儲的位置 if (head ->next[num] == NULL) { head->next[num] = new Node; } head = head->next[num]; } head->isWord = true; } bool Search(string str) { Node *head = root; for (long int i = 0; i != str.length(); ++ i) { int num = str[i] - 'a'; if (head->next[num] == NULL) { return false; } else { head = head->next[num]; } } return head->isWord; } }; int main(int argc, const char * argv[]) { string inp1; cin>>inp1; DicTree A; A.Insert(inp1); string inp2; cin>>inp2; A.Search(inp2); return 0; }
反思:
1.書到用時方恨少...快點讀書...