zoukankan      html  css  js  c++  java
  • 根据二叉树的前序和中序遍历结果,还原二叉树

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

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

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

           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;
    	}
    
    }

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

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

  • 相关阅读:
    CodeForces Gym 100500A A. Poetry Challenge DFS
    CDOJ 486 Good Morning 傻逼题
    CDOJ 483 Data Structure Problem DFS
    CDOJ 482 Charitable Exchange bfs
    CDOJ 481 Apparent Magnitude 水题
    Codeforces Gym 100637G G. #TheDress 暴力
    Gym 100637F F. The Pool for Lucky Ones 暴力
    Codeforces Gym 100637B B. Lunch 找规律
    Codeforces Gym 100637A A. Nano alarm-clocks 前缀和
    TC SRM 663 div2 B AABB 逆推
  • 原文地址:https://www.cnblogs.com/tanliwei/p/9102659.html
Copyright © 2011-2022 走看看