(1)trie.h
#ifndef TRIE_H_ #define TRIE_H_ typedef struct word_trie_t word_trie_t; typedef enum bool bool; enum bool { false=0, true=1, }; struct word_trie_t { bool (*insert)(word_trie_t *this,char *str); bool (*find_word)(word_trie_t *this,char *str); int (*find_prefix)(word_trie_t *this,char *str); bool (*delete)(word_trie_t *this,char *str); void (*destroy)(word_trie_t *this); }; word_trie_t *word_trie_create(); #endif
(2)trie.c
#include "trie.h" #include <stdio.h> #include <string.h> #include <malloc.h> // /* 字典树节点 */ // #define TRIE_NODE_MAX 26 typedef struct trie_node_t trie_node_t; /*字典树节点结构*/ struct trie_node_t { int count; //用来计算前缀数 bool is_str; //用来标识到此的字符串 trie_node_t *word[TRIE_NODE_MAX]; //子节点指针 }; /*创建一个节点*/ trie_node_t* trie_node_create() { trie_node_t* node=(trie_node_t *)malloc(sizeof(trie_node_t)); memset(node,0,sizeof(trie_node_t)); return node; } /*回收一个节点*/ void trie_node_destroy(trie_node_t* node) { free(node); } /// /* 字典树对外接口实现 */ /// typedef struct private_word_trie_t private_word_trie_t; struct private_word_trie_t { word_trie_t public; //对外接口 trie_node_t *root; //字典树根 }; //插入一个字符串 bool insert(private_word_trie_t *this,char *str) { trie_node_t *current=this->root; int word_pos; //不断的循环插入,直到字符串结尾 while(*str) { word_pos=*str-'a'; //如果插入的分支为空,新建节点 if(current->word[word_pos]==NULL) { current->word[word_pos]=trie_node_create(); } current=current->word[word_pos]; //节点索引值增加 current->count++; str++; } //在最后一个节点标识为一个字符串 current->is_str=true; return true; } //查找节点 bool find_word(private_word_trie_t *this,char *str) { trie_node_t *current=this->root; int word_pos; while(*str) { word_pos=*str-'a'; //如果分支为空,标识没有此字符串 if((current=current->word[word_pos])==NULL) { return false; } str++; } return current->is_str; } //查找前缀数 int find_prefix(private_word_trie_t *this,char *str) { trie_node_t *current=this->root; int word_pos; while(*str) { word_pos=*str-'a'; if((current=current->word[word_pos])==NULL) { return 0; } str++; } return current->count; } //删除一个字符串 bool delete(private_word_trie_t *this,char *str) { trie_node_t *current=this->root; int word_pos; trie_node_t *del=NULL; //第一步查找,如果是曾经插入的字符串,可以删除 if(find_word(this,str)) { //释放前缀数,如果索引值为0,可以回收节点 while(*str) { word_pos=*str-'a'; if(((current->word[word_pos])->count--)==0) { del=current->word[word_pos]; current->word[word_pos]=NULL; str++; break; } str++; } //释放下面的节点 if(del!=NULL) { while(*str) { word_pos=*str-'a'; current=del; del=current->word[word_pos]; trie_node_destroy(current); str++; } trie_node_destroy(del); } return true; } else { return false; } } //递归回收节点 void trie_destroy(trie_node_t *node) { int i; for(i=0;i<TRIE_NODE_MAX;i++) { if(node->word[i]!=NULL) { trie_destroy(node->word[i]); } } trie_node_destroy(node); } //销毁节点树 void destroy(private_word_trie_t *this) { trie_destroy(this->root); free(this); } //创建字典树对象 word_trie_t *word_trie_create() { private_word_trie_t *this=(private_word_trie_t *)malloc(sizeof(private_word_trie_t)); this->public.insert=(bool (*)(word_trie_t *,char *))insert; this->public.find_word=(bool (*)(word_trie_t *,char *))find_word; this->public.find_prefix=(int (*)(word_trie_t *,char *))find_prefix; this->public.delete=(bool (*)(word_trie_t *,char *))delete; this->public.destroy=(void (*)(word_trie_t *))destroy; this->root=trie_node_create(); return &this->public; } int main() { word_trie_t *tree=word_trie_create(); char str[100]; while(gets(str)&&str[0]) { tree->insert(tree,str); } while(gets(str)&&str[0]) { printf("前缀:%d\n",tree->find_prefix(tree,str)); if(tree->find_word(tree,str)) { printf("%s是插入的一个字符串\n",str); } else { printf("%s不是插入的一个字符串\n",str); } } tree->destroy(tree); return 1; }