Trie树

Trie树即字典树
以下内容来自某度某科
***

在计算机科学中,trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。
在计算机科学中,trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。
Trie这个术语来自于retrieval。根据词源学,trie的发明者Edward Fredkin把它读作英语发音:/ˈtriː/ "tree"。[1][2]但是,其他作者把它读作英语发音:/ˈtraɪ/ "try"。[1][2][3]
在图示中,键标注在节点中,值标注在节点之下。每一个完整的英文单词对应一个特定的整数。Trie可以看作是一个确定有限状态自动机,尽管边上的符号一般是隐含在分支的顺序中的。
键不需要被显式地保存在节点中。图示中标注出完整的单词,只是为了演示trie的原理。
trie中的键通常是字符串,但也可以是其它的结构。trie的算法可以很容易地修改为处理其它结构的有序序列,比如一串数字或者形状的排列。比如,bitwise trie中的键是一串位元,可以用于表示整数或者内存地址。
***

关于Trie树是什么,我不会详细的解释(大家可以看一下其他大佬的Blog,不要在意我这个小蒟蒻说的)

我直接说Trie树的核心:如何建立Trie树

因为我不喜欢用指针,所以我说的所有内容都不包含指针

大概论述一下过程:

  1. 选定要加入到Trie树中的字符串
  2. 从根节点开始依次判断当前结点的子节点中是否包含下一个字符
  3. 如果包含,则直接访问,重复第2步
  4. 否则,则建立这个结点,继续重复第2步
  5. 若进行第2步时已经到达了最后一个字符,则直接结束

以上的内容全是凭着我自己的写法来说的,中间可能会存在错误。可以选择性的跳过上面的概述,直接看例子。
***
那么,我们来举个例子
假如,我要构建成字典树的单词是
her hen hers say said

最终构建完的字典树就长这样:

这里写图片描述




原谅我图画的丑

然而我们并不知道这些东西分别代表那些字符串
于是,我们对每个字符串的结尾所在的那个节点加个标记。

这里写图片描述

于是乎,我们从根节点开始,一层层依次遍历,当读入到一个加了标记的结点时,一路读到的字符连成的字符串便是原来需要储存的字符串

那么,至于怎么加入一个串呀。。。
我们也来演示一下吧、。。。(画图会画死我的)

比如当前这样子,其他的串都已经加入,我们现在需要加入字符串said

这里写图片描述

那么,我们从根节点开始

这里写图片描述

发现根节点的子节点里面存在s这个字符结点

把一个指针移动过去,继续找接下来的字符

这里写图片描述

接着,我们惊奇的发现a也存在了
于是继续遍历

这里写图片描述

这个时候,却发现当前结点不存在一个i结点
那么,我们就手动的造一个i结点出来

这里写图片描述

这个时候,发现有i结点了

于是继续访问下一层
这里写图片描述

发现这一层也没有d结点
于是我们再人工造一个出来
并且把它连上去

这里写图片描述

然后继续访问下一层。

这里写图片描述

还往下继续

诶~这个串没有了

OK
搞定
标记当前的d结点是一个单词的结束就好了

这里写图片描述


上面,我举了一个插入的例子

而如果要构建整棵Trie树的话,那么就从只有一个根节点开始,反复上面的过程即可。


画图真是画死我了
也没有啥东西会让你单独用一个字典树吧。。。
但是字典树是一个好东西。
到时候讲其他东西的时候是一定会讲到字典树的
到时候再说吧


接下来分析一下Trie树的代码

struct Node
{
       bool End;//是否是某个单词的结束
       int vis[MAX];//接下来的子节点的位置
}Trie[MAXNode};

上面是Trie树节点的构建
封装在了struct里面
其中MAX是字符的最大个数
MAXNode是啥意思就自己理解




接下来是构建一个Trie树

void Build(string s)//s是要放到Trie树里面的串
{
       int now=0;//当前位置
       int l=s.length();//字符串长度
       for(int i=0;i<len;++i)//依次遍历所有位置
       {
                if(!Trie[now].vis[s[i]])//不存在这个位置
                      Trie[now].vis[s[i]]=++cnt;//那就构建出这个节点
                now=Trie[now].vis[s[i]];//访问下一层
       }
}


好了
差不多了
(我尽然找不到Trie树的模板题)

如果文章中有问题,欢迎在评论中告诉我,谢谢。

posted @ 2017-07-17 16:53 小蒟蒻yyb 阅读(...) 评论(...) 编辑 收藏