剑指offer四之重建二叉树
一、题目:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
二、解题思路:
如果理解了递归的访问,那么建树的过程就容易多了,前序遍历序列的第一个数(后序遍历的最后一个数)一定是根结点,所以可以根据此结点在中序序列中的位置把中序序列分为左子树和右子数两个部分,同样的道理,在左子树和右子数中同样可以用到这样的规律来确定每个中间结点。
三、代码
1、重建二叉树
public class ReConstructBinaryTree { public TreeNode reConstructBinaryTree(int[] pre, int[] in) { TreeNode root = new TreeNode(pre[0]);//前序的第一个数定为根 int len = pre.length; //当只有一个数的时候 if (len == 1) { root.left = null; root.right = null; return root; } //找到中序中的根位置 int rootval = root.val; int i; for (i = 0; i < len; i++) { if (rootval == in[i]) break; } //创建左子树 if (i > 0) { int[] pr = new int[i]; int[] ino = new int[i]; for (int j = 0; j < i; j++) { pr[j] = pre[j + 1]; } for (int j = 0; j < i; j++) { ino[j] = in[j]; } root.left = reConstructBinaryTree(pr, ino); } else { root.left = null; } //创建右子树 if (len - i - 1 > 0) { int[] pr = new int[len - i - 1]; int[] ino = new int[len - i - 1]; for (int j = i + 1; j < len; j++) { ino[j - i - 1] = in[j]; pr[j - i - 1] = pre[j]; } root.right = reConstructBinaryTree(pr, ino); } else { root.right = null; } return root; } }
2、二叉树的节点类
/** * Definition for binary tree */ public class TreeNode { int val; TreeNode left; TreeNode right; public TreeNode(){ } public TreeNode(int x) { val = x; } public TreeNode(int val, TreeNode left, TreeNode right) { this.val = val; this.left = left; this.right = right; } //以下是getter和setter方法 public int getVal() { return val; } public void setVal(int val) { this.val = val; } public TreeNode getLeft() { return left; } public void setLeft(TreeNode left) { this.left = left; } public TreeNode getRight() { return right; } public void setRight(TreeNode right) { this.right = right; } }
3、遍历重构的二叉树
public class Traversal { public void theFirstTraversal(TreeNode root){ //先序遍历 //输出根节点 printRoot(root); //遍历左孩子 if(root.getLeft()!=null){ theFirstTraversal(root.getLeft()); } //遍历右孩子 if(root.getRight()!=null){ theFirstTraversal(root.getRight()); } } public void theInOrderTraversal(TreeNode root) { //中序遍历 //遍历左孩子 if (root.getLeft() != null) { theInOrderTraversal(root.getLeft()); } //输出根节点 printRoot(root); //遍历右孩子 if (root.getRight() != null) { theInOrderTraversal(root.getRight()); } } public void thePostOrderTraversal(TreeNode root) { //后序遍历 //遍历左孩子 if (root.getLeft() != null) { thePostOrderTraversal(root.getLeft()); } //遍历右孩子 if(root.getRight() != null) { thePostOrderTraversal(root.getRight()); } //输出根节点 printRoot(root); } public void printRoot(TreeNode root){ //输出根加点的值 System.out.print(root.val+","); } }
4、主方法
public class TestMain { public static void main(String[] args) { int[] pre={1,2,4,7,3,5,6,8}; //前序遍历的结果 int[] in={4,7,2,1,5,3,8,6}; //中序遍历的结果 //重建的二叉树 ReConstructBinaryTree re=new ReConstructBinaryTree(); TreeNode root=re.reConstructBinaryTree(pre,in); //二叉树的遍历 Traversal traversal=new Traversal(); traversal.theFirstTraversal(root);//前序遍历 System.out.println(); traversal.theInOrderTraversal(root);//中序遍历 System.out.println(); traversal.thePostOrderTraversal(root);//后序遍历 } }
-----------------------------------------------------------------------------------------------------------------------------------
参考了的文章链接:
http://blog.csdn.net/qq_23217629/article/details/51718996