字典树(trie)/前缀树(PrefixTree)实例讲解

对于字典树/前缀树可能大部分情况很难直观或者有接触的体验,尤其是对前缀这个玩意没啥概念,可能做题遇到前缀问题也是使用暴力匹配蒙混过关,如果字符串比较少使用哈希表等结构可能也能蒙混过关,但如果字符串比较长、相同前缀较多那么使用字典树可以大大减少内存的使用和效率。

一个字典树的应用场景:在搜索框输入部分单词下面会有一些神关联的搜索内容,你有时候都很神奇是怎么做到的,这其实就是字典树的一个思想。

一、字典树trie树

Trie树,又叫字典树、前缀树(PrefixTree)、单词查找树,是一种多叉树结构。

二、trie树的作用

(1)核心应用

1.字符串检索;

2.词频统计;

3.字符串排序;

4.前缀匹配。

(2)trie树节点

每个字母都占用一个trie树节点,根节点与子节点没有本质的区别,主要有这几个属性:

1.root:是否为根节点

2.dict:装子节点的hash表

3.flag:是否为一个单词的结尾

4.value:该单词的完整内容(只有在flag为True时才有)

5.count:该单词出现的次数(只有在flag为True时才有)

6.list:是一个字典,用于遍历储存东西的(只有root节点才有)

classTrie(object):def__init__(self,root=None,flag=False,count=None,value=None):self.root=root#root节点用于装内容self.count=count#count用于计数,可以统计词频self.dict={}#dict用于装子节点,子节点还是trie树self.flag=flag#flag用于判断是否结束self.value=value#value就表示这个单词是什么self.list={}(3)常规操作

先来实现最基础的四个操作:

1.insert:增,注意最后一个字母的判断以及处理即可

2.search:查

3.delete:删

4.startsWith:判断前缀是否存在

①增

definsert(self,word):""":typeword:str:rtype:None"""trie=selfforj,iinenumerate(word):#如果是不是最后一个字母就遍历(或添加)ifj!=len(word)-1:ifinotintrie.dict:trie.dict[i]=Trie(root=i)trie=trie.dict[i]else:#是最后一个字母且flag为true就加计数ifiintrie.dictandtrie.dict[i].flag:trie=trie.dict[i]trie.count+=1#是最后一个字母但flag为false就修改flag将计数改为1elifiintrie.dictandnottrie.dict[i].flag:trie=trie.dict[i]trie.flag=Truetrie.count=1trie.value=word#如果trie.dict中没有就新增else:trie.dict[i]=Trie(root=i,flag=True,count=1,value=word)②查

defsearch(self,word):""":typeword:str:rtype:bool"""trie=selfforiinword:ifiintrie.dict:trie=trie.dict[i]else:returnFalsereturntrie.flag③删

defstartsWith(self,prefix):""":typeprefix:str:rtype:bool"""trie=selfforiinprefix:ifiintrie.dict:trie=trie.dict[i]else:returnFalsereturnTrue(4)遍历操作

遍历操作就首选DFS深度优先搜索,参数中加入prefix的目的是为了后面的联想操作,如果只做遍历可以不加;值得一提的是,我对子节点的储存采用的是字典的形式,遍历出来的结果排序刚刚好就是字典序,也就实现了前面说的字符串字典序的处理(其实真要排字典序,直接sorted就好了,没必要用trie树)

def__iter__(self):self.list={}#重置self.listself.dfs([],self)returniter(self.list)(5)联想操作

联想业务应该是这样的:用户输入前几个字母,然后匹配出完整的单词,使用频率越高的单词理应放在最前面;

所以整体思路是这样的:根据前缀找到前缀最后一个字母所在的trie树节点,从那个节点开始进行DFS遍历,然后在遍历结果前加上一个前缀,最后将结果按照count进行排序最后以列表形式输出结果;

先实现排序算法,这里用的是快速排序,注意比较的值是count,最后留下的是单词;

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

THE END
1.字典树算法(C/C++)字典树算法(C/C++) 本文介绍了字典树(Trie)算法,一种用于高效存储和检索字符串的数据结构。文章详细阐述了字典树的基本概念,包括插入、查询操作,并提供了一个C++实现示例。此外,文章还讨论了在删除和修改操作上的挑战,并给出了一种可能的解决方案。最后,通过一个例题展示了字典树在解决字符串查找问题中的应用。https://blog.csdn.net/gaoqiandr/article/details/131033556
2.算法学习:字典树算法学习:字典树 一、概念 字典树,即 Trie 树,又称单词查找树或键树,是一种树形结构。 典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。 优点:最大限度地减少无谓的字符串比较,查询效率比哈希表高。https://www.jianshu.com/p/724b805999bb
3.Trie树(字典树或者前缀树)算法详解算法简介 Trie树,即字典树,也有的称为前缀树,是一种树形结构。广泛应用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是最大限度地减少无谓的字符串比较,查询效率比较高。 Trie的核心思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的https://leetcode.cn/circle/discuss/mv8GnX/
4.《Java数据结构与算法》第7章:字典树腾讯云开发者社区字典树 Trie 这个词来自于 retrieval,于 1912 年,Axel Thue 首次抽象地描述了一组字符串数据结构的存放方式为 Trie 的想法。这个想法于 1960 年由 Edward Fredkin 独立描述,并创造了 Trie 一词。你看看,多少程序员为了一个词、方法名、属性名,想破脑袋!https://cloud.tencent.com/developer/article/2191777
5.字典树&01字典树算法笔记51CTO博客字典树&01字典树算法笔记 1】学习了字典树之后,觉得它很明显的就是用空间来换时间,空间复杂度特别大,比如字典数单单存26个小写字母,那么每个节点的孩子节点都有26个孩子节点,字典树中的每一层都保留着不同单词的相同字母。 2】01字典树主要用于解决求异或最值的问题https://blog.51cto.com/u_15067244/3900256
6.python算法图解提要文摘附注:本书系统论述了Python编程的理论与方法,全书共分11章,包括数据结构的分类和基本运算、递归、栈和队列、链表、数组、树结构、堆结构、散列表、字典树、图和排序算法。 预约委托 49 浏览 纸本馆藏(1) 收起 索书号 条码号 馆藏地/书架号 书刊状态 导航 TP311.561/H32D A0460959 总馆- C-2https://oleopac.lib.sztu.edu.cn/space/searchDetailLocal/m17da2133e62cbd9111a4fe6337e49fd0
7.一文搞懂字典树!字典树,是一种空间换时间的数据结构,又称Trie树、前缀树,是一种树形结构(字典树是一种数据结构),典型用于统计、排序、和保存大量字符串。所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。 https://zhuanlan.zhihu.com/p/420663173
8.Trie树(字典树)的介绍及Java实现javaTrie树,又称字典树或前缀树,关于它的结构就不详细介绍了。Trie树在单词统计、前缀匹配等很多方面有很大用处。下面这篇文章主要介绍了Trie树,以及Java实现如何Trie树,有需要的朋友可以参考借鉴,下面来一起看看吧。简介Trie树,又称为前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找https://www.jb51.net/article/104543.htm
9.字典树(trietree)专注于c++字典树(trie tree) 今天AC了两题trie tree的题目,感觉trie的性质真的是相当的好,而且实现比较简单。它使在字符串集合中查找某个字符串的操作的复杂度降到最大只需O(n),其中n为字符串的长度。trie是典型的将时间置换为空间的算法,好在ACM中一般对空间的要求很宽松。http://www.cppblog.com/bellgrade/archive/2009/10/08/98097.html