根据二叉树的前序和中序遍历结果,还原二叉树

题目:根据二叉树的前序和中序遍历结果,还原这颗二叉树。

 

例如,一颗的二叉树如下所示

=======二叉树=======

       1

 

     2   3

 

   4 5  6 7

 

  8 

=======二叉树=======

 

根据二叉树的遍历策略:

前序遍历策略:1)访问根节点;2)访问左子树;3)访问右子树。

中序遍历策略:1)访问左子树;2)访问根节点;3)访问右子树。

得到前序和中序遍历的结果如下,

前序遍历为:12485367,

中序遍历为:84251637。

 

现在,已知,二叉树的前序遍历结果、中序遍历的结果,求原二叉树。

 

分析:

1. 数据结构

需要定义Node节点,Node节点包含值/键 key,和指向左右子树的引用left、right。前序中序的遍历结果,存储在数组中。

2. 策略

选择递归策略解题,能用递归解题的原因在于,原问题,经过一趟的处理/划分后,能变成一个规模更小的子问题。每一趟处理,得到一个节点Node,通过把子问题处理结果subNode返回给父问题得到的Node的left、right,把父子问题的Node关联起来,最终得到连通的原二叉树。

3. 编程语言

各种编程语言都可以,我用的是Java。

 

/**
 * @author tanliwei
 * @email tanliweii@qq.com
 * @time 2016-4-28下午10:15:32
 */
public class RestoreBinaryTreeByTwoTraverseOder {
	//
	// ===binary tree=== 
	//      1
	// 
	//     2 3
	// 
	//   4 5 6 7
	// 
	//  8 
        // ===binary tree===
	// 
	// preorder traversal: 12485367; inorder traversal : 84251637;
	// 
	// input : Preoder & inoder traversal results of a binary tree(e.g. above)
	// output : The orginal binary tree
	//
	public Node restore(int[] preorder, int[] inorder) {
		if (preorder.length == 0 ||  inorder.length == 0) {
			return null;
		}
		Node root = new Node(preorder[0]);
		int rootIndexInInorder = findIndexByValue(preorder[0], inorder);
		int lengthOfSubPreorder1 = rootIndexInInorder;
		int[] subPreorder1 = {};
		if (lengthOfSubPreorder1 > 0) {
			// generate subPreorder1 2485
			subPreorder1 = new int[lengthOfSubPreorder1];
			System
					.arraycopy(preorder, 1, subPreorder1, 0,
							lengthOfSubPreorder1);
		}
		// remain subPreorder
		int lengthOfSubPreorder2 = preorder.length - lengthOfSubPreorder1 - 1;
		int[] subPreorder2 = {};
		if (lengthOfSubPreorder2 > 0) {
			// generate subPreorder2 367
			subPreorder2 = new int[lengthOfSubPreorder2];
			System.arraycopy(preorder, preorder.length
					- lengthOfSubPreorder2, subPreorder2, 0, lengthOfSubPreorder2);
		}

		int lengthOfSubinorder1 = rootIndexInInorder;
		int[] subinorder1 = {};
		if (lengthOfSubinorder1 > 0) {
			subinorder1 = new int[lengthOfSubinorder1];
			// generate subPreorder1 8425
			System.arraycopy(inorder, 0, subinorder1, 0, lengthOfSubinorder1);
		}
		// remain subInorder
		int lengthOfSubInorder2 = preorder.length - lengthOfSubinorder1 - 1;
		int[] subinorder2 = {};
		if (lengthOfSubInorder2 > 0) {
			subinorder2 = new int[lengthOfSubInorder2];
			// generate subPreorder2 637
			System.arraycopy(inorder, inorder.length
					- lengthOfSubInorder2, subinorder2, 0, lengthOfSubPreorder2);
		}
		root.setLeft(restore(subPreorder1,subinorder1));
		root.setRight(restore(subPreorder2,subinorder2));
		return root;
	}

	/**
	 * find the index of the same value of compareValue in array a
	 * 
	 * @param compareValue
	 * @param a
	 * @return
	 */
	public int findIndexByValue(int compareValue, int[] a) {
		if (null == a || a.length == 0) {
			return -1;
		}
		for (int i = 0; i < a.length; i++) {
			if (a[i] == compareValue) {
				return i;
			}
		}
		return -1;
	}

	public static void main(String[] args) {
		//12485367; inorder traversal : 84251637;
		int[] preorder = {1,2,4,8,5,3,6,7};
		int[] inorder = {8,4,2,5,1,6,3,7};
		RestoreBinaryTreeByTwoTraverseOder runner = new RestoreBinaryTreeByTwoTraverseOder();
		Node head = new Node(-1);//
		head = runner.restore(preorder, inorder);
		if(null == head){
			return ;
		}
		runner.preorderTraverse(head);
		System.out.println();
		runner.inorderTraverse(head);
	}
	/**
	 * Traverse in preorder
	 * @param root
	 */
	public void preorderTraverse(Node root){
		if(null == root)
			return;
		System.out.print(root.getKey());
		preorderTraverse(root.getLeft());
		preorderTraverse(root.getRight());
	}
	/**
	 * Traverse in inorder
	 * @param root
	 */
	public void inorderTraverse(Node root){
		if(null == root)
			return;
		inorderTraverse(root.getLeft());
		System.out.print(root.getKey());
		inorderTraverse(root.getRight());
	}
}

class Node {
	public Node() {
	};

	public Node(int key) {
		this.key = key;
	}

	private int key;
	private Node left;
	private Node right;

	public Node getLeft() {
		return left;
	}

	public void setLeft(Node left) {
		this.left = left;
	}

	public Node getRight() {
		return right;
	}

	public void setRight(Node right) {
		this.right = right;
	}

	public int getKey() {
		return key;
	}

	public void setKey(int key) {
		this.key = key;
	}

}

 

代码如上,运行测试可行,尚未进行更多的验证。如有遗漏,欢迎指正。

该问题可以继续拓展为,已知中序、后序遍历结果,还原原二叉树,等等。

posted @ 2016-04-30 09:32  tanliwei  阅读(276)  评论(0编辑  收藏  举报