trie树及其应用

来源:互联网 发布:气宗 剑宗 知乎 编辑:程序博客网 时间:2024/05/21 10:41

参考内容:

1.  这位童鞋的文章 http://blog.csdn.net/zhulei632/article/details/6704496

2.  严蔚敏 -数据结构

1.键树的定义:

   键树又叫“数字查找树”。深度>=2  . 树中的每个节点一般不是直接包含关键字,而是包含组成关键字的符号(当然叶子节点除外,叶子节点可能包含整个单词以及词频,非叶节点也可包含单词和词频)。根据存储结构的不同,又分为双链树和多重链表树。或者就是常说的“Trie树”,取自检索“retrieve”中间的四个单词。因此也被称为检索树。Trie树的每个节点含有d个指针域(d为关键字的基数,如果是字母,那么基数为26 即a-z .如果是数字,那么基数是10, 即0-9)。

如图所示,一个Trie树的结构如下:

如果在trie树的node节点添加新的域 count,记录已有的单词总数。那么,Trie树除了实现单词查询之外,还可以实现单词频度统计。

如,我们定义的Trie树的节点结构如下:

[cpp] view plaincopyprint?
  1. typedef struct Trie_node{  
  2.     int  count;  
  3.     struct Trie_node *next[26];  
  4.   
  5. }TrieNode, *Trie;  
其中next数组指向下一层次节点。

有了这个结构。Trie树的实现就有了一个基础。

2。Trie树的建立

建立一个Trie树的过程就是不断添加新的单词的过程。由根节点向下扫描,如果不存在相应的节点则创建之。否则进入下一个层次,直到单词添加完毕。

根据该算法,代码不难写出:

[cpp] view plaincopyprint?
  1. //创建新的节点  
  2. TrieNode* createTrieNode(){  
  3.     TrieNode* root = (TrieNode*)malloc(sizeof(TrieNode));  
  4.     root->count = 0;  
  5.     memset(root->next, 0, sizeof(root->next));  
  6.     return root;  
  7. }  
  8. //插入单词。  
  9. void trie_insert(Trie root, char* word){  
  10.     TrieNode* node = root;  
  11.     char *p = word;  
  12.     while(*p)  
  13.     {  
  14.         if(NULL == node->next[*p-'a'])  
  15.         {  
  16.             node->next[*p-'a'] = createTrieNode();  
  17.         }  
  18.         node = node->next[*p-'a'];  
  19.         p++;  
  20.     }  
  21.     node->count += 1;  
  22. }  

3 .Trie树的检索

Trie树中检索的过程是走一条从跟节点开始到叶子节点的路径(不一定走到叶子节点,取决于你的Trie树的实现,如果规定每个单词以$结束,那么检索成功的话一定走到叶子节点):如下图示意,检索单词bat的路径用红色标出。

实现检索的代码:

[cpp] view plaincopyprint?
  1. int trie_search(Trie root, char* word){  
  2.     TrieNode* node = root;  
  3.     char *p = word;  
  4.     while(*p && node!=NULL)  
  5.     {  
  6.         node = node->next[*p-'a'];  
  7.         p++;  
  8.     }  
  9.     return (node != NULL && node->count > 0);  
  10. }  

4. 利用Trie树实现词频统计

如上文所述:在Trie的node节点中添加count域后,可以统计单词出现的次数。统计的方法就是在插入单词的时候,令相应的count域加1(初始化为0)。代码见Trie插入部分。


完整的测试代码如下:

[cpp] view plaincopyprint?
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <memory.h>  
  4.   
  5. typedef struct Trie_node{  
  6.     int  count;  
  7.     struct Trie_node *next[26];  
  8.   
  9. }TrieNode, *Trie;  
  10.   
  11. TrieNode* createTrieNode(){  
  12.     TrieNode* root = (TrieNode*)malloc(sizeof(TrieNode));  
  13.     root->count = 0;  
  14.     memset(root->next, 0, sizeof(root->next));  
  15.     return root;  
  16. }  
  17.   
  18. void trie_insert(Trie root, char* word){  
  19.     TrieNode* node = root;  
  20.     char *p = word;  
  21.     while(*p){  
  22.         if(NULL == node->next[*p-'a']){  
  23.             node->next[*p-'a'] = createTrieNode();  
  24.         }  
  25.         node = node->next[*p-'a'];  
  26.         p++;  
  27.     }  
  28.     node->count += 1;  
  29. }  
  30.   
  31. int trie_search(Trie root, char* word){  
  32.     TrieNode* node = root;  
  33.     char *p = word;  
  34.     while(*p && node!=NULL){  
  35.         node = node->next[*p-'a'];  
  36.         p++;  
  37.     }  
  38.     return (node != NULL && node->count > 0);  
  39. }  
  40.   
  41. int trie_word_count(Trie root, char* word){  
  42.     TrieNode * node = root;  
  43.     char *p = word;  
  44.     while(*p &&node != NULL){  
  45.         node = node->next[*p-'a'];  
  46.         p++;  
  47.     }  
  48.     return node->count;  
  49. }  
  50.   
  51.   
  52. int main(){  
  53.     Trie t = createTrieNode();  
  54.     char word[][10] = {"test","study","open","show","shit","work","work","test","tea","word","area","word","test","test","test"};  
  55.     for(int i = 0;i < 15;i++ ){  
  56.         trie_insert(t,word[i]);  
  57.     }  
  58.     for(int i = 0;i < 15;i++ ){  
  59.         printf("the word %s appears %d times in the trie-tree\n",word[i],trie_word_count(t,word[i]));  
  60.     }  
  61.     char s[10] = "testit";  
  62.     printf("the word %s exist? %d \n",s,trie_search(t,s));  
  63.     return 0;  
  64. }  

运行结果如下:




版权声明:本文为博主原创文章,未经博主允许不得转载。

0 0
原创粉丝点击