首页 > 代码库 > 字典树(Trie Tree)

字典树(Trie Tree)

在图示中,键标注在节点中,值标注在节点之下。每一个完整的英文单词对应一个特定的整数。Trie 可以看作是一个确定有限状态自动机,尽管边上的符号一般是隐含在分支的顺序中的。键不需要被显式地保存在节点中。图示中标注出完整的单词,只是为了演示 trie 的原理。

trie 中的键通常是字符串,但也可以是其它的结构。trie 的算法可以很容易地修改为处理其它结构的有序序列,比如一串数字或者形状的排列。比如,bitwise trie 中的键是一串位元,可以用于表示整数或者内存地址。

Trie树是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。

它有3个基本性质:

(1) 根节点不包含字符,除根节点外每一个节点都只包含一个字符。

(2) 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。

(3) 每个节点的所有子节点包含的字符都不相同。

基本思想(以字母树为例):
1、插入过程
对于一个单词,从根开始,沿着单词的各个字母所对应的树中的节点分支向下走,直到单词遍历完,将最后的节点标记为红色,表示该单词已插入Trie树。
2、查询过程
同样的,从根开始按照单词的字母顺序向下遍历trie树,一旦发现某个节点标记不存在或者单词遍历完成而最后的节点未标记为红色,则表示该单词不存在,若最后的节点标记为红色,表示该单词存在。

Trie树的实现

字母树的插入(Insert)、删除( Delete)和查找(Find)都非常简单,用一个一重循环即可,即第i 次循环找到前i个字母所对应的子树,然后进行相应的操作。实现这棵字母树,至于Trie树的实现,可以用数组,也可以用指针动态分配,平时为了方便就用数组,静态分配空间。

1.结构定义:

struct Trie{    Trie *next[26];    bool isWord;}Root;

2.插入建树方法:

//插入操作(也是构建Trie树)void insert(char *tar){    Trie* head = &Root;    int id;    while(*tar)    {        id = *tar - ‘a‘;        if(head->next[id] == NULL)            head->next[id] = new Trie();        head = head->next[id];        tar++;    }    head->isWord = true;}

3.搜索查询方法:

//查找bool search(char *tar){    Trie* head = &Root;    int id;    while(*tar)    {        id = *tar - ‘a‘;        if(head->next[id] == NULL)            return false;        head = head->next[id];        tar++;    }    if(head->isWord)        return true;    else        return false;}

  

至于结点对儿子的指向,一般有三种方法:

1、对每个结点开一个字母集大小的数组,对应的下标是儿子所表示的字母,内容则是这个儿子对应在大数组上的位置,即标号;

2、对每个结点挂一个链表,按一定顺序记录每个儿子是谁;

3、使用左儿子右兄弟表示法记录这棵树。

三种方法,各有特点。第一种易实现,但实际的空间要求较大;第二种,较易实现,空间要求相对较小,但比较费时;第三种,空间要求最小,但相对费时且不易写。

 字典树TrieTree的java实现:

package mine.trietree;import java.util.ArrayList;import java.util.List;public class TrieTree {	private int SIZE = 26;	private TreeNode root;	TrieTree(){		root = new TreeNode();	}	class TreeNode{		private TreeNode[] son;		private char data;		private boolean isword;		TreeNode(){			son = new TreeNode[SIZE];			data = http://www.mamicode.com/‘ ‘;"hello");		root.InsertTreeNode("world");		root.InsertTreeNode("lixiaokun");		root.InsertTreeNode("haoxue");		if(root.IsInDictionary("lixiaokun"))			System.out.println("Yes");		else			System.out.println("No");		if(root.IsInDictionary("haoxue"))			System.out.println("Yes");		else			System.out.println("No");	}}

java完整版:

package mine.trietree;import java.util.ArrayList;import java.util.List;public class TrieTree {	private int SIZE = 26;	private TreeNode root;	TrieTree(){		root = new TreeNode();	}	class TreeNode{		private TreeNode[] son;		private char data;		private boolean isword;		private int num;		TreeNode(){			son = new TreeNode[SIZE];			data = http://www.mamicode.com/‘ ‘;" ");			for(TreeNode temp:node.son)				PreVisit(temp);		}	}	public static void main(String[] args) {		TrieTree root = new TrieTree();		root.InsertTreeNode("hello");		root.InsertTreeNode("world");		root.InsertTreeNode("lixiaokun");		root.InsertTreeNode("haoxue");		root.InsertTreeNode("helloworld");		root.InsertTreeNode("comeon");		root.InsertTreeNode("hehehe");		if(root.IsInDictionary("lixiaokun"))			System.out.println("Yes");		else			System.out.println("No");		if(root.IsInDictionary("haoxue"))			System.out.println("Yes");		else			System.out.println("No");		if(root.IsInDictionary("hehe"))			System.out.println("Yes");		else			System.out.println("No");		root.PreVisit(root.GetRoot());		System.out.println();		System.out.println(root.CountTime("he"));	}}

  

文字引用自:http://www.cnblogs.com/archimedes/p/trie-tree.html

字典树(Trie Tree)