数据结构 ——前缀树查词典的实现
一、前缀树的概念
- 前缀树是一种多叉树结构,主要用于存储字符串。每个节点代表一个字符,路径从根节点到叶节点表示一个完整的字符串。前缀树的关键特征是 共享前缀,也就是说,如果两个字符串有相同的前缀,它们会共享前缀部分的节点。
- 优点:由于共享前缀,前缀树能有效地节省空间,并且支持快速查找、插入、删除操作,尤其是在处理大量字符串时非常高效。
- 应用场景:主要用于实现高效的字符串查找、自动补全、词典查询等。
二、查词典的代码实现

 插入key:ant过程,查找单词同插入差不多

 插入key:donkey
 
下面是利用前缀树在一个给定的文件log.txt,来实现一个简单的查词典功能
//log,txt
ant:a samll insect that lives in group
butterfly:a flying insect with a long thin body
cobra:a highly dangerous snake
donkey: a animal with short legs and long ears
//利用前缀数,根据提供的文件实现一个简单的查词典功能
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DESC_SIZE  256
#define KEY_SIZE   256
#define BUFSIZE    512
#define FNAME      "log.txt"
struct node_st
{
    struct node_st *ch[26];//存放26个字母
    char desc[DESC_SIZE];//单词的描述
};
//根据:拆分关键字和描述  donkey: a animal with short legs and long ears
int get_word(FILE *fp, char *key, char *desc)
{
    char buf[BUFSIZE];//用于存放读出来的一行的字符
    char *retp;
    int i,j;
    retp=fgets(buf,BUFSIZE,fp);//从fp文件,读取BUFSIZE个字符,存到buf中 
    //文件读取失败
    if (retp==NULL)
       return -1; 
    //把关键字和描述分开  KEY_SIZE-1是预留一个尾0
    for(i=0;i<KEY_SIZE-1 && buf[i]!=':';i++) 
        key[i]=buf[i];
    key[i]='\0';
    i++;
    for(j=0;j<DESC_SIZE-1 && buf[i]!='\0';j++,i++)
        desc[j]=buf[i];
    desc[j]='\0';
    return 0;  
}
struct node_st *newnode()
{
    struct node_st *node;
    int i;
    node=malloc(sizeof(*node));//申请的是 struct node_st的内存,指针内存是struct node_st *
    if(node==NULL)
        return NULL;
    //初始化一个指针数组ch和描述字符串desc
    node->desc[0]='\0';//字符串是以空字符结尾的字符数组,将第一个字符设置为 '\0' 实际创建了一个空字符串
    for(i=0;i<26;i++)
        node->ch[i]=NULL;
    return node;
}
int insert(struct node_st **root, char *key, char *desc)
{
    if(*root==NULL)
    {
        *root=newnode();
        if(*root==NULL)
            return -1;
    }
    if(*key=='\0')
    {
        strcpy((*root)->desc,desc);
        return 0;
    }
   /*注意(*root)->ch+*key-'a'和root->ch[*key-'a']的区别
   struct node_st *ch[26]定义一个指针数组,ch指向的是一个结构体数组,数组的每一个元素存的是指针值 ch[1]=*(ch+1) 表示的是这个数组首地址偏移一个位置的解引用 *&,访问的是这个偏移一个位置后的数据,且该数据存的是一个指针,为一级指针
   ch+1 则是一个二级指针,表示指向的是这个指针数组首地址偏移一个位置后的地址
   */
    return insert((*root)->ch+*key-'a',key+1,desc);//
}
char *find(struct node_st *root, char *key)
{
    if(root==NULL)
        return NULL;
    if(*key=='\0')
        return root->desc;
    return find(root->ch[*key-'a'],key+1);
    
}
int main() 
{
    FILE *fp;
    struct node_st *tree=NULL;
    char desc[DESC_SIZE]={'\0'}, key[KEY_SIZE]={'\0'};
    int ret;
    char *datap;
    fp=fopen(FNAME,"r");
    if(fp==NULL)
    {
        fprintf(stderr,"fopen():error\n");
        return -1;
    }
    while (1)
    {
        //拆单词
        ret=get_word(fp,key,desc);
        if(ret==-1)
            break;
        //测试key和desc是否分开
        // puts(key);
        // puts(desc);
        insert(&tree,key,desc);
    }
    // datap=find(tree,"donkey");
    datap=find(tree,"hello");
    if(datap==NULL)
        printf("Can not found!\n");
    else
        puts(datap);
    fclose(fp);
    return 0;
}
关于指针数组的一点理解
 



















