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树
因为我不喜欢用指针,所以我说的所有内容都不包含指针
大概论述一下过程:
- 选定要加入到Trie树中的字符串
- 从根节点开始依次判断当前结点的子节点中是否包含下一个字符
- 如果包含,则直接访问,重复第2步
- 否则,则建立这个结点,继续重复第2步
- 若进行第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树的模板题)
如果文章中有问题,欢迎在评论中告诉我,谢谢。