字典樹及其C++實現
1、什麼是Trie樹(參考)
Trie樹,即字典樹,又稱單詞查詢樹或鍵樹,是一種樹形結構,是一種雜湊樹的變種。典型應用是用於統計和排序大量的字串(但不僅限於字串),所以經常被搜尋引擎系統用於文字詞頻統計。它的優點是:最大限度地減少無謂的字串比較,查詢效率比雜湊表高。Trie的核心思想是空間換時間。利用字串的公共字首來降低查詢時間的開銷以達到提高效率的目的。
字典樹3個基本性質:
- 根節點不包含字元,除根節點外每一個節點都只包含一個字元。
- 從根節點到某一節點,路徑上經過的字元連線起來,為該節點對應的字串。
- 每個節點的所有子節點包含的字元都不相同。
假設有b,abc,abd,bcd,abcd,efg,hii 這6個單詞,我們構建的樹就是如下圖這樣的:
如上圖所示,對於每一個節點,從根遍歷到他的過程就是一個單詞,如果這個節點被標記為紅色,就表示這個單詞存在,否則不存在。那麼,對於一個單詞,我只要順著他從根走到對應的節點,再看這個節點是否被標記為紅色就可以知道它是否出現過了。把這個節點標記為紅色,就相當於插入了這個單詞。這樣一來我們查詢和插入可以一起完成,所用時間僅僅為單詞長度,在這一個樣例,便是10。我們可以看到,trie樹每一層的節點數是26^i級別的。所以為了節省空間。我們用動態連結串列,或者用陣列來模擬動態。空間的花費,不會超過單詞數×單詞長度。
字典樹的查詢:
使用trie時,因為當查詢如字串abc是否為某個字串的字首時,顯然以b,c,d....等不是以a開頭的字串就不用查詢了。所以建立trie的複雜度為O(n*len),而建立+查詢在trie中是可以同時執行的,建立的過程也就可以成為查詢的過程,hash就不能實現這個功能。所以總的複雜度為O(n*len),實際查詢的複雜度也只是O(len)。(說白了,就是Trie樹的平均高度h為len,所以Trie樹的查詢複雜度為O(h)=O(len))。
字典樹優缺點:
優點:
- 插入,查詢,刪除等操作複雜度為O(h),其中h為單詞的長度。為什麼會這麼快呢,本質是空間換時間(空間複雜度為26的h次方),利用指標來避免做其他不必要的查詢。(初始化的時間複雜度為 n*O(h),n為單詞個數);
- 當儲存大量單詞或者說儲存的單詞有著共同字首時節省了空間。(比如說用線性儲存boy,boyfriend如用trie儲存的差別);
缺點:
- 指標佔用的空間,空間複雜度大。如果儲存少量的單詞,並不能節省空間。
字典樹的應用:
- 字串檢索:事先將已知的一些字串(字典)的有關資訊儲存到trie樹裡,查詢另外一些未知字串是否出現過或者出現頻率。
- 字串最長公共字首(轉化為尋找共同祖先問題)。
字典樹和雜湊表的比較(參考):
2、字典樹的C++實現(參考)
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
const int Num = 26; //每個節點需要儲存26個字母
struct TrieNode
{
bool Isword; //判斷是否是單詞
TrieNode* next[Num];
TrieNode() :Isword(false) //初始化
{
memset(next, NULL, sizeof(next));
}
};
class Trie
{
public:
Trie() { root = new TrieNode(); }
void insert(string word);
bool search(string word);
void deleteTrie(TrieNode* root);
private:
TrieNode* root;
};
void Trie::insert(string word)
{
TrieNode* location = root;
for (int i = 0; i < word.length();i++)
{
if (location->next[word[i] - 'a'] == nullptr)
{
TrieNode* temp = new TrieNode();
location->next[word[i] - 'a']=temp;
}
location = location->next[word[i] - 'a'];
}
location->Isword = true;
}
bool Trie::search(string word)
{
TrieNode* location = root;
//while (word&&location)//注意location不能為空
for (int i = 0; i < word.length()&&location;i++)
location = location->next[word[i] - 'a'];
return(location != NULL && location->Isword);
}
void Trie::deleteTrie(TrieNode* root)
{
for (int i = 0; i < Num; i++)
{
if (root->next[i] != NULL)
{
deleteTrie(root->next[i]);
}
}
delete root;
}
void main() //簡單測試
{
Trie tree;
int n; //輸入n個單詞在字典樹中
cin >> n;
while (n--)
{
string s;
cin >> s;
tree.insert(s);
}
string input;
cout << "輸入要檢查的單詞" << endl;
cin >> input;
cout << boolalpha << tree.search(input) << endl;//查詢是否存在是個單詞
}
相關文章
- 字典樹(字首樹)簡單實現
- 字首樹及其Java實現Java
- Trie樹,字典樹
- 字典樹
- codevs 4189 字典【字典樹】dev
- AC自動機+trie樹實現高效多模式匹配字典模式
- 24. 平衡二叉樹,及其程式碼實現二叉樹
- 詳細二叉樹實現c++二叉樹C++
- 字典樹Trie
- 字典樹(Trie)
- trie字典樹
- C#實現前向最大匹、字典樹(分詞、檢索)C#分詞
- 怎樣實現基於Trie樹和字典的分詞功能分詞
- 字典樹專題
- 字典樹學習
- Python 字典實現原理Python
- Python實現建立字典Python
- [轉載] PHP 基於字典樹演算法實現搜尋聯想功能PHP演算法
- Trie|如何用字典樹實現搜尋引擎的關鍵詞提示功能
- 資料結構之樹( 線段樹,字典樹)資料結構
- 一些“字典樹”典
- P8306 【模板】字典樹
- 一文搞懂字典樹
- 資料結構-字典樹資料結構
- 分散式鎖及其實現分散式
- 線性表及其實現
- AOP如何實現及其原理
- Set介面及其實現類
- 面試最常問的陣列轉樹,樹轉陣列 c++ web框架paozhu實現面試陣列C++Web框架
- Python 雜湊表的實現——字典Python
- python如何使用字典實現switchPython
- Redis 字典結構實現分析BTRedis
- Redis設計於實現之字典Redis
- Redis 設計與實現 4:字典Redis
- 樹元件實現元件
- java實現樹Java
- python實現二叉樹及其七種遍歷方式(遞迴+非遞迴)Python二叉樹遞迴
- 最小生成樹的性質與prim演算法(C++實現)演算法C++