内容简介:1.本文原文来自于leetcode上的算法题Implement Trie的解决方案.2.原文地址3.新手献丑了,希望大家轻拍~(微笑)
1.本文原文来自于leetcode上的算法题Implement Trie的解决方案.
2.原文地址
3.新手献丑了,希望大家轻拍~(微笑)
二、原文在这
1.问题描述
算法题:
通过编写插入、查询、判断开头等方法完成一个trie树。
例子:
Trie trie = new Trie(); trie.insert("apple"); trie.search("apple"); // returns true trie.search("app"); // returns false trie.startsWith("app"); // returns true trie.insert("app"); 复制代码
提示:
- 你可以假设所有的输入都是由小写字母a-z组成的。
- 所有的输入string数组都不为空。
总结:
这篇文章是写给中等水平的读者的,将会介绍数据结构trie(前缀树)和其中的常见操作。
2.解决方法:
2.1应用:
trie(前缀树)是一种树形数据结构,常常用来在字符串的数据集中检索一个关键词。目前,trie数据结构已经被高效地应用在了很多领域:
(1)自动填充
(2)拼写检查
(3)IP路由(最长的路由匹配)
(4)九键输入法的预测文字
(5)完成文字游戏
有很多其他的数据结构如,平衡树,hash表都能够在一个string的数据集中查找单词,但是我们为什么要使用trie呢?虽然hash表对于找到一个关键词(key)只需要 O(1)的时间复杂度,但是在下列操作中,它就表现得不是很高效了。
- 找到拥有共同前缀的所有关键词(key)。
- 根据字典序枚举所有字符串
trie优于hash表的另外一个原因是,但hash表的数据规模扩大后,将会出现很多的hash碰撞,因此查询时间复杂度将会提高到 O (n), n 是插入的关键词的个数。而相比于hash表,trie在存储很多具有共同前缀的关键词时需要的空间更少。在这个例子里trie只需要 O (m)的时间复杂度( m 是关键词的长度)。而在平衡树里查询一个关键词,则需要花费 O ( m log n )
2.2 trie节点结构
trie是一个有根树,它的节点有以下几个字段:
- 与子节点间最多有R个连接,每个连接对应到R个字母中的一个。这个R个字母来自于字母表。在这篇文章中,我们假设R是26,即26个小写的拉丁字母。
- 一个布尔值isEnd,说明该布尔值说明当前节点是否是一个关键词的结尾,否则就只是该关键词的前缀。
java编写的trie节点
class TrieNode { // R links to node children private TrieNode[] links; private final int R = 26; private boolean isEnd; public TrieNode() { links = new TrieNode[R]; } public boolean containsKey(char ch) { return links[ch -'a'] != null; } public TrieNode get(char ch) { return links[ch -'a']; } public void put(char ch, TrieNode node) { links[ch -'a'] = node; } public void setEnd() { isEnd = true; } public boolean isEnd() { return isEnd; } } 复制代码
2.3 trie中最常见的操作——添加和查询关键词
(1)添加关键词到trie中
我们通过遍历trie来插入关键词。我们从根节点开始,搜寻和关键词第一个字母对应的连接,这里一般有两种情况:
- 如果连接存在,那么我们就顺着这个连接往下移到下一子层,接着搜寻关键词的下一个字母对应的连接。
- 如果连接不存在,那么我们就新建一个trie节点,对应着现在的关键词字母,建立与父节点的连接。
我们重复这个步骤,直到处理完关键词的最后一个字母,然后标记最后的节点为结束节点。算法结束。
java编写的插入方法
class Trie { private TrieNode root; public Trie() { root = new TrieNode(); } // Inserts a word into the trie. public void insert(String word) { TrieNode node = root; for (int i = 0; i < word.length(); i++) { char currentChar = word.charAt(i); if (!node.containsKey(currentChar)) { node.put(currentChar, new TrieNode()); } node = node.get(currentChar); } node.setEnd(); } } 复制代码
复杂度分析:
- 时间复杂度 O (m), m 是关键词的长度。在算法的每一次循环中,我们要么检查节点要么新建一个节点,直到该关键词的最后一个字母。所以,这只需要进行m次操作。
- 空间复杂度O(m)。最糟糕的情况是,新插入的关键词和已经存在trie的关键词没有共同的前缀,因此我们必须插入m个新的节点,因此需要O(m)空间复杂度。
(2)在trie中搜索关键词
每一个关键词在trie中都可以被一条从根节点到子节点的路径所表示。我们将根据关键词的第一个字母从根节点开始搜索,然后检查节点上的每一个连接对应的字母,一般有两种情况:
- 存在对应关键词字母的连接,我们将从该连接移动到下一个节点,然后搜索关键词的下一个字母对应的连接。
- 对应的连接不存在,如果此时已经遍历到了关键词的最后一个字母,则把当前的节点标记为结束节点,然后返回true。当然还有另外两种情况,我们会返回false:
- 关键词的字母没有遍历完,但没有办法接着在trie中找到根据关键词字母的形成的路径,所以trie中不存在该关键词。
- 关键词的字母的已经遍历完了,但当前的节点不是结束节点,因此搜索的关键词只是trie中的某一个关键字的前缀。
java编写搜索关键词的方法
class Trie { ... // search a prefix or whole key in trie and // returns the node where search ends private TrieNode searchPrefix(String word) { TrieNode node = root; for (int i = 0; i < word.length(); i++) { char curLetter = word.charAt(i); if (node.containsKey(curLetter)) { node = node.get(curLetter); } else { return null; } } return node; } // Returns if the word is in the trie. public boolean search(String word) { TrieNode node = searchPrefix(word); return node != null && node.isEnd(); } } 复制代码
复杂度分析:
- 时间复杂度:O(m)。在算法的每一步都是搜索关键词的下一个字母,因此在最差的情况下,算法需要执行m步。
- 空间复杂度:O(1)。
(3)在trie中搜索关键词的前缀
这个方法和我们在trie中用来搜索关键词的方法很类似。我们从根节点开始移动,直到关键词前缀的每个字母都被搜索到了,或者,没有办法在trie中根据关键词的当前字母找到接下去的路径。这个方法和前面提到的搜索关键词的唯一不同在于,当我们遍历到关键词前缀的最后一个字母时,我们总是返回true,我们不需要考虑当前的节点是否有结束标志,因为我们只是搜索关键词的前缀,而不是整个关键词。
java编写的搜索关键词前缀的方法
class Trie { ... // Returns if there is any word in the trie // that starts with the given prefix. public boolean startsWith(String prefix) { TrieNode node = searchPrefix(prefix); return node != null; } } 复制代码
复杂度分析:
- 时间复杂度:O(m)
- 空间复杂度:O(1)
3. 应用问题
这里有一些非常合适应大家去练习的问题,这些问题都能用trie数据结构解决。
- 添加和搜索单词(数据结构设计) ——一个非常直接的trie的应用。
- 搜索单词2——和boggle这个游戏有点像
这篇分析出自@elmirap
以上所述就是小编给大家介绍的《数据结构——trie树介绍》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 数据结构 – 用于构建文件系统的数据结构?
- 荐 用Python解决数据结构与算法问题(三):线性数据结构之栈
- 数据结构和算法面试题系列-C指针、数组和结构体
- 请问二叉树等数据结构的物理存储结构是怎样的?
- 数据结构——单链表
- 常用数据结构
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。