Trie (發音爲 "try") 或前綴樹是一種樹數據結構,用於檢索字符串數據集中的鍵。這一高效的數據結構有多種應用:1. 自動補全 2.拼寫檢查 3.九宮格打字預測 4.IP路由(最長前綴匹配)
爲什麼需要Trie樹結構?
哈希表可以在 O(1)O(1) 時間內尋找鍵值,卻無法高效的完成以下操作:
- 找到具有同一前綴的全部鍵值。
- 按詞典序枚舉字符串的數據集。
Trie 樹優於哈希表的另一個理由是,隨着哈希表大小增加,會出現大量的衝突,時間複雜度可能增加到 O(n),其中 n是插入的鍵的數量。與哈希表相比,Trie 樹在存儲多個具有相同前綴的鍵時可以使用較少的空間。此時 Trie 樹只需要 O(m)的時間複雜度,其中 m 爲鍵長。而在平衡樹中查找鍵值需要 O(mlogn) 時間複雜度。
Trie 樹的結點結構
Trie 樹是一個有根的樹,其結點具有以下字段:
- 最多 R 個指向子結點的鏈接,其中每個鏈接對應字母表數據集中的一個字母。本文中假定 R 爲 26,小寫拉丁字母的數量。
- 布爾字段,以指定節點是對應鍵的結尾還是隻是鍵前綴。
結構體如下:
struct TrieNode {
bool isEnd; //該結點是否是一個串的結束
TrieNode* next[26]; //字母映射表
};
初始化
Trie() {
for(int i=0;i<26;i++){
root->nodes[i] = NULL;
}
root->isEnd = true;
}
插入
void insert(string word) {
TrieNode * now = root;
for(char c : word){
if(now->nodes[c-'a'] == NULL){
now->nodes[c-'a'] = new TrieNode();
}
now= now->nodes[c-'a'];
}
now->isEnd = true;
}
查找
bool search(string word) {
TrieNode * now = root;
for(char c : word){
if(now->nodes[c-'a'] == NULL){
return false;
}
now = now->nodes[c-'a'];
}
if(now->isEnd) return true;
else return false;
}
判斷前綴
bool startsWith(string prefix) {
TrieNode * now = root;
for(char c:prefix){
if(now->nodes[c-'a'] == NULL)
return false;
now = now->nodes[c-'a'];
}
return true;
}
參考自leetcode208題 實現Trie樹 題目鏈接 https://leetcode-cn.com/problems/implement-trie-prefix-tree/
前綴樹的應用:對字典實現單詞搜索 https://leetcode-cn.com/problems/word-search-ii/