最近笔试题一直遇到这个题,今天就总结一下。本文主要回答以下几个问题(Java实现):
先看以下3种遍历的特点:
特点:
根据上面的特点,可以解决问题(核心都是中序的结构特点:可以明确区分出左子树右子树的位置):
前+中=>后+层:
后+中=>前+层:(类似上面的方法,就是后序的根节点在尾部,相应的左子树/右子树的根节点B/C在尾部,见上图所示。)
具体解决办法:
实现:
public class PreOrderAndInOrder {
/**
*
* @param pre_bg_index 前序数组中,开始的索引(具体到左(右)子树中,数组开始索引+长度len精确指定了某一个左(右)子树)
* @param in_bg_index 中序数组中,开始的索引
* @param len 树(左(右)子树对应到数组中的长度)
* @param pre_Order_Array 前序数组
* @param in_Order_Array 中序数组 (这里一直把前序中序数组当做参数,是由于在递归过程中,没有动过数组,只是动态的去其中的某些项。)
*/
public static void postOrderSolution(int pre_bg_index, int in_bg_index, int len, char[] pre_Order_Array, char[] in_Order_Array) {
if (len == 0)
return;
char root = pre_Order_Array[pre_bg_index];
if (len==1){//递归出口。
System.out.print(root+" ");
return;
}
int i = 0;
while (root != in_Order_Array[in_bg_index + i]) {//找到中序根节点的位置。
i++;
}
//左右中,标准的后序遍历的形式。
postOrderSolution(pre_bg_index+1, in_bg_index, i, pre_Order_Array, in_Order_Array);
postOrderSolution(pre_bg_index+i+1, in_bg_index+i+1, len-i-1, pre_Order_Array, in_Order_Array);
System.out.print(root+" ");
}
public static void main(String[] args){
char[] pre_Order_Array = {'A','B','D','E','H','C','F','G','I'};
char[] in_Order_Array = {'D','B','H','E','A','F','C','G','I'};
postOrderSolution(0, 0, pre_Order_Array.length, pre_Order_Array, in_Order_Array);
}
}
后序+中序=>前序(与上面大体类似,就是后序的下标用于定位根节点的位置与前序不同)
public class InOrderAndPostOrder {
/**
*
* @param post_end_index 后序数组中,结束的索引(具体到左(右)子树中,数组结束索引+长度len精确指定了某一个左(右)子树)
* @param in_bg_index 中序数组中,开始的索引
* @param len 树(左(右)子树对应到数组中的长度)
* @param post_Order_Array 后序数组
* @param in_Order_Array 中序数组 (这里一直把前序中序数组当做参数,是由于在递归过程中,没有动过数组,只是动态的去其中的某些项。)
*/
public static void preOrderSolution(int post_end_index, int in_bg_index, int len, char[] post_Order_Array, char[] in_Order_Array) {
if (len == 0)
return;
char root = post_Order_Array[post_end_index];
if (len==1){//递归出口。
System.out.print(root+" ");
return;
}
int i = 0;
while (root != in_Order_Array[in_bg_index + i]) {//找到中序根节点的位置。
i++;
}
//中左右,标准的前序遍历的形式。注意左子树中后序结束的索引是从后往前减的,中间减掉的(len-i-1)是右子树对应的数组长度。
System.out.print(root+" ");
preOrderSolution(post_end_index-(len-i-1)-1, in_bg_index, i, post_Order_Array, in_Order_Array);
preOrderSolution(post_end_index-1, in_bg_index+i+1, len-i-1, post_Order_Array, in_Order_Array);
}
public static void main(String[] args){
char[] post_Order_Array = {'D','H','E','B','F','I','G','C','A'};
char[] in_Order_Array = {'D','B','H','E','A','F','C','G','I'};
preOrderSolution(post_Order_Array.length-1, 0, post_Order_Array.length, post_Order_Array, in_Order_Array);
}
}
重建二叉树,然后各种序遍历输出,这里以 前序+中序=>后序+层序 为例:
public class TreeNode {
char val;
TreeNode left;
TreeNode right;
public TreeNode(char val) {
this.val = val;
}
}
public class ReConstructPreAndIn {
/**
* @param pre_bg_index 前序数组中,开始的索引(具体到左(右)子树中,数组开始索引+长度len精确指定了某一个左(右)子树)
* @param in_bg_index 中序数组中,开始的索引
* @param len 树(左(右)子树对应到数组中的长度)
* @param pre_Order_Array 前序数组
* @param in_Order_Array 中序数组 (这里一直把前序中序数组当做参数,是由于在递归过程中,没有动过数组,只是动态的去其中的某些项。)
*/
public static TreeNode reConstruct(int pre_bg_index, int in_bg_index, int len, char[] pre_Order_Array, char[] in_Order_Array) {
if (len == 0)
return null;
char root = pre_Order_Array[pre_bg_index];
if (len == 1) {//递归出口。
TreeNode newNode = new TreeNode(root);
return newNode;
}
int i = 0;
while (root != in_Order_Array[in_bg_index + i]) {//找到中序根节点的位置。
i++;
}
TreeNode node = new TreeNode(root);
node.left = reConstruct(pre_bg_index + 1, in_bg_index, i, pre_Order_Array, in_Order_Array);
node.right = reConstruct(pre_bg_index + i + 1, in_bg_index + i + 1, len - i - 1, pre_Order_Array, in_Order_Array);
return node;
}
//后序遍历
public static void postOrderTransverse(TreeNode root) {
if (root == null)
return;
if (root.left == null && root.right == null) {
System.out.print(root.val + " ");
return;
}
postOrderTransverse(root.left);
postOrderTransverse(root.right);
System.out.print(root.val + " ");
}
//层序遍历
public static void levelOrderTransverse(TreeNode root){
Queue queue = new LinkedList<>();
queue.add(root);
TreeNode node;
while (!queue.isEmpty()){
node = queue.peek();
System.out.print(node.val+" ");
queue.poll();
if(node.left!=null)
queue.add(node.left);
if(node.right!=null)
queue.add(node.right);
}
}
public static void main(String[] args) {
char[] pre_Order_Array = {'A', 'B', 'D', 'E', 'H', 'C', 'F', 'G', 'I'};
char[] in_Order_Array = {'D', 'B', 'H', 'E', 'A', 'F', 'C', 'G', 'I'};
TreeNode root = reConstruct(0, 0, pre_Order_Array.length, pre_Order_Array, in_Order_Array);
postOrderTransverse(root);
System.out.println();
levelOrderTransverse(root);
}
}
End