通过trie树实现单词自动补全
/**
* 实现单词补全功能
*/
#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树实现单词自动补全的更多相关文章
- 通过trie树单词自动补全(二)
经常使用iciba进行单词查询, 关于他的搜索建议是通过单词前缀做的索引, 所以自己想动手实现下, 当然如果借助mysql的话,一条sql语句就能实现, 网上查询了下trie正适合做这个,所以通过C语 ...
- 关于在php中变量少写了一个$和页面不断转圈的问题排查和vim的自动补全方式
php中的所有变量都是页面级的, 即任何一个页面, 最多 都只能在一个文件 : 当前页面内使用, 不存在跨 文件/ 跨页面的 作用域的变量! 因此, 即使是 $GLOBALS 这个变量, 虽然叫全局 ...
- 我的Vim配置(自动补全/树形文件浏览)
配置文件的下载路径在这里 http://files.cnblogs.com/files/oloroso/vim.configure.xz.gz 这实际上是一个 xz 格式的文件,添加的 gz 文件后 ...
- IntelliJ IDEA 设置代码提示或自动补全的快捷键 (附IntelliJ IDEA常用快捷键)
修改方法如下: 点击 文件菜单(File) –> 点击 设置(Settings- Ctrl+Alt+S), –> 打开设置对话框. 在左侧的导航框中点击 KeyMap. 接着在右边的树型框 ...
- [LeetCode] Design Search Autocomplete System 设计搜索自动补全系统
Design a search autocomplete system for a search engine. Users may input a sentence (at least one wo ...
- [LeetCode] 642. Design Search Autocomplete System 设计搜索自动补全系统
Design a search autocomplete system for a search engine. Users may input a sentence (at least one wo ...
- Redis 实战 —— 08. 实现自动补全、分布式锁和计数信号量
自动补全 P109 自动补全在日常业务中随处可见,应该算一种最常见最通用的功能.实际业务场景肯定要包括包含子串的情况,其实这在一定程度上转换成了搜索功能,即包含某个子串的串,且优先展示前缀匹配的串.如 ...
- vim自动补全功能
1.首先下载一个插件:ctags 输入:sudo apt-get install ctags 2.Ctrl+n进行单词的自动补全
- Bash的自动补全
内置补全命令 Bash内置两个补全命令,分别是compgen和complete.compgen命令根据不同的参数,生成匹配单词的候选补全列表,例子如下: monster@monster-Z:~$ co ...
随机推荐
- 001.Getting Started -- 【入门指南】
Getting Started 入门指南 662 of 756 people found this helpful Meng.Net 自译 1. Install .NET Core 到官网安装 .NE ...
- 使用javascript和canvas画月半弯
使用javascript和canvas画月半弯,月半弯好浪漫!浏览器须支持html5 查看效果:http://keleyi.com/a/bjad/8xqdm0r2.htm 以下是代码: <!do ...
- Mac ping localhost 地址变化
title: Mac ping localhost 地址变化date: 2016-1-15 16:21:55categories: IOS tags: mac 小小程序猿我的博客:http://day ...
- Android Handler、Loop 的简单使用
1.子线程和子线程之间的通信 package lib.com.myapplication; import android.os.Bundle; import android.os.Handler; i ...
- C++实现Ping
这是一个老话题了,但是我刚学会... 我们的目的是实现这么个东西: 之所以用红框框一下是因为,从baidu.com到123.125.114.144的过程是DNS解析,我们暂时先实现ping的部分. 基 ...
- JavaScript的个人学习随手记(一)
JavaScript 简介 要学习的人可以到W3School http://www.w3school.com.cn/b.asp JavaScript 是世界上最流行的编程语言. 这门语言可用于 HT ...
- 让我们来谈谈JDBC
1.JDBC 1)JDBC简介 - JDBC就是Java中连接数据库方式 - 我们可以通过JDBC来执行SQL语句. 2)获取数据库连接 - j ...
- Linux命令学习总结:dos2unix - unix2dos
命令简介: dos2unix是将Windows格式文件转换为Unix.Linux格式的实用命令.Windows格式文件的换行符为\r\n ,而Unix&Linux文件的换行符为\n. dos2 ...
- 为什么忘记commit也会造成select查询的性能问题
今天遇到一个很有意思的问题,一个开发人员反馈在测试服务器ORACLE数据库执行的一条简单SQL语句非常缓慢,他写的一个SQL没有返回任何数据,但是耗费了几分钟的时间.让我检查分析一下原因,分析解决过后 ...
- ansible 初探nginx安装
我的配置: /etc/hosts: /etc/ansible/hosts: nglinx安装包: ansible自动化安装nginx: 1.安装ansible. 2.创建目录结构: mkdir -p ...