Trie
在计算机科学中,trie,又称前缀树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。
Trie 这个术语来自于 retrieval。根据词源学,trie 的发明者 Edward Fredkin 把它读作 /ˈtriː/ "tree"。 但是,其他作者把它读作 /ˈtraɪ/ "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版权声明。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
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 }