树的基础和使用二叉树把后缀表达式转为中缀树
4.1 基础知识
4.1.1 树的定义
按照递归的方式定义树。一棵树是一些节点的集合。这些集合可以是空集。如果不是空集,则树由称为根() 的节点r以及0个或者多个非空的(子)树T1,T2,T3,…Tk组成,这些子树中每一棵的根都来自于根r的一条有向的边所连接。
每一棵子树的根叫做根r的儿子(child),而r是每一棵子树的根的父亲(parent)。
一棵树是N个节点和N-1条边的集合,其中的一个节点叫做根(除了根节点之外每个节点都有且仅有一个父亲,也即是有且仅有一条边),每个节点可以有任意多个儿子,没有儿子的节点称为树叶(leaf),具有相同父亲的节点称为兄弟(siblings),类似还有祖父和孙子关系
从节点n1-nk的路径(path) 定义为节点n1 n2 n3 … nk 的一个序列,使得对于1<=i<k节点ni是ni+1的父亲,这条路径的长是为该路径上的边的条数,即k-1,每个节点到自己都有一条长为0的路径,在一棵树中从根到每个节点恰好存在一条路径。
对于任意节点ni,ni的 深度(depth) 为从根到ni的唯一路径的长。因此根的深度为0。ni的高(height) 是从ni到一片树叶的最长路径的长,因此,所有树叶的高都为0.一棵树的高等于他根的高,一棵树的深度等于他最深的树叶的深度;该深度总是等于这棵树的高。如果存在n1到n2的一条路径,那么n1是n2的一位祖先 (ancestor)
。如果n1!=n2,那么n1是n2的真祖先,n2是n1的真后裔(proper descendant) 。
/*树的表示*/
private class TreeNode{
public Object object;
public TreeNode firstNode;
public TreeNode nextSibling;
public TreeNode() {
}
}
4.1.2 树的遍历
三种遍历策略
-
先序遍历:先对节点的处理再对节点儿子处理
-
后序遍历:先对节点儿子处理再处理节点
-
中序遍历:左儿子-节点-右儿子方式,适用于二叉树
三种方式对应着前缀表达式,中缀表达式和后缀表达式
4.2 二叉树
二叉树(binary tree)是一棵树,其中每个节点都不能有多于两个的儿子,二叉树的一个性质是一棵二叉树的平均深度要比节点数N小得多,二叉树的平均深度是O(N^0.5),对二叉查找树(binary search tree),其深度的平均值是O(log(N))
4.2.1 二叉树的实现
class BinaryNode{
Object element;
BinaryNode left;
BinaryNode right;
}
4.2.2 后缀表达式转为表达式树(中缀)
思路:我们一个一个的把符号读入表达式,如果符号是运算符,那么弹出两个操作数,创建一个新的Tree,然后再压栈,否则,直接把操作数放到栈里面
class BinaryNode<T>{
T element;
BinaryNode left;
BinaryNode right;
}
@Test
public void test(){
String postFixString="ab+cde+**";
buildInfixTree(postFixString);
}
public BinaryNode<String> buildInfixTree(String postFixString){
BinaryNode<String> root=new BinaryNode<>();
Stack<BinaryNode<String>> stack=new Stack<>();
for(int i=0;i<postFixString.length();i++){
String c=String.valueOf(postFixString.charAt(i));
if(check(c)){//检测到运算符,弹出两个操作数
BinaryNode<String> node1=new BinaryNode<>();//例如压入ab,那么弹出ba,node1是b,node2是a
BinaryNode<String> node2=new BinaryNode<>();
node1=stack.pop();
node2=stack.pop();
BinaryNode<String> sNode=new BinaryNode<>();
sNode.element=c;
sNode.left=node2;
sNode.right=node1;
stack.push(sNode);
}else {
BinaryNode<String> node=new BinaryNode<>();
node.element=c;
stack.push(node);
}
}
return stack.peek();
}
/**
* 检查是不是运算符
* @param c
* @return
*/
public boolean check(String c){
if(c.equals("+")||c.equals("-")||c.equals("*")||c.equals("/")){
return true;
}
return false;
}