字典树: 单词的查找树,也就是26叉树,部分结构如下:
程序代码:
class TrieNode {
char value;// 当前结点存储的字符
int num;// 有多少个单词经过了这个字符,从本字符到根就是这num个单词的前缀
boolean isword;// 是否构成一个完整的单词,true为是
TrieNode[] son;// 所有孩子存放在一个对象数组里,默认是26叉
public TrieNode() {
num = 1;// 至少有一个字符经过本字符
isword = false;// 开始假定是false
son = new TrieNode[26];// 本案例只考虑单词的26个字母
}
}
public class TrieTree {
TrieNode root;// 字典树的根
public TrieTree() {
root = new TrieNode();// 初始化根结点
}
// 建树的过程就是不断地往字典树里插入单词
public void insertTrieTree(String s) {
if (s == null || s.length() == 0)
return;// 空串的处理
TrieNode node = root;// 先获取到根,因为插入的时候要一个一个字符处理,node会变的
char[] words = s.toCharArray();// 得到字符数组
for (int i = 0; i < words.length; i++) {
int distance = words[i] - 'a';// 计算当前字符是当前根的第多少个孩子
if (node.son[distance] == null) {
node.son[distance] = new TrieNode();
node.son[distance].value = words[i];// 存入当前字符
} else {
node.son[distance].num++;// 经过当前字符的次数+1
}
node = node.son[distance];
}
node.isword = true;// 最后一个字符都存储完毕后,这个字符一定是单词的完整的结尾
}
// 给定单词,查找其是否在字典树里
public boolean isContains(String s) {
if (s == null || s.length() == 0)
return false;// 空串的处理
TrieNode node = root;// 先获取到根,因为插入的时候要一个一个字符处理,node会变的
char[] words = s.toCharArray();// 得到字符数组
for (int i = 0; i < words.length; i++) {
int distance = words[i] - 'a';// 计算当前字符是当前根的第多少个孩子
if (node.son[distance] != null) {
node = node.son[distance];// 继续往下找
} else {
return false;
}
}
return node.isword;
}
// 给定前缀返回有多少个单词以它作为前缀
public int getPreFixNum(String prefix) {
if (prefix == null || prefix.length() == 0)
return 0;// 空串的处理
TrieNode node = root;// 先获取到根,因为插入的时候要一个一个字符处理,node会变的
char[] words = prefix.toCharArray();// 得到字符数组
for (int i = 0; i < words.length; i++) {
int distance = words[i] - 'a';// 计算当前字符是当前根的第多少个孩子
if (node.son[distance] != null) {
node = node.son[distance];// 继续往下找
} else {
return 0;
}
}
return node.num;
}
public static void main(String[] args) {
TrieTree tree = new TrieTree();
String[] strs = { "banana", "band", "bee", "absolute", "acm", "acmer" };
String[] prefix = { "ba", "b", "band", "abc", "acm" };
for (String str : strs) {
tree.insertTrieTree(str);
}
System.out.print("字典树中是否包含abc:");
System.out.println(tree.isContains("abc"));
System.out.print("字典树中是否包含acm:");
System.out.println(tree.isContains("acm"));
for (String str : prefix) {
System.out.printf("%s的前缀为:%d\n", str, tree.getPreFixNum(str));
}
}
}
运行结果:
字典树中是否包含abc:false
字典树中是否包含acm:true
ba的前缀为:2
b的前缀为:3
band的前缀为:1
abc的前缀为:0
acm的前缀为:2