如何根据二叉树的前序和中序遍历得到后序遍历
填空题:已知一棵二叉树前序遍历和中序遍历分别为ABDEGCFH和DBGEACHF,则该二叉树的后序遍历为_____________。
答案:DGEBHFCA。
解题过程:
一、基本概念扫盲:对一棵二叉树进行遍历,我们可以采取3中顺序进行遍历,分别是前序遍历、中序遍历和后序遍历。
前序遍历:根节点 -> 左节点 -> 右节点
中序遍历:左节点 -> 根节点 -> 右节点
后序遍历:左节点 -> 右节点 -> 根节点
我们可以发现,根节点是带头大哥,前序就是大哥打头阵,中序就是大哥居中指挥,后序就是大哥坐镇后方。
二、分析前序和中序的特点:
1、前序的第一个节点,必然是大哥;
2、大哥在中序必然居中,自然可以把中序拆分为左右两颗子树;
3、对左右子树重复上面过程,最终必然能把整颗二叉树还原出来。
三、对二叉树进行后序遍历。
四、理论讲完了,回归题目:
前序遍历:ABDEGCFH
中序遍历:DBGEACHF
1、从前序找到大哥:A,那么左子树为:DBGE,右子树:CHF
A
/ \
DBGE CHF
2、对左子树递归,从前序找到大哥:B,那么左子树的左子树是:D,左子树的右子树是:GE
A
/ \
B CHF
/ \
D GE
3、对左子树的左子树没必要递归了,就一个节点D,对左子树的右子树递归,从前序找到大哥:E,那么左子树的右子树的左子树是:G
A
/ \
B CHF
/ \
D E
/
G
4、左子树已经递归完,右子树依葫芦画瓢,最终还原出来的二叉树就是它:
A
/ \
B C
/ \ \
D E F
/ \
G H
5、对它做后序遍历:DGEBHFCA
好了,以上就是解题全过程。作为程序员,应该充分利用手头的工具来解题——计算机。所以我们需要进一步对该题建模,思考模型的算法。巧了,letCode的第105题就是这个题目,大家可以移步去力扣看题解。这里给出最简单的递归算法实现:
/**
* 二叉树构造,根据前序遍历、中序遍历,获取二叉树
* @author wulf
*/
public class BTree {
/**
* 构造二叉树
*
* @param preOrder 前序遍历数组
* @param inOrder 中序遍历数组
* @return
*/
public TreeNode buildTree(String[] preOrder, String[] inOrder) {
return buildTreeByRecursion(preOrder, 0, preOrder.length, inOrder, 0, inOrder.length);
}
/**
* 递归构造二叉树
*
* @param preOrder 前序遍历数组
* @param preOrderStart
* @param preOrderEnd
* @param inOrder 中序遍历数组
* @param inOrderStart
* @param inOrderEnd
*/
private TreeNode buildTreeByRecursion(String[] preOrder, int preOrderStart, int preOrderEnd,
String[] inOrder, int inOrderStart, int inOrderEnd) {
if (preOrderStart == preOrderEnd) {
return null;
}
// 根节点值
String rootValue = preOrder[preOrderStart];
// 构造根节点
TreeNode rootNode = new TreeNode(rootValue);
// 在中序遍历中找到根节点位置
int rootIndex = 0;
for (int i = inOrderStart; i < inOrderEnd; i++) {
if (inOrder[i].equals(rootValue)) {
rootIndex = i;
break;
}
}
int leftNum = rootIndex - inOrderStart;
// 递归的构造左子树
rootNode.left = buildTreeByRecursion(preOrder, preOrderStart + 1, preOrderStart + leftNum + 1,
inOrder, inOrderStart, rootIndex);
// 递归的构造右子树
rootNode.right = buildTreeByRecursion(preOrder, preOrderStart + leftNum + 1, preOrderEnd,
inOrder, rootIndex + 1, inOrderEnd);
return rootNode;
}
/**
* 后续遍历
*
* @param treeNode 二叉树对象
*/
private void postOrder(TreeNode treeNode) {
if (treeNode != null) {
postOrder(treeNode.left);
postOrder(treeNode.right);
System.out.print(treeNode.val + " ");
}
}
/**
* 测试
*
* @param args
*/
public static void main(String[] args) {
String[] preOrder = {"A", "B", "D", "E", "G", "C", "F", "H"};
String[] inOrder = {"D", "B", "G", "E", "A", "C", "H", "F"};
BTree bTree = new BTree();
TreeNode treeNode = bTree.buildTree(preOrder, inOrder);
System.out.println("二叉树:" + treeNode);
System.out.println("后续遍历:");
bTree.postOrder(treeNode);
}
/**
* 二叉树对象
*/
private class TreeNode {
String val; //节点数据
TreeNode left; //左节点
TreeNode right; //右节点
TreeNode() {
}
TreeNode(String val) {
this.val = val;
}
TreeNode(String val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(val);
sb.append(",");
sb.append(left);
sb.append(",");
sb.append(right);
return sb.toString();
}
}
}
运行结果:
二叉树:A,B,D,null,null,E,G,null,null,null,C,null,F,H,null,null,null
后续遍历:
D G E B H F C A
浙公网安备 33010602011771号