一、题目
1.原题
有一棵二叉树,每个节点由一个大写字母标识(最多26个节点)。
现有两组字母,
分别表示后序遍历(左孩子->右孩子->父节点)和 中序遍历(左孩子->父节点->右孩子)的结果,
请输出层次遍历的结果。
2.题目理解
已知一棵二叉树的后序遍历和中序遍历结果,可以根据两种遍历结果重建二叉树,再进行层次遍历(广度优先遍历)。
二、思路与代码过程
1.思路
二叉树的后序遍历(左子树->右子树->根节点)的最后一个元素是根节点;中序遍历(左子树->根节点->右子树)的中间是根节点;由后序遍历可得到根节点的值,再在中序遍历中查找到位置,就可分出左子树和右子树(左子树和右子树同理)。
创建一个分割函数(接收传值:左右子树值链表和当前根节点值),递归调用它分割左右子树,并对二叉树进行构建(第一个根节点传入后有了root,分割出左右子树后序遍历后可以从末尾获取左右子树的节点值,有了root->left和root->right,递归下去直到左右子树链表为空)。
最后对root进行层次遍历打印即可。
2.代码过程
①main函数
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ArrayList<String> postorderTraversal = new ArrayList<>();
ArrayList<String> inorderTraversal = new ArrayList<>();
System.out.println("请输入当前二叉树后序遍历的结果:");
String[] sb = sc.nextLine().split(" ");
for (String s : sb) {
postorderTraversal.add(s);
}
System.out.println("请输入当前二叉树中序遍历的结果:");
String[] sm = sc.nextLine().split(" ");
for (String s : sm) {
inorderTraversal.add(s);
}
TreeNode BFSresult = OutPutBFS(postorderTraversal,inorderTraversal);
System.out.print("该二叉树的层次遍历结果为:");
BFSresult.printLevelOrder();
}
②OutPutBFS函数
private static TreeNode OutPutBFS(ArrayList<String> postorderTraversal, ArrayList<String> inorderTraversal) {
int n = postorderTraversal.size();
TreeNode FristNode = new TreeNode(postorderTraversal.get(n-1));
TreeNode root = splitLRSubTree(postorderTraversal,inorderTraversal,FristNode);
return root;
}
③全局变量
static ArrayList<TreeNode> rootNode = new ArrayList<>();
④splitLRSubTree函数
private static TreeNode splitLRSubTree(ArrayList<String> postorderTraversal, ArrayList<String> inorderTraversal,TreeNode root) {
int n = postorderTraversal.size();//
ArrayList<String> leftSubTreePT = new ArrayList<>();
ArrayList<String> rightSubTreePT = new ArrayList<>();
ArrayList<String> leftSubTreeIT = new ArrayList<>();
ArrayList<String> rightSubTreeIT = new ArrayList<>();
for (int i = 0; i < postorderTraversal.size(); i++) {
//后序遍历的最后一个是根节点,遍历中序找到后序的最后一个节点值的位置
if (inorderTraversal.get(i).equals(postorderTraversal.get(n - 1))) {
//将根节点加入根节点链表
rootNode.add(root);
break;
} else {
//没找到时,后序遍历左子树添加后序遍历的数值
leftSubTreePT.add(postorderTraversal.get(i));
//中序遍历添加中序遍历的数值
leftSubTreeIT.add(inorderTraversal.get(i));
}
}
//从链表的最后开始转存入
for (int i = leftSubTreePT.size(); i<n-1; i++) {
rightSubTreePT.add(postorderTraversal.get(i));
rightSubTreeIT.add(inorderTraversal.get(i + 1));
}
//左节点加入方法
//左子树的长度不为零,将左子树的后序遍历的末尾作为当前root的左节点
if (leftSubTreePT.size()>0) {
int leftSize = leftSubTreePT.size();
TreeNode LeftNode = new TreeNode(leftSubTreePT.get(leftSize-1));
root.left = LeftNode;
}
//右节点加入方法
//右子树的长度不为零,将右子树的后序遍历的末尾作为当前root的左节点
if (rightSubTreePT.size()>0) {
int rightSize = rightSubTreePT.size();
TreeNode RightNode = new TreeNode(rightSubTreePT.get(rightSize-1));
root.right = RightNode;
}
//递归
if (leftSubTreePT.size()>1) {
splitLRSubTree(leftSubTreePT,leftSubTreeIT,root.left);//DEB DBE
}
if (rightSubTreePT.size()>1) {
splitLRSubTree(rightSubTreePT,rightSubTreeIT,root.right);//FC CF
}
//若树节点数等于所有节点数,返回
if (root.countNodes()==n) {
return root;
}
return root;
}
⑤TreeNode类
static class TreeNode{
String value;
TreeNode left;
TreeNode right;
TreeNode(String value){
this.value = value;
this.left = null;
this.right = null;
}
public int countNodes() {
if (this == null) {
return 0;
}
return 1 + (left != null ? left.countNodes() : 0) + (right != null ? right.countNodes() : 0);
}
public void printLevelOrder() {
if (this == null) {
return;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(this);
StringBuilder result = new StringBuilder();
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
result.append(node.value).append(" "); // 将节点值添加到结果中,并用空格分隔
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
System.out.println(result.toString().trim()); // 打印整个结果,并去除末尾的多余空格
}
public String toString(){
return value;
}
}
三、运行结果
1.运行截图
2.带数据分析运行结果
-------splitLRSubTree开始-------
中序子树[D, B, E, A, C, F]
后序子树[D, E, B, F, C, A]
1 根节点:
A
1 根节点:
A
1 中序子树[D, B, E, A, C, F]
1 后序子树[D, E, B, F, C, A]
-------循环开始-------
中序i=0,值为D
后序i=0,值为D
根节点值为:A
未找到根节点将D加入中序左子树leftSubTreeIT
未找到根节点将D加入后序左子树leftSubTreePT
2 中序左子树[D]
2 后序左子树[D]
-------循环开始-------
中序i=1,值为B
后序i=1,值为E
根节点值为:A
未找到根节点将B加入中序左子树leftSubTreeIT
未找到根节点将E加入后序左子树leftSubTreePT
2 中序左子树[D, B]
2 后序左子树[D, E]
-------循环开始-------
中序i=2,值为E
后序i=2,值为B
根节点值为:A
未找到根节点将E加入中序左子树leftSubTreeIT
未找到根节点将B加入后序左子树leftSubTreePT
2 中序左子树[D, B, E]
2 后序左子树[D, E, B]
-------循环开始-------
中序i=3,值为A
后序i=3,值为F
根节点值为:A
找到了根节点:A
当前根节点链表为[A]
2 中序右子树[C]
2 后序右子树[F]
2 中序右子树[C, F]
2 后序右子树[F, C]
-------分割后检查-------
3 根节点:
A
3 中序左子树[D, B, E]
3 后序左子树[D, E, B]
3 中序右子树[C, F]
3 后序右子树[F, C]
----------递归开始---------
-------splitLRSubTree开始-------
中序子树[D, B, E]
后序子树[D, E, B]
1 根节点:
B
1 根节点:
B
1 中序子树[D, B, E]
1 后序子树[D, E, B]
-------循环开始-------
中序i=0,值为D
后序i=0,值为D
根节点值为:B
未找到根节点将D加入中序左子树leftSubTreeIT
未找到根节点将D加入后序左子树leftSubTreePT
2 中序左子树[D]
2 后序左子树[D]
-------循环开始-------
中序i=1,值为B
后序i=1,值为E
根节点值为:B
找到了根节点:B
当前根节点链表为[A, B]
2 中序右子树[E]
2 后序右子树[E]
-------分割后检查-------
3 根节点:
B
3 中序左子树[D]
3 后序左子树[D]
3 中序右子树[E]
3 后序右子树[E]
----------递归开始---------
当前二叉树的层次遍历为:B D E
根节点链表长度为:3
-------splitLRSubTree开始-------
中序子树[C, F]
后序子树[F, C]
1 根节点:
C
1 根节点:
C
1 中序子树[C, F]
1 后序子树[F, C]
-------循环开始-------
中序i=0,值为C
后序i=0,值为F
根节点值为:C
找到了根节点:C
当前根节点链表为[A, B, C]
2 中序右子树[F]
2 后序右子树[F]
-------分割后检查-------
3 根节点:
C
3 中序左子树[]
3 后序左子树[]
3 中序右子树[F]
3 后序右子树[F]
----------递归开始---------
当前二叉树的层次遍历为:C F
根节点链表长度为:2
当前二叉树的层次遍历为:A B C D E F
根节点链表长度为:6
该二叉树的层次遍历结果为:A B C D E F
3.带数据分析完整代码
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
public class test26 {
public static void main(String[] args) {
/*
Scanner sc = new Scanner(System.in);
ArrayList<String> postorderTraversal = new ArrayList<>();
ArrayList<String> inorderTraversal = new ArrayList<>();
System.out.println("请输入当前二叉树后序遍历的结果:");
String[] sb = sc.nextLine().split(" ");
for (String s : sb) {
postorderTraversal.add(s);
}
System.out.println("请输入当前二叉树中序遍历的结果:");
String[] sm = sc.nextLine().split(" ");
for (String s : sm) {
inorderTraversal.add(s);
}
System.out.println("当前二叉树层次遍历的结果为:");
*/
// /*测试
int n = 6;
String[] sb = {"D", "E", "B", "F", "C", "A"};//后
String[] sm = {"D", "B", "E", "A", "C", "F"};//中
ArrayList<String> postorderTraversal = new ArrayList<>();
ArrayList<String> inorderTraversal = new ArrayList<>();
for (String s : sb) {
postorderTraversal.add(s);
}
for (String s : sm) {
inorderTraversal.add(s);
}
//层次遍历:ABCDEF
TreeNode BFSresult = OutPutBFS(postorderTraversal,inorderTraversal);
System.out.print("该二叉树的层次遍历结果为:");
BFSresult.printLevelOrder();
}
private static TreeNode OutPutBFS(ArrayList<String> postorderTraversal, ArrayList<String> inorderTraversal) {
int n = postorderTraversal.size();//
TreeNode FristNode = new TreeNode(postorderTraversal.get(n-1));
TreeNode root = splitLRSubTree(postorderTraversal,inorderTraversal,FristNode);
return root;
}
static ArrayList<TreeNode> rootNode = new ArrayList<>();
private static TreeNode splitLRSubTree(ArrayList<String> postorderTraversal, ArrayList<String> inorderTraversal,TreeNode root) {
System.out.println("-------splitLRSubTree开始-------");
System.out.println("中序子树"+inorderTraversal);//FC
System.out.println("后序子树"+postorderTraversal);//DEB
System.out.println("1 根节点:");// A
root.printLevelOrder();
int n = postorderTraversal.size();//
ArrayList<String> leftSubTreePT = new ArrayList<>();
ArrayList<String> rightSubTreePT = new ArrayList<>();
ArrayList<String> leftSubTreeIT = new ArrayList<>();
ArrayList<String> rightSubTreeIT = new ArrayList<>();
System.out.println("1 根节点:");// A
root.printLevelOrder();
System.out.println("1 中序子树"+inorderTraversal);//DBE CF
System.out.println("1 后序子树"+postorderTraversal);//DEB FC
///*
for (int i = 0; i < postorderTraversal.size(); i++) {
System.out.println("-------循环开始-------");
//后序遍历的最后一个是根节点,遍历中序找到后序的最后一个节点值的位置
System.out.println("中序i="+i+",值为"+inorderTraversal.get(i));
System.out.println("后序i="+i+",值为"+postorderTraversal.get(i));
System.out.println("根节点值为:"+postorderTraversal.get(n - 1));
if (inorderTraversal.get(i).equals(postorderTraversal.get(n - 1))) {
//将根节点加入根节点链表
//rootNode.add(postorderTraversal.get(n - 1));
System.out.println("找到了根节点:"+inorderTraversal.get(i));
rootNode.add(root);
System.out.println("当前根节点链表为"+rootNode);
break;
} else {
System.out.println("未找到根节点将"+inorderTraversal.get(i)+"加入中序左子树leftSubTreeIT");
System.out.println("未找到根节点将"+postorderTraversal.get(i)+"加入后序左子树leftSubTreePT");
//没找到时,后序遍历左子树添加后序遍历的数值
leftSubTreePT.add(postorderTraversal.get(i));
//中序遍历添加中序遍历的数值
leftSubTreeIT.add(inorderTraversal.get(i));
System.out.println("2 中序左子树"+leftSubTreeIT);
System.out.println("2 后序左子树"+leftSubTreePT);
}
}
//从链表的最后开始转存入
for (int i = leftSubTreePT.size(); i<n-1; i++) {
rightSubTreePT.add(postorderTraversal.get(i));
rightSubTreeIT.add(inorderTraversal.get(i + 1));
System.out.println("2 中序右子树"+rightSubTreeIT);
System.out.println("2 后序右子树"+rightSubTreePT);
}
System.out.println("-------分割后检查-------");
System.out.println("3 根节点:");// A
root.printLevelOrder();
System.out.println("3 中序左子树"+leftSubTreeIT);//DBE
System.out.println("3 后序左子树"+leftSubTreePT);//DEB
System.out.println("3 中序右子树"+rightSubTreeIT);//CF
System.out.println("3 后序右子树"+rightSubTreePT);//FC
//左节点加入方法
//左子树的长度不为零,将左子树的后序遍历的末尾作为当前root的左节点
if (leftSubTreePT.size()>0) {
int leftSize = leftSubTreePT.size();
TreeNode LeftNode = new TreeNode(leftSubTreePT.get(leftSize-1));
root.left = LeftNode;
}
//右节点加入方法
//右子树的长度不为零,将右子树的后序遍历的末尾作为当前root的左节点
if (rightSubTreePT.size()>0) {
int rightSize = rightSubTreePT.size();
TreeNode RightNode = new TreeNode(rightSubTreePT.get(rightSize-1));
root.right = RightNode;
}
//递归
System.out.println("----------递归开始---------");
if (leftSubTreePT.size()>1) {
splitLRSubTree(leftSubTreePT,leftSubTreeIT,root.left);//DEB DBE
}
if (rightSubTreePT.size()>1) {
splitLRSubTree(rightSubTreePT,rightSubTreeIT,root.right);//FC CF
}
System.out.print("当前二叉树的层次遍历为:");
root.printLevelOrder();
System.out.println("根节点链表长度为:"+root.countNodes());
//若树节点数等于所有节点数,返回
if (root.countNodes()==n) {
return root;
}
// */
return root;
}
static class TreeNode{
String value;
TreeNode left;
TreeNode right;
TreeNode(String value){
this.value = value;
this.left = null;
this.right = null;
}
public int countNodes() {
if (this == null) {
return 0;
}
return 1 + (left != null ? left.countNodes() : 0) + (right != null ? right.countNodes() : 0);
}
public void printLevelOrder() {
if (this == null) {
return;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(this);
StringBuilder result = new StringBuilder();
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
result.append(node.value).append(" "); // 将节点值添加到结果中,并用空格分隔
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
System.out.println(result.toString().trim()); // 打印整个结果,并去除末尾的多余空格
}
public String toString(){
return value;
}
}
}