trie树- 转自 维基百科

Trie

 
一个保存了 8 个键的 trie 结构,"A", "to", "tea", "ted", "ten", "i", "in", and "inn".

计算机科学中,trie,又称前缀树,是一种有序,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。

Trie 这个术语来自于 retrieval。根据词源学,trie 的发明者 Edward Fredkin 把它读作 /ˈtr/ "tree"。 但是,其他作者把它读作 /ˈtr/ "try"。

在图示中,键标注在节点中,值标注在节点之下。每一个完整的英文单词对应一个特定的整数。Trie 可以看作是一个确定有限状态自动机,尽管边上的符号一般是隐含在分支的顺序中的。

键不需要被显式地保存在节点中。图示中标注出完整的单词,只是为了演示 trie 的原理。

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

应用
trie树常用于搜索提示。如当输入一个网址,可以自动搜索出可能的选择。当没有完全匹配的搜索结果,可以返回前缀最相似的可能。

实现

trie树实际上是一个DFA,通常用转移矩阵表示。行表示状态,列表示输入字符,(行, 列)位置表示转移状态。这种方式的查询效率很高,但由于稀疏的现象严重,空间利用效率很低。也可以采用压缩的存储方式即链表来表示状态转移,但由于要线性查询,会造成效率低下。

于是人们提出了下面两种结构。

三数组Trie

三数组Trie(Tripple-Array Trie)结构包括三个数组:base,next和check.

二数组Trie

二数组Trie(Double-Array Trie)包含base和check两个数组。base数组的每个元素表示一个Trie节点,即一个状态;check数组表示某个状态的前驱状态。

实例

这是一个用于词频统计的程序范例,因使用了getline(3),所以需要glibc才能链接成功,没有glibc的话可以自行改写。代码由User:JohnBull捐献,遵从GPL版权声明

 

View Code
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4  
 5 #define TREE_WIDTH 256
 6  
 7 #define WORDLENMAX 128
 8  
 9 struct trie_node_st {
10         int count;
11         struct trie_node_st *next[TREE_WIDTH];
12 };
13  
14 static struct trie_node_st root={0, {NULL}};
15  
16 static char *spaces=" \t\n/.\"\'()";
17  
18 static int insert(const char *word)
19 {
20         int i;
21         struct trie_node_st *curr, *newnode;
22  
23         if (word[0]=='\0') {
24                 return 0;
25         }
26         curr = &root;
27         for (i=0; ; ++i) {
28                 if (word[i] == '\0') {
29                         break;
30                 }
31                 if (curr->next[ word[i] ] == NULL) {
32                         newnode=(struct trie_node_st*)malloc(sizeof(struct trie_node_st));
33                         memset(newnode, 0, sizeof(struct trie_node_st));
34                         curr->next[ word[i] ] = newnode;
35                 } 
36                 curr = curr->next[ word[i] ];
37         }
38         curr->count ++;
39  
40         return 0;
41 }
42  
43 static void printword(const char *str, int n)
44 {
45         printf("%s\t%d\n", str, n);
46 }
47  
48 static int do_travel(struct trie_node_st *rootp)
49 {
50         static char worddump[WORDLENMAX+1];
51         static int pos=0;
52         int i;
53  
54         if (rootp == NULL) {
55                 return 0;
56         }
57         if (rootp->count) {
58                 worddump[pos]='\0';
59                 printword(worddump, rootp->count);
60         }
61         for (i=0;i<TREE_WIDTH;++i) {
62                 worddump[pos++]=i;
63                 do_travel(rootp->next[i]);
64                 pos--;
65         }
66         return 0;
67 }
68  
69 int main(void)
70 {
71         char *linebuf=NULL, *line, *word;
72         size_t bufsize=0;
73         int ret;
74  
75         while (1) {
76                 ret=getline(&linebuf, &bufsize, stdin);
77                 if (ret==-1) {
78                         break;
79                 }
80                 line=linebuf;
81                 while (1) {
82                         word = strsep(&line, spaces);
83                         if (word==NULL) {
84                                 break;
85                         }
86                         if (word[0]=='\0') {
87                                 continue;
88                         }
89                         insert(word);
90                 }
91         }
92  
93 /* free(linebuf); */
94  
95         do_travel(&root);
96  
97         exit(0);
98 }

 

 

 

posted @ 2013-06-06 11:12  Neo.  阅读(348)  评论(1编辑  收藏  举报