2013 年 6 月 8 日 by sciencefans
之前的一篇博客讲到我在哈佛cs50的课堂中学习到了trie树这一神器,但是一直都没机会自己实现,正值端午放五天假,今晚熬夜实现了一下,发现还是学到了不少细节处理的东西。在实现中出了很多错误,也学了很多知识。
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #define MAX 26 5 6 typedef struct TrieNode //Trie结点声明 7 { 8 bool isStr; //标记该结点处是否构成单词 9 struct TrieNode *next[MAX]; //儿子分支 10 }Trie; 11 12 void insert(Trie *root, const char *s) //将单词s插入到字典树中 13 { 14 if(root == NULL||*s == '\0') 15 return; 16 int i; 17 Trie *p = root; 18 while(*s != '\0') 19 { 20 if(p->next[*s - 'a'] == NULL) //如果不存在,则建立结点 21 { 22 Trie *temp=(Trie *)malloc(sizeof(Trie)); 23 for(i = 0;i < MAX; i++) 24 { 25 temp->next[i] = NULL; 26 } 27 temp->isStr = false; 28 p->next[*s - 'a'] = temp; 29 p = p->next[*s - 'a']; 30 } 31 else 32 { 33 p = p->next[*s - 'a']; 34 } 35 s++; 36 } 37 p->isStr=true; //单词结束的地方标记此处可以构成一个单词 38 } 39 40 int search(Trie *root,const char *s) //查找某个单词是否已经存在 41 { 42 Trie *p = root; 43 while(p != NULL && *s != '\0') 44 { 45 p = p->next[*s-'a']; 46 s++; 47 } 48 return(p!=NULL && p->isStr==true); //在单词结束处的标记为true时,单词才存在 49 } 50 51 void del(Trie *root) //释放整个字典树占的堆区空间 52 { 53 int i; 54 for(i = 0;i < MAX; i++) 55 { 56 if(root->next[i] != NULL) 57 { 58 del(root->next[i]); 59 } 60 } 61 free(root); 62 } 63 64 int main(int argc,char*argv[]) 65 { 66 int i; 67 int n, m; //n为建立Trie树输入的单词数,m为要查找的单词数 68 char s[100]; 69 Trie *root= (Trie *)malloc(sizeof(Trie)); 70 for(i = 0;i < max; i++) 71 { 72 root->next[i]=NULL; 73 } 74 root->isStr = false; 75 scanf("%d",&n); 76 getchar(); 77 for(i = 0; i < n; i++) //先建立字典树 78 { 79 scanf("%s",s); 80 insert(root,s); 81 } 82 while(scanf("%d",&m)!=EOF) 83 { 84 for(i=0;i < m; i++) //查找 85 { 86 scanf("%s",s); 87 if(search(root,s)) 88 printf("YES\n"); 89 else 90 printf("NO\n"); 91 } 92 printf("\n"); 93 } 94 del(root); //释放空间很重要 95 return 0; 96 }