【剑指offer】重建二叉树&&二叉树的递归与非递归遍历
2017-03-05 22:55
746 查看
前序遍历:先根节点,左子结点,右子节点。
中序遍历:先左子节点,根节点,右子节点。
后序遍历:先左子结点,右子节点,根节点。
题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
中序遍历:先左子节点,根节点,右子节点。
后序遍历:先左子结点,右子节点,根节点。
题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
import java.util.Stack; class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } public class Solution { public TreeNode reConstructBinaryTree(int [] pre,int [] in) { return reConTree(pre,0,pre.length-1,in,0,in.length-1); } public TreeNode reConTree(int[] pre,int preleft, int preright,int[] in,int inleft,int inright){ if(preleft>preright||inleft>inright){ return null; } TreeNode root = new TreeNode(pre[preleft]); for(int i=inleft;i<=inright;i++){ if(pre[preleft]==in[i]){ //构建左子树,区间长度为(i-inleft),先序区间为[preleft+1,preleft+(i-inleft)],中序区间为[inleft,i-1] root.left=reConTree(pre,preleft+1,preleft+(i-inleft),in,inleft,i-1); //构建右子树,区间长度为(inright-i),先序区间为[左子树右区间+1,先序右区间末],中序区间为[i+1,inright]; root.right=reConTree(pre,preleft+(i-inleft)+1,preright,in,i+1,inright); } } return root; } /** * 递归遍历二叉树 * @param node */ public static void traverseBinTree(TreeNode node){ if (node==null){ return; } //System.out.println(node.val); //前序遍历 if(node.left!=null){ traverseBinTree(node.left); } //System.out.println(node.val); //中序遍历 if(node.right!=null){ traverseBinTree(node.right); } System.out.println(node.val); //后序遍历 } /** * 非递归版先序遍历 * * 即对于任一结点,其可看做是根结点,因此可以直接访问。 * 访问完之后,若其左孩子不为空,按相同规则访问它的左子树 * 当访问其左子树时,再访问它的右子树。 * * @param node */ public static void preOrder(TreeNode node){ Stack<TreeNode> tree = new Stack<TreeNode>(); while(node!=null || !tree.empty()){ while(node!=null){ System.out.println(node.val); tree.push(node); node = node.left; } if(!tree.empty()){ node = tree.pop(); node = node.right; } } } /** * 非递归版中序遍历 * * 对于任一结点,优先访问其左孩子,而左孩子结点又可以看做一根结点。 * 然后继续访问其左孩子结点,直到遇到左孩子结点为空的结点才进行访问。 * 按相同的规则访问其右子树。 * * @param node */ public static void inOrder(TreeNode node){ Stack<TreeNode> tree = new Stack<TreeNode>(); while(node!=null || !tree.empty()){ while(node!=null){ tree.push(node); node = node.left; } if(!tree.empty()){ node = tree.pop(); System.out.println(node.val); node = node.right; } } } /** * 非递归版后序遍历1 * * 要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。 * 如果P不存在左孩子和右孩子,则可以直接访问它; * 或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。 * 若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候。 * 左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。 * * @param node */ public static void postOrder(TreeNode node){ Stack<TreeNode> tree = new Stack<TreeNode>(); TreeNode pre = null; //前一个访问的节点 TreeNode cur ; //当前节点 tree.push(node); while(!tree.empty()){ cur = tree.peek(); //访问栈顶元素 //如果当前结点没有孩子结点(情况一)或者孩子节点都已被访问过 (情况二)[pre!=null] if((cur.left==null&&cur.right==null)||(pre!=null&&(pre==cur.left||pre==cur.right))){ System.out.println(cur.val); tree.pop(); pre = cur; }else{ //注意入栈先后顺序,右子节点点先入栈 if(cur.right!=null){ tree.push(cur.right); } if(cur.left!=null){ tree.push(cur.left); } } } } /** * 非递归版后序遍历2 * * 对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点。 * 此时该结点出现在栈顶,但是此时不能将其出栈并访问,因此其右孩子还为被访问。 * 所以接下来按照相同的规则对其右子树进行相同的处理。 * 当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。 * * @param node */ public static void postOrder2(TreeNode node){ Stack<TreeNode> tree = new Stack<TreeNode>(); Stack<Integer> counts = new Stack<Integer>(); Integer i = new Integer(1); while(node != null || !tree.empty()){ while(node!=null){ tree.push(node); counts.push(new Integer(0)); node = node.left; } while(!tree.empty()&&counts.peek().equals(i)){ counts.pop(); System.out.println(tree.pop().val); } if(!tree.empty()){ counts.pop(); counts.push(new Integer(1)); //标记有访问右孩子 node = tree.peek(); node = node.right; } } } public static void main(String[] args) { int[] pre = new int[]{1,2,4,7,3,5,6,8}; int[] in = new int[]{4,7,2,1,5,3,8,6}; TreeNode tree = new Solution().reConstructBinaryTree(pre, in); postOrder(tree); } }
相关文章推荐
- 牛客_剑指offer_重建二叉树,再后续遍历_递归思想_分两端
- 剑指offer面试题6——重建二叉树(递归)
- 剑指offer-->面试题6 重建二叉树
- 【剑指Offer】重建二叉树 解题报告(Java & Python)
- 【剑指Offer】面试招聘题目2:重建二叉树
- 剑指offer:6-重建二叉树
- 【剑指Offer面试编程题】题目1385:重建二叉树--九度OJ
- 【剑指offer】链表相关-合并两个有序链表&递归写法17
- 剑指offer 面试题6 重建二叉树
- [剑指offer]重建二叉树
- 【剑指offer】重建二叉树
- 九度Online Judge | 剑指Offer | 重建二叉树
- 【剑指Offer面试编程题】题目1385:重建二叉树--九度OJ
- 剑指offer面试题6 重建二叉树(java)
- 剑指offer面试题6--重建二叉树
- 【九度OJ1385】|【剑指offer6】重建二叉树
- 剑指Offer - 九度1385 - 重建二叉树
- 【剑指offer】题目1385:重建二叉树
- 重建二叉树(剑指offer6、编程之美3.9)