在大数据处理中,用字典树来解决一些有公共前缀或者是自动完成功能的词汇存储时,经常能够用到,而且十分方便,总能在O(n)时间内查找到相应节点。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。
字典树的每个节点有26个孩子节点,节点依照其位置,代表不同的字母,而节点中存储的key信息就是能够到达这个节点的公共前缀数目,即从根节点到此节点的路径上字母连起来构成的公共前缀单词的数目。但如果存储的单词数目庞大,而且有公共前缀的不多,则使用字典树将十分耗费空间,呈指数增长~~
实现的数据结构及操作如下:
1 #ifndef _STDIO_H_H 2 #define _STDIO_H_H 3 #include <stdio.h> 4 #endif 5 6 #include <malloc.h> 7 8 const int sonnum=26; //26个字母,所以每个节点就有26个分支 9 const int base='a'; //以a为基准值 10 11 struct Trie{ 12 int num; //用于记录到达此节点的单词数 13 bool terminal; //是否为叶节点的标志 14 struct Trie *son[sonnum]; //26颗子树 15 }; 16 /*新建树*/ 17 Trie *NewTrie() 18 { 19 Trie *temp = (Trie *)malloc(sizeof(Trie)); 20 temp->num = 1; 21 temp->terminal = false; 22 for(int i=0;i<sonnum;++i) 23 temp->son[i] = NULL; //每个孩子都置为空 24 return temp; 25 } 26 /*删除树*/ 27 void Delete(Trie *pnt) 28 { 29 if(pnt!=NULL) 30 { 31 for(int i=0;i<sonnum;++i) 32 if(pnt->son[i]!=NULL) 33 Delete(pnt->son[i]); 34 free(pnt); 35 pnt = NULL; 36 } 37 } 38 /*插入节点*/ 39 void Insert(Trie *pnt,char *s,int len) 40 { 41 Trie *temp = pnt; 42 for(int i=0;i<len;++i) 43 { 44 if(temp->son[s[i]-base]==NULL) 45 temp->son[s[i]-base]=NewTrie(); 46 else 47 temp->son[s[i]-base]->num++; 48 temp = temp->son[s[i]-base]; 49 } 50 temp->terminal = true; 51 } 52 /*查找字符串*/ 53 Trie *Find(Trie *pnt,char *s,int len) 54 { 55 Trie *temp = pnt; 56 for(int i=0;i<len;++i) 57 if(temp->son[s[i]-base]!=NULL) 58 temp = temp->son[s[i]-base]; 59 else 60 return NULL; 61 return temp; 62 }
下面是一个应用例子,无任何意义。随便输入一些字符串(我假设单词长度不超过100个字母),存储进一颗字典树中,输入end来结束输入,再输入查找的公共前缀,成功查找到后返回节点指针,打印出节点中的num成员就是单词数目。最后得记得释放内存~~
1 #include <stdio.h> 2 #include <string.h> 3 4 #include "Trie.h" 5 6 /*This is a Trie-tree apply programme*/ 7 8 int main(int argc,char *argv[]) 9 { 10 Trie *root = NewTrie(); 11 12 char in_buff[100]; 13 14 while(1) 15 { 16 printf("Input words:\n"); 17 scanf("%s",in_buff); 18 printf("%s\n",in_buff); 19 if(in_buff[0]=='e'&&in_buff[1]=='n'&&in_buff[2]=='d') //输入结束判断,真尼玛的麻烦,但我实在懒得想更好的意义明确的结束方式~这么做树里就不能有end~ 20 break; 21 else 22 Insert(root,in_buff,strlen(in_buff)); 23 } 24 25 printf("Input search prex:\n"); 26 27 scanf("%s",in_buff); 28 29 Trie *Node = Find(root,in_buff,strlen(in_buff)); 30 31 printf("%d\n",Node->num); //output the prex number 32 33 Delete(root); 34 35 return 0; 36 }