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


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

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

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

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

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

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

  • 相关阅读:
    Exadata 上关于SAS盘的小秘密
    Python 全栈开发:python循环语句while
    Python 全栈开发:python条件语句if..else..
    Python 全栈开发:python基础
    Python 全栈开发:python初识
    计算机基础(简单了解)
    如何计算网络配置中广播域和冲突域的数目?
    使VS开发的程序在Win7系统运行时自动提升权限
    在程序中通过Process启动外部exe的方法及注意事项
    获取指定目录下多种格式的文件
  • 原文地址:https://www.cnblogs.com/tanliwei/p/9102659.html
Copyright © 2020-2023  润新知