根据一个树的中序遍历和前序遍历数据,还原一个二叉树的思考
2017-03-09 19:15
423 查看
根据一个树的中序遍历和前序遍历数据,还原一个二叉树的思考。
一般树的通常遍历一共有四种:前序,中序,后序,层次遍历;中序遍历和其他任何一个两个遍历序列就可以唯一确定一颗二叉树。
下面的代码基于递归实现是完全没有问题的。可运行。
package com.mytest.test001;
import java.util.Arrays;
//树节点的定义
class BTree{
BTree left;
BTree right;
int val;
}
public class ConstructTreefromcol {
public static void main(String[] args) throws Exception {
int[] preorder={1,2,4,7,3,5,6,8};
int[] inorder={4,7,2,1,5,3,8,6};
BTree root=ConstructTree(preorder,inorder);;
}
private static BTree ConstructTree(int[] preorder, int[] inorder) throws Exception {
if(preorder==null || inorder==null)
return null;
if(preorder.length!=inorder.length)
throw new Exception("输入的中序和前序遍历不对");
BTree root=new BTree();
//法1
for(int i=0;i<inorder.length;i++){
if(inorder[i]==preorder[0]){
root.val=inorder[i];
System.out.println(root.val);
root.left=ConstructTree(Arrays.copyOfRange(preorder, 1, i+1),
Arrays.copyOfRange(inorder, 0, i));
root.right=ConstructTree(Arrays.copyOfRange(preorder, i+1, preorder.length),
Arrays.copyOfRange(inorder, i+1, inorder.length));
}
}
return root;
}
}
针对上面的代码我们做些小的调整试试,将红色部分修改为如下代码:第一种改法! 报错,数组越界:
都是找到i的位置,为何越界?当左右子树一个为空,则访问 root.val=preorder[0]出错。
正确添加一个判断即为:
第二种改法:
这个正确写法是将while循环中的前后顺序需要兑换。
是不是有什么启发呢?虽然是很简单的问题,但是细节很重要。你需要几秒钟能发现问题呢?不同的写法,细节上有很多隐含的东西,使用for循环第一种写法,暗含了对左右为空的处理,健壮性较好,后面的改写,需要注意诸多细节才能调试成功!
一般树的通常遍历一共有四种:前序,中序,后序,层次遍历;中序遍历和其他任何一个两个遍历序列就可以唯一确定一颗二叉树。
下面的代码基于递归实现是完全没有问题的。可运行。
package com.mytest.test001;
import java.util.Arrays;
//树节点的定义
class BTree{
BTree left;
BTree right;
int val;
}
public class ConstructTreefromcol {
public static void main(String[] args) throws Exception {
int[] preorder={1,2,4,7,3,5,6,8};
int[] inorder={4,7,2,1,5,3,8,6};
BTree root=ConstructTree(preorder,inorder);;
}
private static BTree ConstructTree(int[] preorder, int[] inorder) throws Exception {
if(preorder==null || inorder==null)
return null;
if(preorder.length!=inorder.length)
throw new Exception("输入的中序和前序遍历不对");
BTree root=new BTree();
//法1
for(int i=0;i<inorder.length;i++){
if(inorder[i]==preorder[0]){
root.val=inorder[i];
System.out.println(root.val);
root.left=ConstructTree(Arrays.copyOfRange(preorder, 1, i+1),
Arrays.copyOfRange(inorder, 0, i));
root.right=ConstructTree(Arrays.copyOfRange(preorder, i+1, preorder.length),
Arrays.copyOfRange(inorder, i+1, inorder.length));
}
}
return root;
}
}
针对上面的代码我们做些小的调整试试,将红色部分修改为如下代码:第一种改法! 报错,数组越界:
int i=0; while(i<inorder.length){ if(inorder[i]!=preorder[0]) {i++;} if(inorder[i]==preorder[0]){ break; } } root.val=preorder[0]; System.out.println(root.val); root.left=ConstructTree(Arrays.copyOfRange(preorder, 1, i+1), Arrays.copyOfRange(inorder, 0, i)); root.right=ConstructTree(Arrays.copyOfRange(preorder, i+1, preorder.length), Arrays.copyOfRange(inorder, i+1, inorder.length));
都是找到i的位置,为何越界?当左右子树一个为空,则访问 root.val=preorder[0]出错。
正确添加一个判断即为:
int i=0; while(i<inorder.length){ if(inorder[i]!=preorder[0]) {i++;} if(inorder[i]==preorder[0]){ break; } } if(i<inorder.length){ //很重要,这个必须有 root.val=preorder[0]; System.out.println(root.val); root.left=ConstructTree(Arrays.copyOfRange(preorder, 1, i+1), Arrays.copyOfRange(inorder, 0, i)); root.right=ConstructTree(Arrays.copyOfRange(preorder, i+1, preorder.length), Arrays.copyOfRange(inorder, i+1, inorder.length)); }
第二种改法:
int i=0; while(inorder[i]!=preorder[0] && i<inorder.length){ i++; } if(i<inorder.length){ root.val=preorder[0]; System.out.println(root.val); root.left=ConstructTree(Arrays.copyOfRange(preorder, 1, i+1), Arrays.copyOfRange(inorder, 0, i)); root.right=ConstructTree(Arrays.copyOfRange(preorder, i+1, preorder.length), Arrays.copyOfRange(inorder, i+1, inorder.length)); }任然是数组越界:
这个正确写法是将while循环中的前后顺序需要兑换。
int i=0; while( i<inorder.length && inorder[i]!=preorder[0]){ i++; } if(i<inorder.length){ root.val=preorder[0]; System.out.println(root.val); root.left=ConstructTree(Arrays.copyOfRange(preorder, 1, i+1), Arrays.copyOfRange(inorder, 0, i)); root.right=ConstructTree(Arrays.copyOfRange(preorder, i+1, preorder.length), Arrays.copyOfRange(inorder, i+1, inorder.length)); }
是不是有什么启发呢?虽然是很简单的问题,但是细节很重要。你需要几秒钟能发现问题呢?不同的写法,细节上有很多隐含的东西,使用for循环第一种写法,暗含了对左右为空的处理,健壮性较好,后面的改写,需要注意诸多细节才能调试成功!
相关文章推荐
- 根据树的前序遍历与中序遍历构建二叉树
- 数据结构实验之求二叉树后序遍历和层次遍历(根据前序中序还原二叉树)
- 根据二叉树的中序遍历和层次遍历还原二叉树
- 数据结构与算法——二叉树的前序遍历,中序遍历,后序遍历
- 数据结构——根据前序遍历和中序遍历还原二叉树
- 根据树的前序遍历与中序遍历构建二叉树
- 根据二叉树的前序遍历和中序遍历(或者中序遍历和后序遍历)还原二叉树
- 数据结构之二叉树的前序遍历、中序遍历、后序遍历、层序遍历
- 数据结构之二叉树的前序遍历、中序遍历、后序遍历、层序遍历
- 二叉树问题-根据前序遍历结果和中序遍历结果得出后序遍历结果
- 根据二叉树的中序遍序列和后续遍历序列还原一颗二叉树
- 根据前序和中序序列建造一个二叉树并且输出后序序列
- 根据前序和中序遍历的结果建立二叉树
- 根据二叉树的先序和中序遍历还原二叉树
- 根据前序和中序遍历序列重构二叉树 代码完整版
- 根据后序遍历和中序遍历结果还原二叉树
- C++数据结构--二叉树的前序遍历,中序遍历,后序遍历
- poj2255 根据二叉树的前序和中序遍历 求出树的后序遍历
- 一个关于二叉树的创建、先序遍历、中序遍历、后序遍历、求叶子节点的完整函数的c语言完整程序。
- [c++]已知二叉树的前序遍历与中序遍历结果(二叉树中不含重复数字),重构二叉树