Trie樹,字典樹
又稱單詞查找樹,Trie樹,是一種樹形結構,是一種哈希樹的變種。典型應用是用於統計,排序和保存大量的字符串(但不僅限於字符串),所以經常被搜索引擎系統用於文本詞頻統計。它的優點是:利用字符串的公共前綴來減少查詢時間,最大限度地減少無謂的字符串比較,查詢效率比哈希樹高。
它有3個基本性質:
根節點不包含字符,除根節點外每一個節點都只包含一個字符; 從根節點到某一節點,路徑上經過的字符連接起來,爲該節點對應的字符串; 每個節點的所有子節點包含的字符都不相同。
(以上來自百度百科)
如果我們有一個單詞庫,然後我們要從裏面找詞。。。用hash可以很快,但是浪費了很多空間,所以用Trie樹,速度一樣能到O(n),n是要查找的單詞長度。
這就是一顆Trie樹,根路徑沒有值,用#
表示,假如我們的單詞庫有這麼幾個單詞
string[] words = new string[] {
"ant",
"at",
"as",
"cn",
"com",
};
那就對應這麼一顆Trie樹(來自畫圖。。。)
從根到葉子節點的值連起來就是一個單詞,比如c->o->m,要查找at是否在單詞庫裏,就從第一個字母a開始,找到a節點,下一個字母t,找a節點下是否有t,找到,說明at在,其它單詞類似。
構建Trie樹和查找過程差不多,代碼附上:
//樹節點
class TreeNode
{
public char value = '#';
public List<TreeNode> next = new List<TreeNode>();
}
class Class1
{
string[] words = new string[] {
"ant",
"at",
"as",
"cn",
"com",
};
//構建Trie樹
public TreeNode Build()
{
TreeNode root = new TreeNode();
//就是不停的添詞
for (int i = 0; i < words.Length; i++)
{
AddWord(words[i], root);
}
return root;
}
//這是主要的方法,把一個詞添加到Trie樹中
public void AddWord(string word,TreeNode root)
{
TreeNode now = root;
int i,j;
for (j = 0; j < word.Length; j++)
{
bool has = false;
char c = word[j];
for (i = 0; i < now.next.Count; i++)
{
if (c == now.next[i].value)
{
now = now.next[i];
has = true;
break;
}
}
if (!has)
{
TreeNode t = new TreeNode();
t.value = c;
now.next.Add(t);
now = now.next[i];
}
}
}
//查找一個詞是否在Trie樹中
public bool Search(TreeNode root,string word)
{
TreeNode now = root;
int i, j;
for (i = 0; i < word.Length; i++)
{
char c = word[i];
bool has = false;
for (j = 0; j < now.next.Count; j++)
{
if (now.next[j].value == c)
{
now = now.next[j];
has = true;
break;
}
}
if (!has) return false;
}
return true;
}
}
測試程序:
static void Main(string[] args)
{
Class1 c1 = new Class1();
TreeNode root=c1.Build();
Console.WriteLine(c1.Search(root, "cn"));
Console.WriteLine(c1.Search(root,"cnt"));
Console.WriteLine(c1.Search(root, "com"));
Console.WriteLine(c1.Search(root, "at"));
Console.WriteLine(c1.Search(root, "b"));
Console.ReadLine();
}
輸出結果: