字典树-小记

本文深入探讨了字典树(又称Trie树、前缀树),一种特殊的哈希树变种,主要用於高效地进行字符串查找。通过比较字典树与一般多叉树的结构差异,展示了其在节点设计上的独特之处,如字母映射表。通过实例解释了字典树如何存储数据,并提供了插入、搜索和前缀查询的实现代码。此外,还介绍了字典树在单词查找和前缀匹配等场景中的应用。
摘要由CSDN通过智能技术生成

字典树通俗的叫法有:Trie树、单词查找树、前缀树,是一种哈希树的变种

为什么说非典型呢?因为它和一般的多叉树不一样,尤其在结点的数据结构设计上

结构体差异

一般的多叉树的结点是这样的

typedef struct TreeNode {
    VALUETYPE value;            //结点值
    TreeNode* children[NUM];    //指向孩子结点
}TreeNode;

字典树的结构体是这样的

typedef struct TrieNode {
    bool isEnd;             //该结点是否是一个串的结束
    TrieNode* children[26]; //字母映射表
}TrieNode;

由两个结构体相比可以看出差异 ,接下来我们一起看看字母映射表

字母映射表

以 "sea","sells","she"为例,看下这三个单词在字典树中是如何存储的

省去上图中的空指针,可以画出如下图像

实际并非如此,但我们仍可这样理解

“sea”:“a”的父节点是“e”,“e”的父节点是 “s”,前缀树、字典树的名字由此而来

字典树的操作

结构体

typedef struct Trie {
    struct Trie *children[26];
    bool isEnd;
} Trie;

创建

Trie *trieCreate()
{
    Trie *trie = (Trie *)malloc(sizeof(Trie));
    memset(trie->children, 0, sizeof(trie->children));
    trie->isEnd = false;
    return trie;
}

插入

void trieInsert(Trie *obj, char *word)
{
    int wordLength = strlen(word);
    Trie *trieP = obj;
    for (int i = 0; i < wordLength; i++) {
        int wordInd = word[i] - 'a';
        if (trieP->children[wordInd] == 0) {
            trieP->children[wordInd] = trieCreate();
        }
        trieP = trieP->children[wordInd];
    }
    trieP->isEnd = true;
}

查询

bool trieSearch(Trie *obj, char *word)
{
    int wordLength = strlen(word);
    Trie *trieP = obj;
    for (int i = 0; i < wordLength; i++) {
        int wordInd = word[i] - 'a';
        if (trieP->children[wordInd] == NULL) {
            return false;
        }
        trieP = trieP->children[wordInd];
    }
    return trieP->isEnd;
}

前缀查询

bool trieStartsWith(Trie *obj, char *prefix)
{
    int wordLength = strlen(prefix);
    Trie *trieP = obj;
    for (int i = 0; i < wordLength; i++) {
        int wordInd = prefix[i] - 'a';
        if (trieP->children[wordInd] == NULL) {
            return false;
        }
        trieP = trieP->children[wordInd];
    }
    return true;
}

释放

void trieFree(Trie *obj)
{
    for (int i = 0; i < 26; i++) {
        if (obj->children[i]) {
            trieFree(obj->children[i]);
        }
    }
    free(obj);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值