在计算机科学中,trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。
Trie这个术语来自于retrieval。根据词源学,trie的发明者Edward Fredkin把它读作/ˈtriː/ “tree”。[1][2]但是,其他作者把它读作/ˈtraɪ/ “try”。
如图可以查看trie树的基本结构:
接下来,我们直接看,实现方式,简单易懂:
#include <stdio.h>
#include <stdlib.h>
#define ALPHABET_SIZE 26
typedef struct trie_node {
int count;
struct trie_node *children[ALPHABET_SIZE];
} trie_node;
trie_node * create_node() {
trie_node * n = (trie_node *) malloc(sizeof(trie_node));
n->count = 0;
int i;
for (i = 0; i < ALPHABET_SIZE; ++i) {
n->children[i] = NULL;
}
}
void insert_word(trie_node *t, char *word) {
trie_node * cur = t;
char *w = word;
int indis;
while(*w) {
indis = *w - 'a';
if(cur->children[indis] == NULL) {
cur->children[indis] = create_node();
}
cur = cur->children[indis];
++w;
}
cur->count= 1;
}
int search(trie_node *t, char *word) {
trie_node * cur = t;
char *p = word;
while (*p && cur != NULL) {
cur = cur->children[*p - 'a'];
++p;
}
if(cur == NULL) {
return 0;
}
return cur->count;
}
int main() {
// 关键字集合
char keys[][8] = {"the", "a", "there", "answer", "any", "by", "bye", "their"};
trie_node *root = create_node();
int i;
for (i = 0; i < 8; ++i){
insert_word(root, keys[i]);
}
// 检索字符串
char s[][32] = {"Present in trie", "Not present in trie"};
printf("%s --- %s\n", "the", search(root, "the")>0?s[0]:s[1]);
printf("%s --- %s\n", "these", search(root, "these")>0?s[0]:s[1]);
printf("%s --- %s\n", "their", search(root, "their")>0?s[0]:s[1]);
printf("%s --- %s\n", "thaw", search(root, "thaw")>0?s[0]:s[1]);
printf("Hello, World!\n");
return 0;
}