树的三种遍历方式的遍历顺序:
先序遍历:根、左子树、右子树(特点:第一个元素为根)
中序遍历:左子树、根、右子树(特点:根的两边分别为左子树和右子树)
后序遍历:左子树、右子树、根(特点:最后一个元素为根)
有如下图的二叉树:
其先序、中序、后序遍历分别为:DBACEGF、ABCDEFG、ACBFGED。
1、已知先序和中序求后序
先序遍历的第一个字符为根,因此只需在中序遍历中找到它,就可以把根节点的左子树和右子树分开,就可以知道左子树的字符个数和右子树的字符个数,然后可以确定先序遍历中哪部分是左子树,哪部分是右子树,之后递归先序遍历的序列,直到结束。
如上面的例子:先序遍历的第一个字符是D,则根节点为D,从中序遍历中可以找到D的位置,左边的ABC即为左子树的字符,右边的EFG即为右子树的字符,如果开始递归函数为:build(“DBACEGF”),则找到根的位置后,可以分为递归左子树的先序遍历和递归右子树的先序遍历:build(“BAC”)和build(“EFG”),其对应的中序遍历为:ABC和EFG。然后继续进行以上步骤,直到找完先序序列。每找到根就可以直接输出或保存到数组中,需要注意的是递归的时候不要把根包含在内。
代码如下(已知先序和中序求后序):
//前 中序构造树
public static Node tree(int[] zx, int[] hx, int l1,int r1, int l2,int r2) {
if (l1>r1) return null;
int i;
Node root = new Node();
for (i = l1;!(zx[i]==hx[l2]); i++); //找到根节点
root.data=hx[l2];
int cnt = i-l1; //求出左子树个数
root.L=tree(zx,hx, l1, i-1, l2+1, l2+cnt); //左子树
root.R=tree(zx,hx, i+1, r1, l2+cnt+1, r2); //右子树
return root;
}
//中后序
root.L=tree(zx,hx, l1, i-1, l2, l2+cnt-1); //左子树
root.R=tree(zx,hx, i+1, r1, l2+cnt, r2-1); //右子树
图解
大家看到没,其实两个代码差不多,前面都是一样的,因为后序的根在后面,前序的根在前面,前面后面的不同