重建二叉树(java)

一,问题描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

二,算法分析

中序特点:左子树   根     右子树     (左子树,右子树同理)

前序特点:根 左子树    右子树     (左子树,右子树同理)

例如,前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}

  对应的二叉树:


  左子树和右子树在数组中的位置:


给定的数据结构:

1.int[] preOrder  前序数组

2.int[] inOrder  中序数组

通过前序中序遍历的特点可知,在前序数组中第一个元素为root节点值,由于个元素值不重复,可以在中序数组中找到root节点值对应的下标,设为inOrderRootIndex.因此中序数组可以区分出,左子树和右子树的区域。然后可以确定前序数组中左子树和右子树的区间。再利用递归的思想来构造左子树和右子树。

三,算法设计

定义变量:

(1)对于前序数组

 int preOrderStartIndex  前序数组开始下标  

 int preOrderEndIndex   前序数组结束下标

 int preOrderRootIndex  根节点下标

 int preLeftSubTreeStartIndex 前序左子树开始下标

 int preLeftSubTreeEndIndex 前序左子树结束下标

 int preRightSubTreeStartIndex 前序右子树开始下标

 int preRightSubTreeEndIndex 前序右子树结束下标

      

       (2)对于中序数组

         int preOrderStartIndex  前序数组开始下标  

 int inOrderEndIndex   前序数组结束下标

 int inOrderRootIndex  根节点下标

 int inLeftSubTreeStartIndex 前序左子树开始下标

 int inLeftSubTreeEndIndex 前序左子树结束下标

 int inRightSubTreeStartIndex 前序右子树开始下标

 int inRightSubTreeEndIndex 前序右子树结束下标


实现步骤 :

(1)根据前序数组和中序数组的特点,给各个变量赋初值,并返回根节点

(2)获取左右子树的根节点,构造二叉树

四,代码实现

class BinaryTreeNode{
	int value;
	BinaryTreeNode leftChild;
	BinaryTreeNode rightChild;
	public BinaryTreeNode(int value) {
		this.value = value;
		this.leftChild = null;
		this.rightChild = null;
	}
}

public class ReConstructBinaryTree{
	
	public BinaryTreeNode reConstruct(int[] preOrder, int[] inOrder){
		if(preOrder==null || inOrder==null) return null;
		BinaryTreeNode root = constructCore(preOrder, 0, preOrder.length-1, inOrder, 0, inOrder.length-1);
		return root;
	}
	public BinaryTreeNode constructCore(int[] preOrder, int preOrderStartIndex,int preOrderEndIndex, int[] inOrder, int inOrderStartIndex, int inOrderEndIndex){
		 int preLeftSubTreeStartIndex; //前序左子树开始下标
		 int preLeftSubTreeEndIndex; //前序左子树结束下标
		 int preRightSubTreeStartIndex; //前序右子树开始下标
		 int preRightSubTreeEndIndex; //前序右子树结束下标
		 int preOrderRootIndex; //根节点下标
		 
		 int inLeftSubTreeStartIndex; //前序左子树开始下标
		 int inLeftSubTreeEndIndex; //前序左子树结束下标
		 int inRightSubTreeStartIndex; //前序右子树开始下标
		 int inRightSubTreeEndIndex; //前序右子树结束下标
		 int inOrderRootIndex = 0; //根节点下标
		
		 preOrderRootIndex = preOrderStartIndex;
		 int rootValue = preOrder[preOrderRootIndex];
		 BinaryTreeNode root = new BinaryTreeNode(rootValue);
		 //找到根节点在中序数组中的下标
		 for(int i=inOrderStartIndex; i<=inOrderEndIndex; i++){
			 if(inOrder[i] == rootValue){
				 inOrderRootIndex = i;
			 }
		 }
		//判断是否只包含一个元素
		 if(preOrderStartIndex == preOrderEndIndex && inOrderStartIndex == inOrderEndIndex){
			 return new BinaryTreeNode(preOrder[preOrderStartIndex]);
		 }
		 
		//确定中序数组中左子树和右子树的起始下标和终止下标
		 inLeftSubTreeStartIndex = inOrderStartIndex;
		 inLeftSubTreeEndIndex = inOrderRootIndex -1;
		 inRightSubTreeStartIndex = inOrderRootIndex+1;
		 inRightSubTreeEndIndex = inOrderEndIndex;
		 
		 int leftsubTreeLength = inOrderRootIndex - inOrderStartIndex; 
		 
		 //确定前序数组中左子树和右子树的起始下标和终止下标
		 preLeftSubTreeStartIndex = preOrderRootIndex +1;
		 preLeftSubTreeEndIndex = preLeftSubTreeStartIndex + leftsubTreeLength-1;
		 preRightSubTreeStartIndex = preLeftSubTreeEndIndex+1;
		 preRightSubTreeEndIndex = preOrderEndIndex;
		 
		 //创建左子树
		 if(leftsubTreeLength>0){
			 root.leftChild = constructCore(preOrder, preLeftSubTreeStartIndex, preLeftSubTreeEndIndex, inOrder, inLeftSubTreeStartIndex, inLeftSubTreeEndIndex);
		 }
		 	
		 int rightSubTreeLength = inRightSubTreeEndIndex-inRightSubTreeStartIndex+1;
		 //创建右子树
		 if(rightSubTreeLength>0){
			 root.rightChild = constructCore(preOrder, preRightSubTreeStartIndex, preRightSubTreeEndIndex, inOrder, inRightSubTreeStartIndex, inRightSubTreeEndIndex);
		 }
		 return root;
	}
	
	public void printPreOrder(BinaryTreeNode root){
		if(root==null){
			 return;
		}else{
			System.out.print(root.value+" ");
		}
		if(root.leftChild != null){
			printPreOrder(root.leftChild);
		}
		if(root.rightChild != null){
			printPreOrder(root.rightChild);
		}
		
	}
	
	public static void main(String[] args) {
		  int[] preOrder={1,2,4,7,3,5,6,8};  
	      int[] inOrder={4,7,2,1,5,3,8,6};  
	      ReConstructBinaryTree tree = new ReConstructBinaryTree();
	      BinaryTreeNode root = tree.reConstruct(preOrder, inOrder);
	      tree.printPreOrder(root);
	      
	}
}

五,总结

对于算法设计题,首先要理解对象的特征,比如该题中,前序遍历的顺序是根,左子树,右子树;中序遍历的顺序是左子树,根,右子树。然后根据特征定义变量,编写程序。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值