1.本文原文来自于leetcode上的算法题Implement Trie的解决方案.
2.原文地址
3.新手献丑了,但愿你们轻拍~(微笑)java
算法题:
经过编写插入、查询、判断开头等方法完成一个trie树。node
例子:算法
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");
复制代码
提示:数组
总结:
这篇文章是写给中等水平的读者的,将会介绍数据结构trie(前缀树)和其中的常见操做。数据结构
2.1应用:
trie(前缀树)是一种树形数据结构,经常用来在字符串的数据集中检索一个关键词。目前,trie数据结构已经被高效地应用在了不少领域:
(1)自动填充
app
trie优于hash表的另一个缘由是,但hash表的数据规模扩大后,将会出现不少的hash碰撞,所以查询时间复杂度将会提升到O (n),n 是插入的关键词的个数。而相比于hash表,trie在存储不少具备共同前缀的关键词时须要的空间更少。在这个例子里trie只须要O (m)的时间复杂度(m 是关键词的长度)。而在平衡树里查询一个关键词,则须要花费O (m logn)
2.2 trie节点结构
trie是一个有根树,它的节点有如下几个字段:spa
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来插入关键词。咱们从根节点开始,搜寻和关键词第一个字母对应的链接,这里通常有两种状况:设计
咱们重复这个步骤,直处处理完关键词的最后一个字母,而后标记最后的节点为结束节点。算法结束。 code
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();
}
}
复制代码
复杂度分析:cdn
(2)在trie中搜索关键词
每个关键词在trie中均可以被一条从根节点到子节点的路径所表示。咱们将根据关键词的第一个字母从根节点开始搜索,而后检查节点上的每个链接对应的字母,通常有两种状况:
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();
}
}
复制代码
复杂度分析:
(3)在trie中搜索关键词的前缀
这个方法和咱们在trie中用来搜索关键词的方法很相似。咱们从根节点开始移动,直到关键词前缀的每一个字母都被搜索到了,或者,没有办法在trie中根据关键词的当前字母找到接下去的路径。这个方法和前面提到的搜索关键词的惟一不一样在于,当咱们遍历到关键词前缀的最后一个字母时,咱们老是返回true,咱们不须要考虑当前的节点是否有结束标志,由于咱们只是搜索关键词的前缀,而不是整个关键词。
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;
}
}
复制代码
复杂度分析:
3. 应用问题
这里有一些很是合适应你们去练习的问题,这些问题都能用trie数据结构解决。
这篇分析出自@elmirap