一字典樹
字典樹,又稱單詞查找樹,Trie樹,是一種樹形結構,哈希表的一個變種
二.性質
根節點不包含字符,除根節點以外的每一個節點都只包含一個字符;
從根節點到某一節點,路徑上經過的字符串連接起來,為該節點對應的字符串;
每個節點的所有子節點包含的字符都不相同。
三.優勢: 利用字符串的公共前綴,節約存儲空間和查找時間。時間復雜度O(n)
四.適用於:快速字符串插入,查找字符串,在大量字符串的查找中,體現其高效性。
查找的時間復雜度只和樹的深度有關,跟表中有多少個單詞無關。
樹的深度與單詞的長度有關:
每個節點代表字符串下的一個字母,那么單詞的每一個字母獨占樹的一層的位置,沒有單詞的兩個字母在同一層級,
則整個樹高為(最長字符串+1), + 1因為root 節點獨占頂層

五.應用
(1)排序:
排序:使用數組創建模擬字典樹:將字母序列轉化成數字序列 ,標記為數組索引,那么數組索引有序,字母即有序。(
參考上圖,前序遍歷即排序)
對樹進行前序遍歷 就是有序排序了。
(2)統計單詞/字符串出現次數
字典樹的結構體:

count即為統計的串出現的次數
(3) 查找公共前綴字符串
使用舉例:
/* 字典樹學習: 輸入n個單詞 舉出一個單詞出現的次數。 10 apple ppppp hello hello need bee bee none you apple need ==1 ==Program ended with exit code: 0 */ // // main.cpp // CPlusDemo // // Created by HF on 2018/5/15. // Copyright © 2018年 HF-Liqun. All rights reserved. // #include <iostream> #include <string> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> using namespace std; #define MAX 26 //the total number of alphabet is 26, a...z struct DicTrie{ bool isTerminal;//是否是單詞結束標志 int count; //當前字符串出現次數 struct DicTrie *next[MAX ]; //每個節點 最多 有 MAX 個孩子節點 結構體嵌套 } ; DicTrie *root = NULL; // 根節點是一個空節點 特此聲明並賦值 int init() //初始化鏈表,有對空間要求的 可選用該方法進行初始化 { root = new DicTrie; root->count = 0; for (int i = 0; i < MAX; i ++) { root->next[i] = NULL; // 空節點 root->isTerminal = false; // } return 0; } bool isFindTrie(char *targetString) //判斷是否能在字典樹中查到目標串 { int len = strlen(targetString); DicTrie *head = root; for (int i = 0; i < len; i ++) { int res = (int)(targetString[i] - 'a');//當前小寫字母對應數字 if (head->next[res] == NULL) { //如果是空節點 則為否 結束查找 return false; } else {//不為空 更新頭指針 以便繼續往下查找 head = head->next[res]; } } if (head->count > 0) { return true; } return false; } int findTrieCount(char *targetString) //判斷是否能在字典樹中查到目標串 { int len = strlen(targetString); DicTrie *head = root; for (int i = 0; i < len; i ++) { int res = (int)(targetString[i] - 'a');//當前小寫字母對應數字 if (head->next[res] == NULL) { //如果是空節點 則為否 結束查找 return false; } else {//不為空 更新頭指針 以便繼續往下查找 head = head->next[res]; } } return head->count; } int insertTrie(char *targetString) { int len = strlen(targetString); DicTrie *head = root; for (int i = 0; i < len; i ++) { int res = (int)(targetString[i] - 'a');//當前小寫字母對應數字 if (head->next[res] == NULL) { //如果是空節點 head->next[res] = new DicTrie;//則插入新節點元素 head = head->next[res]; //更新頭指針 並初始化 head->count = 0; // for (int j = 0; j < MAX; j ++) { head->next[j] = NULL; head->isTerminal = false; } } else { head = head->next[res]; } } head->count ++;//每次插入一個,響應計數都增加1 head->isTerminal = true; return head->count; } int deleteTrie(char *targetString) { int len = strlen(targetString); DicTrie *head = root; for (int i = 0; i < len; i ++) { int res = (int)(targetString[i] - 'a');//當前小寫字母對應數字 if (head->next[res] == NULL) { //如果是空節點 表示刪除的字符串不在字典中 return 0; } else { //繼續查找 head = head->next[res]; } } head->count --;//每次刪除一個,響應計數都-1 if (head->count <= 0) { head->count = 0; head->isTerminal = false; } return 0; } int main(int argc, const char * argv[]) { // insert code here... int n; char targetString[20]; init(); scanf("%d",&n); //n 組數據 for (int i = 0; i < n; i ++) { scanf("%s",targetString); //字符串插入字典樹 insertTrie(targetString);//插入方法 } scanf("%s",targetString); printf("==%d\n",findTrieCount(targetString));//查找方法 return 0; }
參考
1.https://blog.csdn.net/piaocoder/article/details/47836559
2.http://blog.51cto.com/570842253/1556652
3.http://pisces.ck.tp.edu.tw/~peng/index.php?action=showfile&file=f743c2923f8170798f62a585257fdd8436cd73b6d
4.https://baike.baidu.com/item/%E5%AD%97%E5%85%B8%E6%A0%91/9825209?fr=aladdin&fromid=517527&fromtitle=Trie%E6%A0%91