/**
* 实现单词补全功能
*/
#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树实现单词自动补全的更多相关文章

  1. 通过trie树单词自动补全(二)

    经常使用iciba进行单词查询, 关于他的搜索建议是通过单词前缀做的索引, 所以自己想动手实现下, 当然如果借助mysql的话,一条sql语句就能实现, 网上查询了下trie正适合做这个,所以通过C语 ...

  2. 关于在php中变量少写了一个$和页面不断转圈的问题排查和vim的自动补全方式

    php中的所有变量都是页面级的, 即任何一个页面, 最多 都只能在一个文件 : 当前页面内使用, 不存在跨 文件/ 跨页面的 作用域的变量! 因此, 即使是 $GLOBALS 这个变量, 虽然叫全局 ...

  3. 我的Vim配置(自动补全/树形文件浏览)

    配置文件的下载路径在这里  http://files.cnblogs.com/files/oloroso/vim.configure.xz.gz 这实际上是一个 xz 格式的文件,添加的 gz 文件后 ...

  4. IntelliJ IDEA 设置代码提示或自动补全的快捷键 (附IntelliJ IDEA常用快捷键)

    修改方法如下: 点击 文件菜单(File) –> 点击 设置(Settings- Ctrl+Alt+S), –> 打开设置对话框. 在左侧的导航框中点击 KeyMap. 接着在右边的树型框 ...

  5. [LeetCode] Design Search Autocomplete System 设计搜索自动补全系统

    Design a search autocomplete system for a search engine. Users may input a sentence (at least one wo ...

  6. [LeetCode] 642. Design Search Autocomplete System 设计搜索自动补全系统

    Design a search autocomplete system for a search engine. Users may input a sentence (at least one wo ...

  7. Redis 实战 —— 08. 实现自动补全、分布式锁和计数信号量

    自动补全 P109 自动补全在日常业务中随处可见,应该算一种最常见最通用的功能.实际业务场景肯定要包括包含子串的情况,其实这在一定程度上转换成了搜索功能,即包含某个子串的串,且优先展示前缀匹配的串.如 ...

  8. vim自动补全功能

    1.首先下载一个插件:ctags 输入:sudo apt-get install ctags 2.Ctrl+n进行单词的自动补全

  9. Bash的自动补全

    内置补全命令 Bash内置两个补全命令,分别是compgen和complete.compgen命令根据不同的参数,生成匹配单词的候选补全列表,例子如下: monster@monster-Z:~$ co ...

随机推荐

  1. WePayUI 快快尝鲜体验

    好久没有更新博客了... 时间真的很快~~~ 不废话了..干货会直接上~~~ WePayUI是什么 WePayUI 由微信支付为服务商和商户量身打造,用于快速制作符合微信支付规范的Web页面.WePa ...

  2. EF 分页查询优化

    按照通常的方式分页查询至少要查询数据两遍,一个操作是查询总数,另一个是查询数据,这样有些耗时 这里介绍一个基于EF的插件 EntityFramework.Extended,当然这个插件有很多的功能,比 ...

  3. Angular+Grunt+Bower+Karma+Protractor (Atom)

    1. 配置bower 1.安装bower npm install -g bower 2.创建.bowerrc文件 { "directory": "src/bower&qu ...

  4. JAVA适配器模式(从现实生活角度理解代码原理)

    说道JAVA中的适配器模式,不得不引用该设计模式的固定表述"适配器模式(Adapter ):将一个类的接口转换成客户希望的另外一个接口,适配器模式使得原本由于接口不兼容而不能一起工作的那些类 ...

  5. iOS可执行文件瘦身方法

    缩减iOS安装包大小是很多中大型APP都要做的事,一般首先会对资源文件下手,压缩图片/音频,去除不必要的资源.这些资源优化做完后,我们还可以尝试对可执行文件进行瘦身,项目越大,可执行文件占用的体积越大 ...

  6. 基于redis分布式缓存实现(新浪微博案例)

    第一:Redis 是什么? Redis是基于内存.可持久化的日志型.Key-Value数据库 高性能存储系统,并提供多种语言的API. 第二:出现背景 数据结构(Data Structure)需求越来 ...

  7. Linux安装DBI/DBD-ORACLE

    本文只是学习如何配置PERL DBI.PERL DBD时,整理的一个学习实践文档,大部分参考网上资料,详情请见下面参考资料. PERL对数据库的支持广而且全,几乎所有的主流数据库都有与之相应的PERL ...

  8. Linux服务器宕机案例一则

    案例环境 操作系统 :Oracle Linux Server release 5.7 64bit 虚拟机 硬件配置 : 物理机型号为DELL R720 资源配置 :RAM 8G Intel(R) Xe ...

  9. Shell : debug

    调试shell脚本的方法: 使用命令:sh -x yourShell.sh

  10. leveldb源码分析--SSTable之Compaction

    对于compaction是leveldb中体量最大的一部分,也应该是最为复杂的部分,为了便于理解我们首先从一些基本的概念开始.下面是一些从doc/impl.html中翻译和整理的内容: Level 0 ...