zoukankan      html  css  js  c++  java
  • 树的遍历,重建二叉树

    详见jiyangg.github.io(二叉树集锦)

    二叉树节点:

    class BinaryTreeNode {
        int val;
        BinaryTreeNode left;
        BinaryTreeNode right;
    
        public BinaryTreeNode(int val) {
            this.val = val;
        }
    }
    

    访问节点操作

    void visit(BinaryTreeNode node) {
        System.out.print(node.val + " ");
    }
    

    二叉树节点数目

    • 如果是空树:返回0
    • 如果不是空树:节点数 = (左子树节点数)+(右子数节点数) + 1
    int TreeNodeCount(BinaryTreeNode root) {
        if (root == null) {
            return 0;
        }
        return TreeNodeCount(root.left) + TreeNodeCount(root.right) + 1;
    }
    

    求二叉树深度

    • 如果是空树:返回0
    • 如果不是空树:深度 = Max(左子树深度,右子树深度) + 1
    int TreeDepth(BinaryTreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftDepth = TreeDepth(root.left);
        int rightDepth = TreeDepth(root.right);
        return leftDepth > rightDepth ? (leftDepth + 1) : (rightDepth + 1);
    }
    

    前序遍历

    • 如果是空树:return
    • 如果不是空树:根->左->右
    void preOrderTraverse(BinaryTreeNode root) {
        if (root == null) {
            return;
        }
        visit(root);                    //访问根节点
        preOrderTraverse(root.left);    //前序遍历左子树
        preOrderTraverse(root.right);   //前序遍历右子树
    }
    

    中序遍历

    • 如果是空树:return
    • 如果不是空树:左->根-右
    void inOrderTraverse(BinaryTreeNode root) {
        if (root == null) {
            return;
        }
        inOrderTraverse(root.left);     //中序遍历左子树
        visit(root);                    //访问根节点
        inOrderTraverse(root.right);    //中序遍历右子树
    }
    

    后序遍历

    • 如果是空树:return
    • 如果不是空树:左->右->根
    void postOrderTraverse(BinaryTreeNode root) {
        if (root == null) {
            return;
        }
        postOrderTraverse(root.left);    //后序遍历左子树
        postOrderTraverse(root.right);   //后序遍历右子树
        visit(root);                    //访问根节点
    }
    

    层序遍历(从上到下,从左到右)

    • 使用队列实现:
      • 队列初始化:将根节点入队
      • 当队列不为空:弹出一个节点,访问,若左节点或右节点不为空,将其入队
    void levelTraverse(BinaryTreeNode root){
        if (root == null) {
            return;
        }
        Queue<BinaryTreeNode> queue = new ArrayDeque<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            BinaryTreeNode node = queue.poll();
            visit(node);
                if (node.left != null) {
                    queue.add(node.left);
                }
                if (node.right != null) {
                    queue.add(node.right);
                }
            }
        }
    

    重建二叉树

    根据前序遍历和中序遍历的结果重建二叉树

    通过前序遍历的第一个元素为树的根找到根节点,然后在中序遍历中找到根节点的位置就能确定树的左右子树的节点数。

    BinaryTreeNode reConstructBinaryTree(int[] pre, int[] in) {
        if (pre == null || in == null || pre.length <= 0 || in.length <= 0) {
            return null;
        }
    	//储存根节点
        BinaryTreeNode root = new BinaryTreeNode(pre[0]);
        int rootPositionInOrder = -1;
    	//查找根节点在中序遍历的位置
        for (int i = 0; i < in.length; i++) {
            if (root.val == in[i]) {
                rootPositionInOrder = i;
                break;
            }
        }
        if (rootPositionInOrder == -1) {
            return null;
        }
    	//确定左子树节点数
        int numOfLeft = rootPositionInOrder;
    	//存储左子树前序遍历结果
        int[] leftPre = new int[numOfLeft];
        for (int i = 0; i < numOfLeft; i++) {
            leftPre[i] = pre[i + 1];
        }
    	//储存左子树中序遍历结果
        int[] leftIn = new int[numOfLeft];
        for (int i = 0; i < numOfLeft; i++) {
            leftIn[i] = in[i];
        }
    	//重建左子树
        root.left = reConstructBinaryTree(leftPre, leftIn);
    
    	//确定右子树节点数
        int numOfRight = in.length - numOfLeft - 1;
    	//储存右子树前序遍历结果
        int[] rightPre = new int[numOfRight];
        for (int i = 0; i < numOfRight; i++) {
            rightPre[i] = pre[i + numOfLeft + 1];
        }
    	//储存右子树中序遍历结果
        int[] rightIn = new int[numOfRight];
        for (int i = 0; i < numOfRight; i++) {
            rightIn[i] = in[i + numOfLeft + 1];
        }
    	//重建右子树
        root.right = reConstructBinaryTree(rightPre, rightIn);
    
        return root;
    }
    
  • 相关阅读:
    appium之adb常用命令
    测试基础之等价类
    selenium之CSS定位
    括号序列的最小代价
    Spark相对于MapReduce的优势
    Cache系统设计
    [京东2017实习生笔试] 终结者C
    [京东2017实习生笔试] 通过考试
    [hihoCoder] 1078. 线段树的区间修改
    [转载] 一步一步理解线段树
  • 原文地址:https://www.cnblogs.com/jiy-for-you/p/7309280.html
Copyright © 2011-2022 走看看