引用:https://blog.csdn.net/qq_29996285/article/details/86674779?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
字典树是一种有序的,用于统计、排序和存储字符串的数据结构,他与二叉查找树不同,关键字不是直接保存在节点中,而是由节点在树中的位置决定,每个节点代表了一个字符,从第一层孩子节点到中间的某个标记的节点代表了存储的字符串。
一个节点的所有子孙都有相同的前缀,而根节点对应空字符串。
一般情况下,不是所有的节点都有对应的字符串,只有叶子节点和部分内部节点进行标记,才存储了字符串。
字典树的最大优点就是利用字符串的公共前缀来减少存储空间与查询时间,从而最大限度的减少无味的字符串比较。查找和插入字符串都可达到O(1)算法复杂度。
class TrieNode {
char val;
boolean isWord;//只有到叶子节点了才算一个word
TrieNode[] children = new TrieNode[26];//当前层最多有a-z 26个字符
TrieNode() {
}
TrieNode(char c) {
val = c;
isWord = false;
}
}
class Trie {
private TrieNode root;
Trie() {
root = new TrieNode();
}
public void insert(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
int index = word.charAt(i) - 'a';
if (node.children[index] == null) {
node.children[index] = new TrieNode(word.charAt(i));
}
node = node.children[index];
}
node.isWord = true;
}
public boolean search(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
int index = word.charAt(i) - 'a';
if (node.children[index] == null) {
return false;
}
node = node.children[index];
}
return node.isWord;
}
public boolean startwith(String prefix) {
TrieNode node = root;
for (int i = 0; i < prefix.length(); i++) {
int index = prefix.charAt(i) - 'a';
if (node.children[index] == null) {
return false;
}
node = node.children[index];
}
return true;
}
}
验证一下:
public static void main(String[] args) {
Trie r = new Trie();
r.insert("apple");
boolean a = r.search("add");//false
a = r.search("apple");//true
a = r.startwith("app");//true
a = r.startwith("b");//false
}
实现先序遍历:
public static ArrayList<ArrayList<Character>> pre_order(TrieNode root) {
ArrayList<ArrayList<Character>> arrayLists = new ArrayList<>();
ArrayList<Character> arrayList = new ArrayList<>();
dfs(arrayLists, arrayList, root);
return arrayLists;
}
private static void dfs(ArrayList<ArrayList<Character>> arrayLists, ArrayList<Character> arrayList, TrieNode root) {
for (int i = 0; i < root.children.length; i++) {
if (root.children[i] != null) {
arrayList.add((char) (i + 'a'));
if (root.children[i].isWord) {
arrayLists.add(new ArrayList<>(arrayList));
}
dfs(arrayLists, arrayList, root.children[i]);
//回溯法恢复现场
arrayList.remove(arrayList.size() - 1);
}
}
}