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


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

    sug.c

      1 /* 
      2  * 单词自动补全功能
      3  * File:   search.c
      4  * Author: baijianmin
      5  */
      6 
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 #include <string.h>
     10 #include <errno.h>
     11 #include <stdarg.h>
     12 #include <time.h>
     13 
     14 #include <sys/socket.h>
     15 #include <netinet/in.h>
     16 #include <arpa/inet.h>
     17 
     18 #define MAX_CHILD 26
     19 #define LISTEN_PORT 8080
     20 #define LOG_DEBUG_PATH "./logs/debug.log"
     21 #define LOG_ERROR_PATH "./logs/error.log"
     22 #define DATA_PATH "one.txt"
     23 
     24 /**
     25  * define log level
     26  */
     27 enum log_level {
     28     DEBUG = 0,
     29     ERROR = 1
     30 };
     31 
     32 #define error(...) 
     33         logger(ERROR, __LINE__, __VA_ARGS__)
     34 
     35 #define debug(...) 
     36         logger(DEBUG, __LINE__, __VA_ARGS__)
     37 
     38 #define assert(expr, rc) 
     39         if(!(expr)){    
     40                 error(#expr"is null or 0");     
     41                 return rc;      
     42         }
     43 
     44 /**
     45  * trie node
     46  */
     47 typedef struct node_s {
     48     int count;
     49     struct node_s *child[MAX_CHILD];
     50     char words[20];
     51 } node_t;
     52 
     53 /**
     54  * global var
     55  */
     56 node_t *global_root;
     57 
     58 
     59 /**
     60  * get now timestr
     61  */
     62 static void get_time(char *time_str, size_t len) {
     63     time_t tt;
     64     struct tm local_time;
     65     time(&tt);
     66     localtime_r(&tt, &local_time);
     67     strftime(time_str, len, "%m-%d %H:%M:%S", &local_time);
     68 }
     69 
     70 /**
     71  * log
     72  */
     73 static void logger(int flag, int line, const char *fmt, ...) {
     74     FILE *fp = NULL;
     75     char time_str[20 + 1];
     76     va_list args;
     77     get_time(time_str, sizeof(time_str));
     78 
     79     switch (flag) {
     80         case DEBUG:
     81             fp = fopen(LOG_DEBUG_PATH, "a");
     82             if (!fp) {
     83                 return;
     84             }
     85             fprintf(fp, "%s DEBUG (%d:%d) ", time_str, getpid(), line);
     86             break;
     87         case ERROR:
     88             fp = fopen(LOG_ERROR_PATH, "a");
     89             if (!fp) {
     90                 return;
     91             }
     92             fprintf(fp, "%s ERROR (%d:%d) ", time_str, getpid(), line);
     93             break;
     94         default:
     95             return;
     96     }
     97 
     98     va_start(args, fmt);
     99     vfprintf(fp, fmt, args);
    100     va_end(args);
    101     fprintf(fp, "
    ");
    102 
    103     fclose(fp);
    104     return;
    105 }
    106 
    107 /**
    108  * listen fro connections on a specified port
    109  */
    110 int startup() {
    111     int sockfd = -1;
    112     struct sockaddr_in addr;
    113     memset(&addr, 0, sizeof (addr));
    114     sockfd = socket(AF_INET, SOCK_STREAM, 0);
    115     if (sockfd < 0) {
    116         error("socket fail: %s", strerror(errno));
    117         return -1;
    118     }
    119     addr.sin_family = AF_INET;
    120     addr.sin_port = htons(LISTEN_PORT);
    121     addr.sin_addr.s_addr = htonl(INADDR_ANY);
    122     if (bind(sockfd, (struct sockaddr *) &addr, sizeof (addr))) {
    123         error("bind fail: %s", strerror(errno));
    124         return -1;
    125     }
    126     if (listen(sockfd, 5)) {
    127         error("listen fail: %s", strerror(errno));
    128         return -1;
    129     }
    130     return sockfd;
    131 }
    132 
    133 /**
    134  * create node
    135  */
    136 node_t *createNode() {
    137     node_t *node = (node_t *) calloc(1, sizeof (node_t));
    138     if (node == NULL) {
    139         error("createNode fail: %s", strerror(errno));
    140     }
    141 }
    142 
    143 /**
    144  * insert words 
    145  */
    146 int insert(node_t *root, char *words) {
    147     if (!root || words[0] == '') {
    148         error("insert fail, root or words is null");
    149         return -1;
    150     }
    151     node_t *node = root;
    152     node_t *tmp;
    153     char *s = words;
    154     while (*s != '') {
    155         if (node->child[*s - 'a'] == NULL) {
    156             tmp = createNode();
    157             if (tmp == NULL) {
    158                 goto err;
    159             }
    160             node->child[*s - 'a'] = tmp;
    161         }
    162         node = node->child[*s - 'a'];
    163         s++;
    164     }
    165     node->count++;
    166     memcpy(node->words, words, strlen(words));
    167     return 0;
    168 err:
    169     return -1;
    170 }
    171 
    172 void search_child(node_t *node, int client_sock) {
    173     if (!node) {
    174         error("search_child fail, node is null");
    175         return;
    176     }
    177     int i;
    178     if (node->count) {
    179         send(client_sock, node->words, strlen(node->words), 0);
    180                 send(client_sock, "|", 1, 0);
    181     }
    182     for (i = 0; i < MAX_CHILD; i++) {
    183         if (node->child[i]) {
    184             search_child(node->child[i], client_sock);
    185         }
    186     }
    187 }
    188 
    189 /**
    190  * search
    191  */
    192 int search(node_t *root, char *words, int client_sockfd) {
    193     //--------------------------------fixme-------------------------------------
    194     char *ps = words;
    195     while (*ps != '') {
    196         if (*ps < 'a' || *ps > 'z') {
    197             *ps = '';
    198             break;
    199         }
    200         ps++;
    201     }
    202     //--------------------------------------------------------------------------
    203     if (!root || words[0] == '') {
    204         error("search fail, root or words is null");
    205         return -1;
    206     }
    207         debug("request query: %s", words);
    208     char *s = words;
    209     node_t *node = root;
    210     while (*s != '') {
    211         if (node->child[*s - 'a'] == NULL) {
    212             break;
    213         }
    214         node = node->child[*s - 'a'];
    215         s++;
    216     }
    217     if (*s == '') {
    218 #if 0        
    219         if (node->count == 0) {
    220             printf("没有搜索到这个字符串,但是它是某个字符串的前缀
    ");
    221         } else {
    222             printf("搜索到此字符串,出现次数为:%d
    ", node->count);
    223         }
    224 #endif
    225         search_child(node, client_sockfd);
    226         
    227     } else {
    228 #if 0        
    229         printf("没有搜索到这个字符串:%s, %d
    ", words, strlen(words));
    230 #endif
    231     }
    232     close(client_sockfd);
    233 }
    234 
    235 /**
    236  * free mem
    237  */
    238 void del(node_t *root) {
    239     if (!root) {
    240         error("del fail, root is null");
    241         return;
    242     }
    243 
    244     int i;
    245     for (i = 0; i < MAX_CHILD; i++) {
    246         if (root->child[i]) {
    247             del(root->child[i]);
    248         }
    249     }
    250     free(root);
    251 
    252 }
    253 
    254 /**
    255  * load data from file
    256  */
    257 int load_data() {
    258         global_root = createNode();
    259         if(!global_root){
    260                 return -1;
    261         }
    262     FILE *fp = fopen(DATA_PATH, "r");
    263     if (!fp) {
    264         error("open fail fail: %S", strerror(errno));
    265         return -1;
    266     }
    267     char words[20];
    268     while (!feof(fp) && fgets(words, sizeof (words), fp)) {
    269         words[strlen(words) - 1] = '';
    270         insert(global_root, words);
    271         memset(words, 0, sizeof (words));
    272     }
    273     debug("load_data success");
    274     return 0;
    275 }
    276 
    277 /**
    278  * response the request
    279  */
    280 void accept_request(int client_sockfd){
    281     char buf[20];
    282     memset(buf, 0, sizeof(buf));
    283     recv(client_sockfd, buf, sizeof(buf), 0);
    284     search(global_root, buf, client_sockfd);
    285     //close client connection
    286     close(client_sockfd);
    287 }
    288 
    289 int main(void) {
    290     int server_sockfd = -1, client_sockfd = -1;
    291     struct sockaddr_in client_addr;
    292     memset(&client_addr, 0, sizeof (client_sockfd));
    293     int addr_len = sizeof (client_sockfd);
    294 
    295     server_sockfd = startup();
    296     if (server_sockfd < 0) {
    297         return -1;
    298     }
    299 
    300     //load data from file
    301     load_data();
    302 
    303     //waitting for client
    304     while (1) {
    305         client_sockfd = accept(server_sockfd,
    306                 (struct sockaddr *) &client_addr, &addr_len);
    307         if(client_sockfd < 0){
    308             error("accept fail, %s", strerror(errno));
    309             return -1;
    310         }
    311         accept_request(client_sockfd);
    312     }
    313     
    314     close(server_sockfd);
    315     return 0;
    316 }

    sug.php

    <?php
    
    if($_GET['query']){
            $query = $_GET['query'];
    }else{
            exit(json_encode(array()));
    }
    
    $host = "127.0.0.1";
    $port = "8080";
    
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("Unable to create socket
    ");
    @socket_connect($socket, $host, $port) or die("Connect error.
    ");
    
    if ($err = socket_last_error($socket)){
    
            socket_close($socket);
            die(socket_strerror($err) . "
    ");
    }
    
    $len = socket_write ($socket , $query, strlen($query));
    $querys = "";
    $ret = socket_read($socket, 100);
    while($ret){
            $querys.=$ret;
            $ret = socket_read($socket, 100);
    }
    socket_close($socket);
    
    $querysArr = explode("|", $querys);
    array_pop($querysArr);
    
    echo json_encode($querysArr);

    效果:

    http://www.idoushuo.com/sug.php?query=a

  • 相关阅读:
    洛谷P1710 地铁涨价
    洛谷P1371 NOI元丹
    洛谷P2409 Y的积木
    洛谷P3392 涂国旗
    洛谷P3370 【模板】字符串哈希
    洛谷P3379 【模板】最近公共祖先(LCA)
    洛谷P3372 【模板】线段树 1
    洛谷P3373 【模板】线段树 2
    Android(java)学习笔记31:泛型高级之通配符
    Android(java)学习笔记30:泛型接口的概述和使用
  • 原文地址:https://www.cnblogs.com/bai-jimmy/p/5428186.html
Copyright © 2020-2023  润新知