前缀树(字典树)应用——实现 Trie (前缀树)、添加与搜索单词

本文介绍了前缀树(字典树)的概念和工作原理,详细阐述了如何使用前缀树实现字符串的插入、搜索和前缀检查功能。通过示例代码解析了在C++中构建前缀树的数据结构,并讨论了前缀树的时间复杂度和内存使用情况,突出了其空间换时间的特点。
摘要由CSDN通过智能技术生成

目录

1 前缀树原理简介

2 实现前缀树

2.1 题目描述

2.2 题目分析

2.3 代码实现

3 添加与搜索单词

3.1 题目描述

3.2 题目分析

3.3 代码实现

4 总结


1 前缀树原理简介

      先来简单介绍一下前缀树是什么。前缀树也叫字典树,常用语字符串的查找,为什么又叫前缀树呢?我们先来看看前缀树长什么样子:

                         

        如图所示,我们把"app"、“and”、“bad”以及“ban”放在树中,每个字符串都是从root开始的,然后根据第一个元素的不同分成了"a"开头与"b"开头两组,然后接着往下走,"a"开头的又分开了,而“b”开头的两个字符串还没有分开,再往下走,“b”开头的两个字符串也分开了。从整个树的结构可以看得出来,字符串两两之间的相同前缀部分是重合的,一旦分开就不会再组合了,因此在一组字符串中查找某一个字符串的时候可以避免很多不必要的查找。

        好了,简单介绍了前缀树之后,还有几点也必须考虑:既然前缀树也是树,那么每个结点的数据类型应当是什么呢?首先,根据前缀树的结构可以看出来,每个树的结点都是需要指向子结点的,那么子结点应该有几个呢?子结点的个数我们是无法确定的,就像图中的结点,有的结点有两个子结点,有的结点只有一个子结点,那该怎么办呢?

       实际上也很简单,如果前缀树中只可能出现多少种结点情况那就定义多少个子结点!比如说这里如果前缀树中的都是小写字母的话,那就直接定义26个子结点就好了。有了子结点,那每个结点需不需要再定义一个value来存放到底是'a'还是'b'呢?实际上根本就不需要,因为既然前面定义了26个子结点,那么每个子结点就已经确定好了,无需再定义一个value。现在,有了子结点,查找的时候就可以顺着子结点往下搜索了,那我什么时候才叫搜索到什么时候结束呢?比如说我要查找“and”,那就应该到'd'结束,那我怎么知道结束了呢?将26个结点全部遍历一次全为空?如果这样的话,如果树中还包含数字之类的话显然效率就很低了,因此,我们直接再给每个结点定义一个末尾标记变量,如果这个结点是其所在的这条线的最后一个结点,那就标记为末尾,那又怎么去标记呢?我们下面就用例题来说了。先来看看每个结点的数据类型:

struct TrieNode{
    TrieNode* child[26]; //子结点
    bool endFlag; //末尾标记,是则true,否则false

    TrieNode():endFlag(false)
    {
        for(auto &c:child)c=NULL; //初始化末尾标记为false,每个子结点为NULL
    }
};

2 实现前缀树

2.1 题目描述

实现一个 Trie (前缀树),包含 insertsearch, 和 startsWith 这三个操作。

示例:

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

说明:

  • 你可以假设所有的输入都是由小写字母 a-z 构成的。
  • 保证所有输入均为非空字符串。

2.2 题目分析

       题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值