首页 > 代码库 > 剑指offer之重建二叉树

剑指offer之重建二叉树

1、题目

   很简单,知道一棵二叉树的前序和中序,要求重建此二叉树。


2、思路

由前序可知道根结点的值,然后遍历中序,可以找到根结点的位置,然后在该位置的左边就是根结点的左子树,右边就是右子树,然后通过递归就可以得到整棵树。


3、实现代码

	/**
	 * decription: 树节点
	 * @author : linjq
	 */
	private class TreeNode {
		private int element;
		private TreeNode left;
		private TreeNode right;

		public TreeNode(int element) {
			this.element = element;
		}
	}

/**
	 * decription: 重构二叉树,知道前序和中序 解决思路:由前序可知道一个树结点的值,然后在中序那里找到那个值,记录位置,它左边的是它的
	 * 左子树,右边是右子树,依次递归可得到整棵树。
	 * @author : linjq
	 */

	private TreeNode rebuidTree(int[] preOrder, int[] inOrder, int preBegin,
			int preEnd, int inBegin, int inEnd) {
		if (preBegin > preEnd || inBegin > inEnd) {
			return null; // 证明已到尽头,返回空结点
		} else {
			TreeNode rootNode = new TreeNode(preOrder[preBegin]);
			// 当前节点值在中序的位置,找到该位置是为了找到这个结点的左右子树
			int rootInPosition = -1;
			for (int i = inBegin; i <= inEnd; i++) {
				if (inOrder[i] == rootNode.element) {
					rootInPosition = i;
					break;
				}
			}
			//下面是准确定位到哪些是它的左子树范围,哪些事右子树
			int leftNum = rootInPosition - inBegin;// 左子树 有多少个结点
			int leftPreBegin = preBegin + 1;
			int leftPreEnd = preBegin + leftNum;
			int leftInBegin = inBegin;
			int leftInEnd = inBegin + leftNum;
		
			int rightPreBegin = preBegin + 1 + leftNum;
			int rightPreEnd = preEnd;
			int rightInBegin = rootInPosition + 1;
			int rightInEnd = inEnd;
			// 寻找该结点的左子树,右子树
			TreeNode leftNode = rebuidTree(preOrder, inOrder, leftPreBegin,
					leftPreEnd, leftInBegin, leftInEnd);
			TreeNode righNode = rebuidTree(preOrder, inOrder, rightPreBegin,
					rightPreEnd, rightInBegin, rightInEnd);
			rootNode.left = leftNode;
			rootNode.right = righNode;
			return rootNode;
		}
	}

	/**
	 * decription:中序遍历
	 * @author : linjq
	 */
	public void inOrder(TreeNode rootNode) {
		if (rootNode == null) {
			return;
		} else {
			inOrder(rootNode.left);
			System.out.print(rootNode.element + " ");
			inOrder(rootNode.right);
		}
	}


	/**
	 * decription:前序遍历
	 * @author : linjq
	 */
	public void preOrder(TreeNode rootNode) {
		if (rootNode == null) {
			return;
		} else {
			System.out.print(rootNode.element + " ");
			preOrder(rootNode.left);
			preOrder(rootNode.right);
		}
	}
	

/**
	 * decription: main方法 测试 重建二叉树
	 * @author : linjq
	 */
	public static void main(String[] args) {
		RecoverBST bst = new RecoverBST();
		
		int[] inOrder =  {4,7,2,1,5,3,8,6};
		int[] preOrder = {1,2,4,7,3,5,6,8};
		TreeNode root = bst.rebuidTree(preOrder, inOrder, 0, preOrder.length-1, 0, inOrder.length-1);
		System.out.println("重建后的中序");
		//输出中序
		bst.inOrder(root);
		System.out.println();
		System.out.println("重建后的前序");
		//输出前序
		bst.preOrder(root);
	}

4、测试结果



对比给定的已知条件,它们一致,代码正确。然而,递归的方法虽然简单,当该二叉树很深很深,比如深度达到1000以上的时候,用递归就不好了,容易造成栈溢出。因此,换成非递归方法来实现是更好的选择。










剑指offer之重建二叉树