添加和查找单词-力扣

数据结构:字典树
1 前缀树原理简介
先来简单介绍一下前缀树是什么。前缀树也叫字典树,常用语字符串的查找,为什么又叫前缀树呢?我们先来看看前缀树长什么样子:
添加和查找单词-力扣_第1张图片

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

    如图所示,我们把”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
}
};

图中的搜索方法,深度优先搜索
深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法。它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节点,然后从另一条路开始走到底,这种尽量往深处走的概念即是深度优先的概念。
基本思想:

  (1)访问顶点v;

  (2)从v的未被访问的邻接点中选取一个顶点w,从w出发进行深度优先遍历;

   (3)重复上述两步,直至图中所有和v有路径相通的顶点都被访问到。

算法复杂度:

若有v个顶点、E条边,则

用邻接表储存图,有O(V+E)

用邻接矩阵储存图,有O(V^2)

伪代码:

递归实现:

         (1)访问顶点v;visited[v]=1;//算法执行前visited[n]=0

         (2)w=顶点v的第一个邻接点;

         (3)while(w存在)

           if(w未被访问)

           从顶点w出发递归执行该算法;

           w=顶点v的下一个邻接点;

复制代码
//布尔型数组Visited[]初始化成false
void DFS(Vetex v)
{
Visited[v] = true;
for each w adjacent to v
if (!Visited[w])
DFS(w);
}
复制代码
更加详细过程:
https://www.cnblogs.com/DWVictor/p/10048554.html

你可能感兴趣的:(数据结构)