字典树的相关介绍可以参见:http://blog.csdn.net/wsyw126/article/details/61416055
大致来说,每个节点都是一个字符集中的字符,根节点为空,从根节点根据父子联系到某个子节点可以代表一个字符串,前缀相同的字符串共用一段路径。每一个节点包含多个指向孩子的指针和这个节点对应的单词是否是单词的标记或者单词出现的次数。
Trie树的基本性质可以归纳为:
- 根节点不包含字符,除根节点意外每个节点只包含一个字符。
- 从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。
- 每个节点的所有子节点包含的字符串不相同。
Trie树有一些特性:
- 根节点不包含字符,除根节点外每一个节点都只包含一个字符。
- 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
- 每个节点的所有子节点包含的字符都不相同。
- 如果字符的种数为n,则每个结点的出度为n,这也是空间换时间的体现,浪费了很多的空间。
- 插入查找的复杂度为O(n),n为字符串长度。
leetcode上构建一个Trie的算法题和简单实现:
Implement a trie with insert, search, and startsWith methods.
Note:
You may assume that all inputs are consist of lowercase letters a-z.
class TrieNode {
public boolean isWord;
public TrieNode[] children = new TrieNode[26];
public TrieNode() {}
}
public class Trie {
private TrieNode root;
public Trie() {
root = new TrieNode();
}
public void insert(String word) {
TrieNode ws = root;
for(int i = 0; i < word.length(); i++){
char c = word.charAt(i);
if(ws.children[c - 'a'] == null){
ws.children[c - 'a'] = new TrieNode();
}
ws = ws.children[c - 'a'];
}
ws.isWord = true;
}
public boolean search(String word) {
TrieNode ws = root;
for(int i = 0; i < word.length(); i++){
char c = word.charAt(i);
if(ws.children[c - 'a'] == null) return false;
ws = ws.children[c - 'a'];
}
return ws.isWord;
}
//是否有单词是以prefix为前缀的。只需要看是否有prefix节点即可,因为
//如果有prefix对应的节点,说明肯定插入了前缀为prefix的单词。
public boolean startsWith(String prefix) {
TrieNode ws = root;
for(int i = 0; i < prefix.length(); i++){
char c = prefix.charAt(i);
if(ws.children[c - 'a'] == null) return false;
ws = ws.children[c - 'a'];
}
return true;
}
}