主要是hash樹的變種,先看下圖:
每乙個點儲存乙個字元,所以trie(字典樹)的key不是每個字串,而是一條鏈。其原理就是充分利用了公共字串,這樣在查詢時,就不需要做重複工作了。並且查詢的複雜度可以維持在o(len),len為字串的長度,原因很簡單,我們只需沿著從根到節點的一條路徑就可以了。插入也是類似的原理。
建立的過程:
每個節點包括三個資訊:26個指標(假設查詢26個英文小寫字母),每個節點的後繼節點可能出現26個字母當中的任何乙個,故需26個指標,當然對於不存在的後繼結點,設定為null;標誌位,此標誌位主要是為了識別是否為字串為乙個單詞;第三個為附加資訊,看具體應用場合,可以為字元出現的次數,也可以為字首的個數,字串的個數,總之靈活應用就是。
查詢的過程:
與建立過程原理雷同,只是沒有建立新節點的過程;
刪除的過程:
很少見,如果非要刪除,則採用遞迴從下往上挨個delete即可;
我直接**:
trie樹的應用:
1.有乙個1g大小的乙個檔案,裡面每一行是乙個詞,詞的大小不超過16位元組,記憶體限制大小是1m。返回頻數最高的100個詞。
2.1000萬字串,其中有些是重複的,需要把重複的全部去掉,保留沒有重複的字串。請怎麼設計和實現?
3.乙個文字檔案,大約有一萬行,每行乙個詞,要求統計出其中最頻繁出現的前10個詞,請給出思想,給出時間複雜度分析。
4.尋找熱門查詢:搜尋引擎會通過日誌檔案把使用者每次檢索使用的所有檢索串都記錄下來,每個查詢串的長度為1-255位元組。假設目前有一千萬個記錄,這些查詢串的重複讀比較高,雖然總數是1千萬,但是如果去除重複和,不超過3百萬個。乙個查詢串的重複度越高,說明查詢它的使用者越多,也就越熱門。請你統計最熱門的10個查詢串,要求使用的記憶體不能超過1g。
字尾樹的應用:
1.查詢字串o是否在字串s中。
方案:用s構造字尾樹,按在trie中搜尋字串的方法搜尋o即可。
原理:若o在s中,則o必然是s的某個字尾的字首。
例如:leconte,查詢o:con是否在s中,則o(con)必然是s(leconte)的字首。
2.指定字串t在字串s中的重複次數。
方案:用s+』$』構造字尾樹,搜尋t節點下的葉子節點數目即為重複次數
原理:如果t在s中重複了兩次,則s應有兩個字尾以t為字首,重複次數自然統計出來了。
3.字串s中的最長重複子串
方案:原理同2,具體做法是找到最深的非葉子節點。
這個深指從root所經歷過的字元個數,最深非葉子節點所經歷的字串起來就是最長重複子串。為什麼非要是葉子節點呢?因為既然是要重複的,當然葉子節點個數要》=2
4.兩個字串s1,s2的最長公共子串(而非以前所說的最長公共子串行,因為子串行是不連續的,而子串是連續的。)
方案:將s1#s2$作為字串壓入字尾樹,找到最深的非葉子節點,且該節點的葉子節點既有#也有$.
5.最長回文子串
前文已經提及,建立的時間複雜度為:o(n*len),查詢,插入都為o(len)。空間複雜度就比較大了,這也是它的乙個缺點,主要是指標得占用空間。
首先比較建立的複雜度,建立的複雜度,hash為o(n*(len+3))(n指字串的個數,len指字串的長度),原理可見我的博文hash 乙個海量資料的實現,裡面有段**:
int sdbmhash(char* str)
return (hash & 0x7fffffff);
} 分析:3具體指int hash= 0
; 和return (hash & 0x7fffffff);有人會說,這也算,幾乎沒影響,但是大家想想,每個字串多倆次操作,當字串很大時,就不是倆次的問題了可能是10的幾次方了,還有一次是hash表的操作。查詢和插入同樣的道理,每個字串多兩個操作。所以hash的時間複雜度不如trie的。這還是小case,在很多方面hash沒法跟trie比的,比如查詢字首字串,trie幾乎用不到o(len),hash的操作就複雜多了,並且字首字串還要額外的hashmap。空間方面,可能hash 節省,但是恰恰就是因為trie犧牲了空間才換如此巨大的時間效果。
我自己建立了乙個txt檔案,裡面有很多單詞,一行乙個,利用trie統計某個單詞出現的頻數,可在我的資源檔案裡下到工程檔案,裡面有乙個txt。可以在txt裡複製同乙個單詞多次,然後查詢,就可以看到它存在的次數了。
#include#include#includeusing namespace std;const int n=26;
typedef struct trie_node
trienode , *trie;
trienode* createtrienode()
void trie_insert(trie root, char* word)
node = node->next[id]; // 每插入一步,相當於有乙個新串經過,指標向下移動
++p;
//node->count += 1; // 這行**用於統計每個單詞字首出現的次數(也包括統計每個單詞出現的次數)
} node->exist = true;// 單詞結束的地方標記此處可以構成乙個單詞
node->count++;
}
int trie_search(trie root, char* word)
const int num=5000;
//產生乙個txt檔案,模擬字串
void createstrtxt()
{ for(int i=0;i>str)
{ trie_insert(root,str);
cout<
測試圖:
資料結構 TRIE樹
分類 data structure 2009 04 19 22 31 5425人閱讀收藏 舉報trie樹 trie樹就是字元樹,其核心思想就是空間換時間。舉個簡單的例子。給你100000個長度不超過10的單詞。對於每乙個單詞,我們要判斷他出沒出現過,如果出現了,第一次出現第幾個位置。這題當然可以用h...
資料結構 TRIE樹
trie樹 trie樹就是字元樹,其核心思想就是空間換時間。舉個簡單的例子。給你100000個長度不超過10的單詞。對於每乙個單詞,我們要判斷他出沒出現過,如果出現了,第一次出現第幾個位置。這題當然可以用hash來,但是我要介紹的是trie樹。在某些方面它的用途更大。比如說對於某乙個單詞,我要詢問它...
資料結構之Trie樹
1 什麼是trie樹 trie樹,即字典樹,又稱單詞查詢樹或鍵樹,是一種樹形結構,是一種雜湊樹的變種。典型應用是用於統計和排序大量的字串 但不僅限於字串 所以經常被搜尋引擎系統用於文字詞頻統計。它的優點是 最大限度地減少無謂的字串比較,查詢效率比雜湊表高。trie的核心思想是空間換時間。利用字串的公...