1. /**
  2. * 实现单词补全功能
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <errno.h>
  8. #include <stdarg.h>
  9.  
  10. #define MAX_CHILD 26
  11.  
  12. #define error(...) \
  13. logger(stderr, __LINE__, __VA_ARGS__)
  14.  
  15. #define notice(...) \
  16. logger(stdout, __LINE__, __VA_ARGS__)
  17.  
  18. /**
  19. * 定义trie树节点
  20. */
  21. typedef struct node_s{
  22. int count;
  23. struct node_s *child[MAX_CHILD];
  24. char words[];
  25. } node_t;
  26.  
  27. /**
  28. * 日志
  29. */
  30. void logger(FILE *fp, int line, const char *fmt, ...){
  31. fprintf(fp, "[line]:%d | ", line);
  32. va_list ap;
  33. va_start(ap, fmt);
  34. vfprintf(fp, fmt, ap);
  35. va_end(ap);
  36. fprintf(fp, "\n");
  37. }
  38.  
  39. /**
  40. * 创建节点
  41. */
  42. node_t *createNode(){
  43. node_t *node = (node_t *)calloc(, sizeof(node_t));
  44. if(node == NULL){
  45. error("createNode fail, errno[%d]", errno);
  46. }
  47. }
  48.  
  49. /**
  50. * 添加
  51. */
  52. int insert(node_t *root, char *words){
  53. if(!root || words[] == '\0'){
  54. error("insert fail, root or words is null");
  55. return -;
  56. }
  57. node_t *node = root;
  58. node_t *tmp;
  59. char *s = words;
  60. while(*s != '\0'){
  61. if(node->child[*s - 'a'] == NULL){
  62. tmp = createNode();
  63. if(tmp == NULL){
  64. goto err;
  65. }
  66. node->child[*s - 'a'] = tmp;
  67. }
  68. node = node->child[*s - 'a'];
  69. s++;
  70. }
  71. node->count++;
  72. memcpy(node->words, words, strlen(words));
  73. notice("insert success, words = %s", words);
  74. return ;
  75. err:
  76. return -;
  77. }
  78.  
  79. /**
  80. * 搜索指定单词
  81. */
  82. int search(node_t *root, char *words){
  83. if(!root || words[] == '\0'){
  84. error("search fail, root or words is null");
  85. return -;
  86. }
  87. char *s = words;
  88. node_t *node = root;
  89. while(*s != '\0'){
  90. if(node->child[*s - 'a'] == NULL){
  91. break;
  92. }
  93. node = node->child[*s - 'a'];
  94. s++;
  95. }
  96. if(*s == '\0'){
  97. if(node->count == ){
  98. printf("没有搜索到这个字符串,但是它是某个字符串的前缀\n");
  99. }else{
  100. printf("搜索到此字符串,出现次数为:%d\n", node->count);
  101. }
  102.  
  103. searchChild(node);
  104. }else{
  105. printf("没有搜索到这个字符串\n");
  106. }
  107. }
  108.  
  109. /**
  110. * 遍历出来的子节点是排序后的
  111. */
  112. void searchChild(node_t *node){
  113. if(!node){
  114. error("searchChild fail, node is null");
  115. return;
  116. }
  117. int i;
  118. if(node->count){
  119. printf("%s\n", node->words);
  120. }
  121. for(i = ; i < MAX_CHILD; i++){
  122. if(node->child[i]){
  123. searchChild(node->child[i]);
  124. }
  125. }
  126. }
  127.  
  128. /**
  129. * 递归回收内存
  130. */
  131. void del(node_t *root){
  132. if(!root){
  133. error("del fail, root is null");
  134. return;
  135. }
  136.  
  137. int i;
  138. for(i = ; i < MAX_CHILD; i++){
  139. if(root->child[i]){
  140. del(root->child[i]);
  141. }
  142. }
  143. free(root);
  144.  
  145. }
  146.  
  147. int main(){
  148. char *str = "jimmy";
  149. node_t *root = createNode();
  150. if(!root){
  151. return -;
  152. }
  153.  
  154. //insert(root, str);
  155. //search(root, "j");
  156. FILE *fp = fopen("one.txt", "r");
  157. if(!fp){
  158. perror("open file fail");
  159. }
  160. char words[];
  161. while(!feof(fp)){
  162. fgets(words, sizeof(words), fp);
  163. //去掉回车符
  164. words[strlen(words) - ] = '\0';
  165. insert(root, words);
  166. memset(words, , sizeof(words));
  167. }
  168.  
  169. while(scanf("%s", words)){
  170. search(root, words);
  171. }
  172.  
  173. del(root);
  174. }

运行效果如下:

通过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. ABySS非root权限安装

    本文转自  http://yangl.net/2015/11/12/abyss_install/ ABySS: ABySS is a de novo, parallel, paired-end seq ...

  2. Java 四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor

    介绍new Thread的弊端及Java四种线程池的使用,对Android同样适用.本文是基础篇,后面会分享下线程池一些高级功能. 1.new Thread的弊端执行一个异步任务你还只是如下new T ...

  3. stm32 usart 异步传输示例

    STM32F103xE的USART异步数据传输示例 USART全称Universal Synchronous/Asynchronous Receiver/Transmitter,是一种可以进行同步/异 ...

  4. Atitit.atiagent  agent分销系统 代理系统 设计文档

    Atitit.atiagent  agent分销系统 代理系统 设计文档 1. 启动项目1 2. 首也2 3. 登录功能2 4. 用户中心2 5. 充值查询3 6. 授权下级代理4 7. 我的提成5 ...

  5. springmvc+mybatis+spring 整合源码项目

    A集成代码生成器 [正反双向(单表.主表.明细表.树形表,开发利器)+快速构建表单; freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本,处理类,service等 ...

  6. django基础篇

    Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. ...

  7. iOS PresentViewControlle后,直接返回根视图

    在开发中:用[self presentViewController:VC animated:YES completion:nil];实现跳转,多次跳转后,直接返回第一个. 例如: A presentV ...

  8. 初识JavaScript 变量, 操作符, 数组

    这里讲的不会太多, 因为所有的语言都是一样的, 一些基本的东西, 所以就随便写写. 变量 变量就是可变的量, 编程角度理解就是用于存储某种/某些数值的存储器. 我们可以把变量具象理解为一个盒子, 而我 ...

  9. window.frameElement的使用

    window.frameElement的使用: 返回嵌入当前window对象的元素(比如 <iframe> 或者 <object>),如果当前window对象已经是顶层窗口,则 ...

  10. SQLServer复制(二)--事务代理作业

    之前的一篇已经介绍了如何配置复制,介绍了发布者.分发者和订阅者以及事务日志运行的简单关系.其中提到了复制代理,我们这篇将详细介绍复制代理,它是什么?在事务复制的步骤中起到了什么作用? 代理和工作 首先 ...