Trie 字典树

字典树是哈希树的变种, 它采用公用前缀的方式来提高效率, 刚开始以为公用前缀, 空间会节省, 后来想想, 空间也不是节省, 因为每一个都有26个指针(这里假设都是小写字母的话), 不过他的时间复杂度是常数级的, 效率非常高, O(1)的复杂度, 它是典型的空间换时间, 他常用的功能是增删查, 其实删除并不算太常用, 增加和查找用的比较多点.具体的实现代码如下:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 //结构体里面可以灵活的加一些东西,根据功能来加
  5 typedef struct Node{
  6     int isWord;//标记是否到这里是个单词
  7     struct Node *next[26];//26个子孩子,
  8 }Node, *PNode;
  9 
 10 void add_word(PNode *root, char *word)//将指定单词添加到字典树
 11 {
 12     PNode node;
 13     int len = strlen(word);
 14     int i = 0;
 15     PNode ptr = *root;
 16     while(i < len)
 17     {
 18         if(ptr->next[word[i] - 'a'] == NULL)
 19         {
 20             node = (PNode)malloc(sizeof(Node));
 21             for(int j = 0; j < 26; j++)
 22             {
 23                 node->isWord = 0;
 24                 node->next[j] = NULL;
 25             }
 26             ptr->next[word[i] - 'a'] = node;
 27         }
 28         ptr = ptr->next[word[i] - 'a'];
 29         i++;
 30     }
 31     ptr->isWord = 1;//最后标记这个点是单词的结尾
 32 }
 33 
 34 void search_word(PNode root, char *word)//查找单词,递归方式
 35 {
 36     if(word[0] != '\0' && root->next[word[0] - 'a'] == NULL)
 37     {
 38         printf("No this word\n");
 39         return;
 40     }
 41     if(word[0] == '\0')
 42     {
 43         if(root == NULL)
 44             printf("exist!\n");
 45         else
 46         {
 47             if(root->isWord == 1)
 48                 printf("exist!\n");
 49             else
 50                 printf("No this word\n");
 51         }
 52         return;
 53     }
 54     search_word(root->next[word[0] - 'a'], word + 1);
 55 }
 56 //查找单词,非递归方式
 57 int search_words(PNode root, char *word)
 58 {
 59     int len = strlen(word);
 60     int i = 0;
 61     PNode ptr = root;
 62     while(i < len)
 63     {
 64         if(ptr->next[word[i] - 'a'] == NULL)
 65             return 0;
 66         ptr = ptr->next[word[i] - 'a'];
 67         i++;
 68     }
 69     if(ptr->isWord == 1)
 70         return 1;
 71     return 0;
 72 }
 73 //删除指定的单词,这里只是将它的标记设为0, 并没有真正意义上的删除
 74 void delete_word(PNode *root, char *word)
 75 {
 76     if(word[0] == '\0' && (*root) != NULL)
 77     {
 78         (*root)->isWord = 0;
 79         return;
 80     }
 81     if((*root) == NULL)
 82     {
 83         printf("No this word\n");
 84         return;
 85     }
 86     delete_word(&(*root)->next[word[0] - 'a'], word + 1);
 87 }
 88 //删除整个字典树,真正的删除
 89 //如果要在函数里面调用此函数的时候,调用完之后如果还想创建树,要重新malloc根节点
 90 void delete_all(PNode root)
 91 {
 92     for(int i = 0; i < 26; i++)
 93     {
 94         if(root->next[i] != NULL)
 95             delete_all(root->next[i]);
 96     }
 97     free(root);
 98 }
 99 
100 int main()
101 {
102     int choice;
103     char str[100];
104     PNode root = (PNode)malloc(sizeof(Node));
105     root->isWord = 0;
106     for(int i = 0; i < 26; i++)
107         root->next[i] = NULL;
108     do{
109         //测试菜单
110         printf("1. add word   2. search word   3. delete word   0. exit\n");
111         scanf("%d", &choice);
112         switch(choice)
113         {
114         case 1:
115             scanf("%s", str);
116             add_word(&root, str);
117             break;
118         case 2:
119             scanf("%s", str);
120             if(search_words(root, str) == 1)
121                 printf("exist\n");
122             else
123                 printf("not found\n");
124             //当然也可以用递归的那个
125 //            search_word(root, str);
126             break;
127         case 3:
128             scanf("%s", str);
129             delete_word(&root, str);
130         default:
131             break;
132         }
133     }while(choice != 0);
134     delete_all(root);
135     return 0;
136 }

 

posted @ 2014-10-15 19:09  Howe_Young  阅读(207)  评论(0编辑  收藏  举报