数据结构大都离不开数组和链表。他们是计算机中最基本的数据机构,基本全部的数据机构均可以有这两种数据机构来实现。java
而链表是一种特殊的树,树更是一种特殊的图。node
极客时间 数学专栏的做者的一段话,一直以为很受用:算法
其实计算机到了最后仍是搞数学,咱们要作的就是如何将问题应用到数学在到编程上去。编程
数学思想到编程的实现大都分为三步走数组
1.2.1 什么是字典树?数据结构
字典树也能够叫作前缀树,其实就是将不少单词组成的一种数据机构。一般都是树形结构的全部叫作字典树。ui
以下图所示:this
跟节点一般都是空,不一样的单词组成一条条的通路,造成了一个树状结构。编码
字典树有两种实现方式链表和数组。spa
由于字典树的二维关系是很是稀疏很是动态的,因此采用链表来实现字典树。
具体的代码注释以下:
static class TreeNode{
/** * 节点的数据void */
private char data;
/** * 子节点 */
private Map<Character,TreeNode> sons = null;
/** * 节点的解释 */
private String explanation = null;
/** * 节点的前缀字符串 */
private String prefix = null;
public TreeNode(char data, String explanation, String prefix) {
this.data = data;
this.sons = new HashMap<>(16);
this.explanation = explanation;
this.prefix = prefix;
}
}
复制代码
1.2.2 字典树的操做
字典树有两种
由于字典树的二维关系是很是稀疏很是动态的,
字典树的操做有两个
构建字典树(Dynamic)
public static void buildPrefixTree(String word){
if(StringUtils.isEmpty(word)) {
return;
}
TreeNode findNode = headNode;
String prefix = "";
String explanation = null;
for(int i=0;i<word.length();i++){
char c = word.charAt(i);
Map<Character, TreeNode> sons = findNode.sons;
if(sons.containsKey(c)){
findNode = sons.get(c);
}else{
if(i == word.length()-1){
explanation = prefix + c;
}
TreeNode sonNode = new TreeNode(c,explanation,prefix);
sons.put(c,sonNode);
findNode = sonNode;
}
prefix += c;
}
}
复制代码
查询字典
/** * 在PrefixTree中查找 单词 * @param word * @return */
public static TreeNode findWrod(String word){
if(StringUtils.isEmpty(word)) {
return null;
}
TreeNode findNode = headNode;
for(int i=0;i<word.length();i++){
char c = word.charAt(i);
Map<Character, TreeNode> sons = findNode.sons;
if( sons.size()!=0 && sons.containsKey(c)){
findNode = sons.get(c);
}else{
return null;
}
}
if(StringUtils.isEmpty(findNode.explanation)){
return null;
}
return findNode;
}
复制代码
遍历字典树中的全部单词
/** * 使用栈便利全部的单词 */
public static void dfsByStack(){
Stack<TreeNode> stack = new Stack<>();
stack.push(headNode);
while(stack.size()>0){
TreeNode node = stack.pop();
if(!StringUtils.isEmpty(node.explanation)){
System.out.println(node.explanation);
}
Map<Character, TreeNode> sons = node.sons;
sons.forEach((sonKey,sonValue)->{
stack.push(sonValue);
});
}
}
复制代码
字典树的这三种操做其实均可以用递归来实现,可是最后一种的效率是明显优于递归的,由于减小了大量的中间变量的建立,利用了栈模拟了递归调用。