通过trie树实现单词自动补全

时间:2021-10-12 23:21:50
/**
* 实现单词补全功能
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h> #define MAX_CHILD 26 #define error(...) \
logger(stderr, __LINE__, __VA_ARGS__) #define notice(...) \
logger(stdout, __LINE__, __VA_ARGS__) /**
* 定义trie树节点
*/
typedef struct node_s{
int count;
struct node_s *child[MAX_CHILD];
char words[];
} node_t; /**
* 日志
*/
void logger(FILE *fp, int line, const char *fmt, ...){
fprintf(fp, "[line]:%d | ", line);
va_list ap;
va_start(ap, fmt);
vfprintf(fp, fmt, ap);
va_end(ap);
fprintf(fp, "\n");
} /**
* 创建节点
*/
node_t *createNode(){
node_t *node = (node_t *)calloc(, sizeof(node_t));
if(node == NULL){
error("createNode fail, errno[%d]", errno);
}
} /**
* 添加
*/
int insert(node_t *root, char *words){
if(!root || words[] == '\0'){
error("insert fail, root or words is null");
return -;
}
node_t *node = root;
node_t *tmp;
char *s = words;
while(*s != '\0'){
if(node->child[*s - 'a'] == NULL){
tmp = createNode();
if(tmp == NULL){
goto err;
}
node->child[*s - 'a'] = tmp;
}
node = node->child[*s - 'a'];
s++;
}
node->count++;
memcpy(node->words, words, strlen(words));
notice("insert success, words = %s", words);
return ;
err:
return -;
} /**
* 搜索指定单词
*/
int search(node_t *root, char *words){
if(!root || words[] == '\0'){
error("search fail, root or words is null");
return -;
}
char *s = words;
node_t *node = root;
while(*s != '\0'){
if(node->child[*s - 'a'] == NULL){
break;
}
node = node->child[*s - 'a'];
s++;
}
if(*s == '\0'){
if(node->count == ){
printf("没有搜索到这个字符串,但是它是某个字符串的前缀\n");
}else{
printf("搜索到此字符串,出现次数为:%d\n", node->count);
} searchChild(node);
}else{
printf("没有搜索到这个字符串\n");
}
} /**
* 遍历出来的子节点是排序后的
*/
void searchChild(node_t *node){
if(!node){
error("searchChild fail, node is null");
return;
}
int i;
if(node->count){
printf("%s\n", node->words);
}
for(i = ; i < MAX_CHILD; i++){
if(node->child[i]){
searchChild(node->child[i]);
}
}
} /**
* 递归回收内存
*/
void del(node_t *root){
if(!root){
error("del fail, root is null");
return;
} int i;
for(i = ; i < MAX_CHILD; i++){
if(root->child[i]){
del(root->child[i]);
}
}
free(root); } int main(){
char *str = "jimmy";
node_t *root = createNode();
if(!root){
return -;
} //insert(root, str);
//search(root, "j");
FILE *fp = fopen("one.txt", "r");
if(!fp){
perror("open file fail");
}
char words[];
while(!feof(fp)){
fgets(words, sizeof(words), fp);
//去掉回车符
words[strlen(words) - ] = '\0';
insert(root, words);
memset(words, , sizeof(words));
} while(scanf("%s", words)){
search(root, words);
} del(root);
}

运行效果如下:

通过trie树实现单词自动补全