又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。

 

 

它有3个基本性质:

 

  根节点不包含字符,除根节点外每一个节点都只包含一个字符。 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。 每个节点的所有子节点包含的字符都不相同。

 

基本操作

  其基本操作有:查找 插入和删除,当然删除操作比较少见.我在这里只是实现了对整个树的删除操作,至于单个word的删除操作也很简单.

 

  

namespace ConsoleApplication1
{
public class TireTree
{
private TireNode root = new TireNode(' ');
public TireTree()
{

}
private void CreateTireTree(TireNode node, string word, int index)
{
if (word.Length == index) return;
char key = word[index];
TireNode newNode = null;
if (node.NextNode.ContainsKey(key))
{
newNode = node.NextNode[key];
}
else
{
newNode = new TireNode(key);
node.NextNode.Add(key, newNode);
}
if (word.Length - 1 == index)
{
newNode.Word = word;
}
CreateTireTree(node.NextNode[key], word, index + 1);
}

public void AddWords(string word)
{
CreateTireTree(root, word, 0);
}
public List<string> SearchWords(string content)
{
List<string> result = new List<string>();
char[] charArr = content.ToCharArray();
TireNode currentNode = root;
for (int i = 0; i < charArr.Length; i++)
{
if (currentNode.NextNode.ContainsKey(charArr[i])) //如果下个节点找得到当前字,则继续往下找下个字符。
{
currentNode = currentNode.NextNode[charArr[i]];
}
else if (root.NextNode.ContainsKey(charArr[i])) //如果下个节点找不到当前字,则从根节点找。
{
currentNode = root.NextNode[charArr[i]];
}
else //否则下个字符,也从根节点找。
{
currentNode = root;
}
if (currentNode.IsWord)
{
if (!result.Contains(currentNode.Word))
result.Add(currentNode.Word);
}
}

return result;
}
private class TireNode
{
public char Key { get; set; }
public string Word { get; set; }
public bool IsWord { get { return this.Word != null; } }
private Dictionary<char, TireNode> nextNode = new Dictionary<char, TireNode>();
public Dictionary<char, TireNode> NextNode
{
get { return nextNode; }
set { nextNode = value; }
}

public TireNode(char key)
{
this.Key = key;
}

}
}
}


实现方法

  搜索字典项目的方法为(1) 从根结点开始一次搜索;

 

  (2) 取得要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索;

 

  (3) 在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索。

 

  (4) 迭代过程……

 

  (5) 在某个结点处,关键词的所有字母已被取出,则读取附在该结点上的信息,即完成查找。

 

   测试代码

    private void TestTireTree()
{ const int count=100;
string[] Arr = new string[count]; for (int i = 0; i < Arr.Length; i++) { Arr[i] = (Guid.NewGuid()).ToString(); } // 这里是只是演示放入字符,建立Tire树

TireTree Tree = new TireTree();

foreach (string str in Arr)
{
Tree.AddWords(str );
}
string word = "检测的字符";
List<string> ResultList= Tree.SearchWords(word);
foreach(string result in ResultList)
{
Console.WriteLine(string.Format("检测到非法词语{0}"),result);
}

}

代码中 CreateTireTree(TireNode node, string word, int index) 使用递归实现的,可以修改回溯版本,提高效率。

  private void CreateArrayTireTree(TireNode node, string word)
{
char[] wordsarray = word.ToCharArray();
for (int i = 0; i < wordsarray.Length; i++)
{
char key = word[i];
TireNode newNode = null;
if (node.NextNode.ContainsKey(key))
{
newNode = node.NextNode[key];
}
else
{
newNode = new TireNode(key);
node.NextNode.Add(key, newNode);
}
if (i == wordsarray.Length - 1)
{
newNode.Word = word;
}

node = node.NextNode[key];
}


}