树
题目:重构二叉树
输入输入某二叉树的前序遍历和中序遍历的结果,请重构该二叉树。
假设输入的前序遍历和中序遍历的结果中都不包含重复的数字。例如,输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},重建该树。树的结点类如下:
class TreeNode{
int value;
TreeNode left;
TreeNode right;
TreeNode(int val){
this.value = value;
}
}
解决:
思路:
通过前序遍历获取根节点的值,然后遍历中序遍历序列,找到根节点,将中序遍历数组分成左右两个树支,然后递归调用,构成一个树。
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
//边界条件的判断
if(pre == null || in == null){
return null;
}
if(pre.length==0 || in.length == 0){
return null;
}
//前序和中序遍历的长度不一致
if(pre.length != in.length){
return null;
}
//获取树的根节点
TreeNode root = new TreeNode(pre[0]);
for(int i= 0;i<in.length;i++){
//在中序遍历中找到前序遍历的值,将中序遍历分成两半
if(in[i] == pre[0]){
root.left = reConstructBinaryTree(Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(in,0,i));
root.right = reConstructBinaryTree(Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(in,i+1,in.length));
}
}
return root;
}
对于树的结构的打印
思路:初步思考这样实现:
......|-6-|
......|...|-8
..|-3-|
..|...|-5
1-|
..|-2-|
......|...|-7
......|-4-|
实现display方法,打印树的结构;先打印右子树的结点,然后再打印根节点,最后打印左子节点。
设置树的每一个节点的表示字符串,树的结点类表示如下:
class TreeNode{
int value;
TreeNode leftNode;
TreeNode rightNode;
String s ;//用于描述改节点的字符串描述
TreeNode(int value) {
this.value = value;
}
}
通过构造树,并将每一个节点表示的字符串进行设置
/**
* 用于设置每一个节点的字符串描述
* @param parent 父节点
* @param next 设置字符串的结点
* @param flag 是否是左节点的右节点的判断
*/
private static void setTreeStructure(TreeNode parent,TreeNode next,boolean flag){
//如果是叶子节点的时候,直接返回
if(next == null){
return;
}
//首先是将前面的根节点的数字替换为' . ' ,为后面添加自己的数值做准备
next.s = parent.s.replaceAll("[0-9]|-",".").substring(0,parent.s.length()-1);
//如果不是内嵌节点,就可以直接将| 全部替换为 .
if(flag == false) {
int index = next.s.lastIndexOf("|");
if (index != -1) {
next.s = next.s.substring(0, index) + "." + next.s.substring(index + 1);
}
}
//添加该节点的值
next.s+="|-"+next.value+"-|";
//进入左右节点的判断
if(parent.leftNode == next ){
if(next.rightNode!=null)
setTreeStructure(next,next.rightNode,true);
if(next.leftNode != null){
setTreeStructure(next,next.leftNode,false);
}
}
if(parent.rightNode == next){
if(next.leftNode != null){
setTreeStructure(next,next.leftNode,true);
}
if(next.rightNode != null){
setTreeStructure(next,next.rightNode,false);
}
}
}
最后将树的结构打印出来
public static void printTree(TreeNode node){
//始终先打印右节点,然后打印本身,最后打印左节点
if(node.rightNode!=null){
printTree(node.rightNode);
}
//如果没有子节点,就不打印后面的"-|“
if(node.leftNode==null&&node.rightNode==null){
System.out.println(node.s.substring(0, node.s.length()-2));
}else{
//有子节点的直接打印该节点的描述
System.out.println(node.s);
}
if(node.leftNode!=null){
printTree(node.leftNode);
}
}
最后来个主方法,看看如何设置树的结构
public static void main(String [] args){
int [] pre = {1,2,4,7,3,5,6,8};//先根遍历结果
int [] in = {4,7,2,1,5,3,8,6};//后根遍历结果
TreeNode root = reConstructBinaryTree(pre,in);
//display(root);
root.s = root.value + "-|";
setTreeStructure(root,root.leftNode,false);//设置左节点
setTreeStructure(root,root.rightNode,false);
//输出
printTree(root);
}