(字典树)C/C++之Trie树(最通俗易懂的代码(含详细注释))

前言

最近无聊,用70%C和30%C++写了个Trie树的源程序,源码可在CodeBlocks、VC++等上面运行

Trie树

含义:
Trie树,即字典树,又称单词查找树,是一种树形结构,是一种哈希树的变种。
典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以
经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀
来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

三个基本性质:
1.根节点不包含字符,除根节点外每一个节点都只包含一个字符; 
2.从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串;
3.每个节点的所有子节点包含的字符都不相同。

简而言之,Trie树就是根据公共前缀来存储元素的多叉树吧(下图转载)
在这里插入图片描述

一.题目要求

1)初始化
2)插入元素
3)删除元素
4)查找元素
5)Trie树的应用

二.数据结构体

typedef struct TrieNode {
   
    struct TrieNode *next[Max];//(256个Ascll码)
    int if_end;//判断结点是否某元素最后一个字符
    int node_count;  //子next的数量
    char word;//储存一个字符
	} TrieNode, *TrieNodePtr, *TrieSTPtr;

三.主要函数

1. 插入函数 void Trie_insert(TrieNodePtr root,char *word)
	包含的参数:Trie数的根节点root , 插入元素的字符串地址word。
	返回值:(无返回值)。

2.查找函数 int searchTrie(TrieNodePtr root,char *word)
	包含的参数:Trie数的根节点root , 查询元素的字符串地址word。
	返回值:(int类型)如果存在就返回1,不存在就返回0。
3.删除函数 
	TrieNodePtr Trie_delect(TrieNodePtr root,char *word,int locate)
	包含的参数:Trie数的某节点root,被删除元素的字符串地址word和该元素
	的第locate个字符。
	返回值:(结构图指针类型)返回值是否NULL决定了递归时要进行的操作

四.函数块及其解析

1.插入函数
   trie树是一棵多叉树,它的插入要遵循相邻两个结点存储的字符不能相同这
   一规则,并且新建结点要用calloc使其结点内容初始化为空,若是已存在该
   结点,它的父母结点的子节点数要加1,若是已到达插入元素的最后一个
   结点,需要把最后一个结点的元素结束标志改为TRUE。
void Trie_insert(TrieNodePtr root, char *word){
   
    int i = 0;
    TrieSTPtr tmp = root;
    while (*(word + i) != '\0') {
   
        int Ascll=*(word + i);//将字符转为其Ascll码
        /*
         如果树里面没有这个字符,就录入
        */
        if (tmp->next[abs(Ascll)] == NULL)//用abs是先前出于中文汉字输入的考虑。但是最终放弃,干脆也不删除了。
            {
   
                tmp->next[abs(Ascll)] = (TrieNode *)calloc(1, sizeof(TrieNode));
                tmp->next[abs(Ascll)]->word=*(word+i);
                tmp->node_count++;//在进入新的字符结点之前,旧结点记录的next数量要加1。
            }
        tmp = tmp->next[abs(Ascll)];
        i++;
    }
    tmp->if_end = TRUE;//出循环代表整个元素所有字符录入完毕,需要在最后一个字符结点做个元素标记
}
 2.查找函数
	查找函数在判断条件上类似于插入函数,如果元素的某个字符在Trie树
	中不存在对应结点,说明不存在该元素,直接结束查找。如果所有
	字符均存在且最后一个字符结点的元素结束标志是TRUE,元素存在。
int searchTrie(TrieNodePtr root,char *word) {
   
    if(root==NULL) {
   
        printf("该Trie树未初始化!\n");
        return 0 ;
    }
    TrieNodePtr tmp=root;
    int i=0;
    while(word[i]!='\0') {
   
        int Ascll=abs(word[i]);
        if(tmp->next[Ascll]==NULL){
   printf("没有该元素(或已删除)!\n");return 0 ;}
        else tmp=tmp->next[Ascll];
        i++;
    }
    if (tmp->if_end == TRUE){
   
        printf(
  • 11
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
好的,下面是C语言实现的字典树词频统计代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define MAX_WORD_LEN 100 // 单词最大长度 // 字典树节点结构体 typedef struct TrieNode { int count; // 记录单词出现次数 struct TrieNode* next[26]; // 指向下一个字符的指针数组 } TrieNode; // 创建新的字典树节点 TrieNode* newTrieNode() { TrieNode* node = (TrieNode*)malloc(sizeof(TrieNode)); node->count = 0; memset(node->next, 0, sizeof(node->next)); return node; } // 将单词插入字典树 void insertWord(TrieNode* root, char* word) { TrieNode* node = root; int len = strlen(word); for (int i = 0; i < len; i++) { int index = tolower(word[i]) - 'a'; // 转换为小写字母后计算下标 if (node->next[index] == NULL) { node->next[index] = newTrieNode(); } node = node->next[index]; } node->count++; } // 统计单词出现次数 int countWords(TrieNode* root, char* word) { TrieNode* node = root; int len = strlen(word); for (int i = 0; i < len; i++) { int index = tolower(word[i]) - 'a'; // 转换为小写字母后计算下标 if (node->next[index] == NULL) { return 0; } node = node->next[index]; } return node->count; } int main() { TrieNode* root = newTrieNode(); char filename[100]; printf("请输入要统计的文本文件名:"); scanf("%s", filename); FILE* fp = fopen(filename, "r"); if (fp == NULL) { printf("文件打开失败!\n"); return 0; } char word[MAX_WORD_LEN]; while (fscanf(fp, "%s", word) != EOF) { insertWord(root, word); } fclose(fp); printf("请输入要查询的单词(输入quit结束查询):\n"); while (1) { scanf("%s", word); if (strcmp(word, "quit") == 0) { break; } printf("%s: %d\n", word, countWords(root, word)); } return 0; } ``` 这份代码可以读取一个文本文件,将其中的单词插入字典树中,并且可以查询某个单词在文本中出现的次数。在插入单词和查询单词时,会将单词转换为小写字母后再进行操作,这样可以避免大小写不同的单词被算作不同的单词

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值