208. 实现 Trie (前缀树)

本文详细介绍了如何实现Trie数据结构,包括插入、搜索和检查前缀等操作。通过C++代码展示了Trie节点的定义和相关方法,强调了在插入和查找过程中的逻辑。此外,还分享了从这道题目中学到的知识点,如C++中的this指针、构造函数、类数组和递归等。
摘要由CSDN通过智能技术生成

题目描述:

Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。

请你实现 Trie 类:

Trie() 初始化前缀树对象。
void insert(String word) 向前缀树中插入字符串 word 。
boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false 。
boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false 。
 

示例:

输入
["Trie", "insert", "search", "search", "startsWith", "insert", "search"]
[[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]
输出
[null, null, true, false, true, null, true]

解释
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple");   // 返回 True
trie.search("app");     // 返回 False
trie.startsWith("app"); // 返回 True
trie.insert("app");
trie.search("app");     // 返回 True
 

提示:

1 <= word.length, prefix.length <= 2000
word 和 prefix 仅由小写英文字母组成
insert、search 和 startsWith 调用次数 总计 不超过 3 * 104 次

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/implement-trie-prefix-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

分析:

        这道题并不会写,甚至连题目都看不懂,最后无奈之下看了题解。

        这道题,本质上是一个26叉树,每个节点伸出来26个分枝,每个分支从1-26分别对应字母a~z,并且节点上还有一个标志位isend,代表该节点是否为某个插入单词的结束点。当插入第一个字符串“word”时,首先需要存放‘w’,我们令当前节点的第23个分支(字母w对应的那个)指向一个新节点(节点指向不为空,意味着该分支对应的字母存在),移动到新节点上。接下来要插入字符串“ord”,则找到o对应的分支,指向一个新节点。。。直到字母“d”也插入完毕。当字母d插入完毕时,在插入字母d时新建的节点上,令其isend为true,代表该节点时某个插入字符串的结尾。

        查找则是沿着根节点开始,查找字符串的第一个字母,查看对应的分枝是否有节点,如果没有,则说明不存在,返回false;如果有,则继续查找下一个字母,直至查找完毕。并且在查找完毕时判断该节点标志位isend是否为true,如果不是,说明该字符串没有被插入(能查找到只是因为该字符串是某个插入字符串的子串),返回false;如果isend为true,则说明该查找字符串曾经被插入过,返回true

        查找子串跟上面流程差不多,只是不用再判断isend标志位了。

详细的分析请看题解:

https://leetcode-cn.com/problems/implement-trie-prefix-tree/solution/trie-tree-de-shi-xian-gua-he-chu-xue-zhe-by-huwt/

代码如下:

class Trie {
public:
    // isend代表该节点是否为某个单词的结束点
    bool isend;
    // 26叉树,分别指向a,b,c。。。。x,y,z
    Trie * next[27];
    Trie() {
        // 初始化isend为false
        this->isend=false;
        // 初始化next为NULL
        memset(this->next,NULL,sizeof(this->next));
    }
    
    void insert(string word) {
        
        // 获取当前节点
        Trie *node=this;
        for(int i=0;i<word.size();i++)
        {
            // 计算word[i]在字母表中的位置,a=1,b=2...z=26
            int index=word[i]-'a'+1;
            // 判断是否需要新建节点
            if(node->next[index]==NULL)
                node->next[index]=new Trie();
            // 移动到下一个节点
            node=node->next[index];
        }
        // 插入完毕,该节点是某个插入字符串的结尾
        node->isend=true;
    }
    
    bool search(string word) {
        // 获取当前节点
        Trie *node=this;
        for(int i=0;i<word.size();i++)
        {
            int index=word[i]-'a'+1;
            // 如果下个节点不为空,则继续查找
            if(node->next[index]!=NULL)
                node=node->next[index];
            // 下个节点为空,则说明该字符串没有被插入
            else
                return false;
        }
        // 判断查找结束后的节点是否为某个插入字符串的结尾
        if(node->isend==true)
            return true;
        else
            return false;
    }
    
    bool startsWith(string prefix) {
        // 获取当前节点
        Trie *node=this;
        for(int i=0;i<prefix.size();i++)
        {
            int index=prefix[i]-'a'+1;
            // 如果下个节点不为空,则继续查找
            if(node->next[index]!=NULL)
                node=node->next[index];
            // 下个节点为空,则说明该前缀不存在
            else
                return false;
        }
        return true;
    }
};

/**
 * Your Trie object will be instantiated and called as such:
 * Trie* obj = new Trie();
 * obj->insert(word);
 * bool param_2 = obj->search(word);
 * bool param_3 = obj->startsWith(prefix);
 */

于我而言,这道题让我学会了很多知识

        1.c++中的this

        2.构造函数中的this及初始化

        3.声明类数组 

        4.c++实例变量

        5.类方法中的递归

以上感悟请看另一篇文章:

https://blog.csdn.net/weixin_43098069/article/details/123686292

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值