• 根据前序遍历和中序遍历重建二叉树


    package com.study;

    /*
     * 根据二叉树的前序遍历和中序遍历结果重建二叉树
     * 并输出其头节点。假设前序遍历和中序遍历结果中没有重复数字
     * 前序遍历序列:{1,2,4,7,3,5,6,8}
     * 中序遍历序列:{4,7,2,1,5,3,8,6}
     * **/
    class TreeNode {
    	public int data;
    	public TreeNode left;
    	public TreeNode right;
    	
    	public TreeNode() {
    		
    	}
    }
    
    
    public class suanfa4 {
    	
    	private static int[] arr1 = {1,2,4,7,3,5,6,8};
    	private static int[] arr2 = {4,7,2,1,5,3,8,6};
    	public static TreeNode RebuildBinaryTree() {
    		TreeNode head = null;
    		head = ConstructBTree( head ,arr1, 0, 7, arr2, 0, 7);
    		return head;
    	}
    	
    	public static TreeNode ConstructBTree(TreeNode node, int[] pre, int pre_start, int pre_end,
    			int[] inorder, int inorder_start, int inorder_end) {
    		//System.out.println("pre_start:" + pre_start);
    		//System.out.println("pre_end: "+ pre_end);
    		/*if(pre_start > pre_end || pre_end > pre.length) 
    			return null;*/ 
    		/*刚开始想着这里应该增加这样一个递归结束条件,但是在调试的过程中发现,如果增加了的话,则不能将最后
    			的叶子节点加到二叉树中,而且后面的判断左子树长度和右子树长度会自然结束递归*/
    		TreeNode root = new TreeNode();
    		root.data = pre[pre_start]; //找到根节点
    		root.left = root.right = null;
    
    		//System.out.println("root :"+ root.data);
    		int pos = FindPos(root.data, inorder); //在中序遍历的数组中找到根节点的位置
    		int Left_Length = pos - inorder_start;
    		int Right_Length = inorder_end - pos;
    		//System.out.println("左子树长度" + Left_Length);
    		//System.out.println("右子树长度" + Right_Length);
    		
    		if( Left_Length > 0) {   //存在左子树
    			TreeNode LeftRoot = new TreeNode();
    			LeftRoot.data = pre[pre_start + 1]; //左根节点
    			root.left = ConstructBTree(LeftRoot, pre , pre_start + 1, pre_start + Left_Length, inorder,
    					inorder_start , pos - 1);			
    		}
    		
    		if( Right_Length > 0) { //存在右子树
    			TreeNode RightRoot = new TreeNode();
    			RightRoot.data = pre[pre_start + Left_Length + 1]; //右根节点
    			root.right = ConstructBTree(RightRoot, pre , pre_start + Left_Length + 1 , pre_start + Left_Length
    					+ Right_Length - 1, inorder, pos + 1 , inorder_end);
    		}
    		
    		return root;		
    	}
    	
    	public static int FindPos(int num, int arr[]) {
    		int i = 0;
    		if(arr != null) {
    			while(arr[i] != num)
    				i++;
    			if(arr[i] == num)
    				return i;
    		}
    		
    		return -1;		
    	}
    	
    	/*后序遍历*/
    	public static void LastOrder(TreeNode head) {
    		if( head != null) {
    			LastOrder(head.left);
    			LastOrder(head.right);
    			System.out.println(head.data);
    		}
    	}
    	
    	
    	public static void main(String[] args) {
    		TreeNode tnode = RebuildBinaryTree();
    		LastOrder(tnode);
    	}
    }
    

    费了好半天劲才弄出来,有两点感想:

    1.如上图代码中被注释掉的打印语句一样,有时调试程序中的逻辑错误,尤其是令人头大的递归,添加打印语句比单步调试更为简单直白,不然,单步跟踪,调着调着就被绕进去了(智商不高,见谅!)

    2.虽然这次是参考着剑指offer上的答案弄出来的,但是还是颇有感触。一定要敢想,坚信一个道理:一切反动派都是纸老虎。尤其是递归,要注意函数的参数。有时候最简单的思路,往往容易被忽视。继续努力!


    今天晚上,在牛客网上做剑指offer的题的时候,发现其实自己之前写的代码还可以继续精简一点,看着思路更清晰。

    	package com.study;
    	
    	/*
    	 * 根据二叉树的前序遍历和中序遍历结果重建二叉树
    	 * 并输出其头节点。假设前序遍历和中序遍历结果中没有重复数字
    	 * 前序遍历序列:{1,2,4,7,3,5,6,8}
    	 * 中序遍历序列:{4,7,2,1,5,3,8,6}
    	 * **/
    	class TreeNode {
    		public int data;
    		public TreeNode left;
    		public TreeNode right;
    		
    		public TreeNode() {
    			
    		}
    	}
    
    
    	public class suanfa4 {
    		
    		private static int[] arr1 = {1,2,4,7,3,5,6,8};
    		private static int[] arr2 = {4,7,2,1,5,3,8,6};
    		public static TreeNode RebuildBinaryTree() {
    			TreeNode head = null;
    			//head = ConstructBTree( head ,arr1, 0, 7, arr2, 0, 7);
    			head = ConstructBTree(arr1, 0, 7, arr2, 0, 7);
    			return head;
    		}
    		
    		public static TreeNode ConstructBTree(int[] pre, int pre_start, int pre_end,
    				int[] inorder, int inorder_start, int inorder_end) {
    			if(pre_start > pre_end || pre_end > pre.length) 
    				return null; 
    			TreeNode root = new TreeNode();
    			root.data = pre[pre_start]; //找到根节点
    			root.left = root.right = null;
    	
    			int pos = FindPos(root.data, inorder); //在中序遍历的数组中找到根节点的位置
    			int Left_Length = pos - inorder_start;
    			int Right_Length = inorder_end - pos;
    			
    			if( Left_Length > 0) {   //存在左子树
    				root.left = ConstructBTree (pre , pre_start + 1, pre_start + Left_Length, inorder,
    						inorder_start , pos - 1);			
    			}
    			
    			if( Right_Length > 0) { //存在右子树
    				root.right = ConstructBTree(pre , pre_start + Left_Length + 1 , pre_start + Left_Length
    						+ Right_Length, inorder, pos + 1 , inorder_end);
    			}
    			
    			return root;		
    		}
    		
    		
    		
    		
    		public static int FindPos(int num, int arr[]) {
    			int i = 0;
    			if(arr != null) {
    				while(arr[i] != num)
    					i++;
    				if(arr[i] == num)
    					return i;
    			}
    			
    			return -1;		
    		}
    		
    		/*后序遍历*/
    		public static void LastOrder(TreeNode head) {
    			if( head != null) {
    				LastOrder(head.left);
    				LastOrder(head.right);
    				System.out.println(head.data);
    			}
    		}
    		
    		
    		public static void main(String[] args) {
    			TreeNode tnode = RebuildBinaryTree();
    			LastOrder(tnode);
    		}
    	}
  • 相关阅读:
    Linux:闪光的宝石,智慧 (在)
    采用jqueryUI创建日期选择器
    C++学习笔记9-运算符重载
    spring mvc综合easyui点击上面菜单栏中的菜单项问题
    TCP拥塞控制 (1)
    牛顿迭代法
    【6】和作为连续序列s
    动态规划-简介
    约瑟夫环问题
    j简单的递归
  • 原文地址:https://www.cnblogs.com/xuehanlee/p/4615293.html
Copyright © 2020-2023  润新知