先上问题:
问题描述
最近,WYF正准备参观他的点卡工厂。WYF集团的经理氰垃圾需要帮助WYF设计参“观”路线。现在,氰垃圾知道一下几件事情:
1.WYF的点卡工厂构成一颗二叉树。
2.一共有n座工厂。
3.他需要把这颗树上的点以后序遍历的方法列出来,才能绘制地图。
还好,最近他的属下给了他先序遍历和中序遍历的数据。可是,氰垃圾最近还要帮㊎澤穻解决一些问题,没有时间。请你帮帮他,替他完成这项任务。由于氰垃圾的一些特殊的要求,WYF的参观路线将会是这棵树的后序遍历。
输入格式
第一行一个整数n,表示一共又n座工厂。
第二行n个整数,表示先序遍历。
第三行n个整数,表示中序遍历。
输出格式
输出共一行,包含n个整数,为后序遍历。
**
思路讲解:
这是一个比较简单的二叉树遍历问题,给出先序遍历,中序遍历序列,要求输出后序遍历序列。
首先需要知道什么是二叉树的先序遍历、中序遍历和后续遍历。先序遍历是先根节点D、然后左孩子L、然后右孩子R,中 序遍历LDR,后序遍历LRD。注意,这里的遍历算法对每一个节点都是这样执行,还有不明白的同学可以参考严蔚敏老师的《数据结构》关于二叉树的内容,讲得很详细。
通过对这几种遍历方法的理解,我们可以知道,先序遍历序列给出了树的跟节点,中序遍历给出了树的左叶子节点。同时,由中序遍历我们可以知道,在序列中 根节点左边的部分就是根节点的左子树,右边的部分就是根节点的右子树,然后一颗子树的后序遍历又是同样的问题!!
至此,思路就已经很清晰了:找到根节点,确定子树,然后递归或者循环。我采用的是递归的方法。还有一些边界问题,我在代码中有注释,可以结合代码看。
import java.util.*;
//二叉树,给出先序遍历和中序遍历,输出后序遍历
/*
* 基本思路:先序遍历的头元素即为整个二叉树的根节点,中序遍历的头元素是最左叶子节点
* 按照中序遍历的算法,当遇到根节点时,即表示树的以便已经遍历完成,即
* 中序遍历序列中,在整树根节点的左边的元素就在根节点左边,右边的树就在右边
* 于是,这个问题就被分解为;两个子问题了。每一次确定树的左右之后,就得到了左右两颗子树
* 而每颗子树的排列又是一样的问题,可以考虑递归算法
* 值得主义的是,子树的边界是什么?
* 二叉树,每一个根节点都有两个子节点,所以,子树的边界就是2
* 即当最后一个子树只有两个元素时,递归就可以结束了
* 按照先序排列的算法,既可以确定这两个元素的位置
*
*
* 还有一个值得思考的问题是,如果根节点的左孩子和他一样呢?
* 或者有孩子节点和他值相同呢?那么上面的方法就会出问题。
* 这时候如何确定中序遍历序列是否完整遍历左树?
*
* 一个可行的方法是在前面的基础上,比较先序遍历的子序列Arrays.copyOfRange(fst, 1, i+1)
* 是否和中序遍历的Arrays.copyOfRange(mid, 0, i)相等,
* 如果相等,证明这就是根节点,否则继续向后遍历
* */
public class Tree {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int n=sc.nextInt();
int[] fst=new int [n];
int[] mid= new int [n];
for(int i=0;i<n;i++) {
fst[i]= sc.nextInt();
}
for(int j=0; j<n;j++) {
mid[j]= sc.nextInt();
}
sc.close();
TreeSort(fst, mid);
/*
* 我的代码老是不通过
* 爱报bug
* 你说啷个搞嘛
* 小错误好难得纠
* 憨了
* 逼着自己的大晚上写题
* 呜呜呜
* */
}
public static void TreeSort(int[] fst,int [] mid) {
if(fst.length != mid.length) {
return;
}
if(mid.length <= 2) {
for(int i=0; i< mid.length; i++) {
System.out.print(mid[i]+" ");
}
return;
}
// else {
// System.out.print(mid[0]+" ");
// }
// int [] temp2, temp1;
//左子树后序遍历输出
for(int i=0;i<mid.length; i++) {
int[] temp2=Arrays.copyOfRange(mid, 0, i);
int [] temp1= Arrays.copyOfRange(fst, 1, i+1);
Arrays.sort(temp1);
Arrays.sort(temp2);
//确定中序遍历序列中是否到达二叉树的根节点
if(mid[i]== fst[0] && equl(temp1,temp2)) {
/*
* 现在的问题是程序没有键入这个if结构
* 也就是if的判断条件不对
* 我怀疑是那个equals方法不对,不能正确比较两个数组是否相等
* 其余暂时没有发现问题
* 03/11
* */
TreeSort(Arrays.copyOfRange(fst, 1, i+1), Arrays.copyOfRange(mid, 0, i));//左树
TreeSort(Arrays.copyOfRange(fst, i+1, fst.length), Arrays.copyOfRange(mid, i+1, mid.length));
System.out.print(fst[0]+" ");
break;
}
}
// System.out.print(fst[0]);
//
}//TreeSort()
//写一个判断子树是否相等的函数,返回boolean值
public static boolean equl(int[] s1,int[] s2) {
if(s1.length != s2.length) {
return false;
}
for(int i=0; i<s1.length;i++) {
if(s1[i]!= s2[i]) {
return false;
}
}
return true;
}
}
但是这个算法有个缺陷,就是时间复杂度太高,主要是equl()方法造成的,我没有想到更好的办法,使用数组的equals()方法不行。
临时写的一篇博客,也许漏洞百出,欢迎指正!
**

本文介绍了一种从先序遍历和中序遍历序列转换到后序遍历序列的算法实现。通过递归方法确定二叉树的根节点及其左右子树,并输出后序遍历序列。

被折叠的 条评论
为什么被折叠?



