zoukankan      html  css  js  c++  java
  • 二叉树(一)

    求二叉树中的节点个数

    求二叉树的深度

    前序遍历

    中序遍历

    后序遍历

    分层遍历

    二叉树分层左右交替遍历(先从左到右,再从右到左,交替)

    求二叉树第K层的节点个数

    二叉树中叶子节点的个数

    判断两棵二叉树是否相同

    判断两个树是否互相镜像

    求二叉树的镜像

    求二叉树中的节点个数

    递归

    /**
     * 求二叉树中的节点个数递归解法: O(n) 
     * (1)如果二叉树为空,节点个数为0 
     * (2)如果二叉树不为空,二叉树节点个数 = 左子树节点个数 + 右子树节点个数 + 1
     */
    public int getNodeNumRec(TreeNode root) {
        if (root == null) {
            return 0;
        } else {
            return getNodeNumRec(root.left) + getNodeNumRec(root.right) + 1;
        }
    }

    迭代

    public int getNodeNum(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int count = 1;
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
        while (!queue.isEmpty()) {
            TreeNode node = queue.remove();
            if (node.left != null) {
                queue.add(node.left);
                count++;
            }
            if (node.right != null) {
                queue.add(node.right);
                count++;
            }
        }
        return count;
    }

     求二叉树的深度

    递归

    /**
     * 求二叉树的深度递归解法: O(n) 
     * (1)如果二叉树为空,二叉树的深度为0 
     * (2)如果二叉树不为空,二叉树的深度 = max(左子树深度, 右子树深度) + 1
     */
    public int getDepthRec(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int left = getDepthRec(root.left);
        int right = getDepthRec(root.right);
        return Math.max(left, right) + 1;
    }

    遍历

    public int getDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        
        int level = 0;
        int currentLevelNode = 1;
        int nextLevelNode = 0;
        
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
        while (!queue.isEmpty()) {
            TreeNode node = queue.remove();
            currentLevelNode--;
            if (node.left != null) {
                nextLevelNode++;
                queue.add(node.left);
            }
            if (node.right != null) {
                nextLevelNode++;
                queue.add(node.right);
            }
    
            if (currentLevelNode == 0) {
                level++;
                currentLevelNode = nextLevelNode;
                nextLevelNode = 0;
            }
        }
        return level;
    }

     前序遍历

    递归

    /**
     *  前序遍历递归解法: 
     * (1)如果二叉树为空,空操作 
     * (2)如果二叉树不为空:访问根节点,前序遍历左子树,前序遍历右子树
     */
    public void preorderTraversalRec(TreeNode root) {
        if (root == null) {
            return;
        }
        System.out.println(root.val);
        preorderTraversalRec(root.left);
        preorderTraversalRec(root.right);
    }
    
    //return list
    ArrayList<Integer> list = new ArrayList<>(); 
    public ArrayList<Integer> preorderTraversalRec(TreeNode root){
        if(root==null){
            return list;
        }
        list.add(root.val);
        preorderTraversalRec(root.left);
        preorderTraversalRec(root.right);
        return list;
    }

     非递归

    public ArrayList<Integer> preorderTraversal(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();  
        if (root == null) {
            return list;
        }
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode cur = stack.pop();
            list.add(cur.val);
    
            if (cur.right != null) {
                stack.push(cur.right);
            }
            if (cur.left != null) {
                stack.push(cur.left);
            }
        }
        return list;
    }

     中序遍历

     递归

    /**
     *  中序遍历递归解法 
     * (1)如果二叉树为空,空操作。 
     * (2)如果二叉树不为空:中序遍历左子树,访问根节点,中序遍历右子树
     */
    public void inorderTraversalRec(TreeNode root) {
        if (root == null) {
            return;
        }
        inorderTraversalRec(root.left);
        System.out.println(root.val);
        inorderTraversalRec(root.right);
    }

     非递归

    public static ArrayList<Integer> inorderTraversal(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();
        if (root == null) {
            return list;
        }
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode cur = root;
        while (true) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            
            if (stack.isEmpty()) {
                break;
            }
    
            cur = stack.pop();
            list.add(cur.val);
            cur = cur.right;
        }
        return list;
    }

     后序遍历

     递归

    public void postorderTraversalRec(TreeNode root) {
        if (root == null) {
            return;
        }
        postorderTraversal(root.left);
        postorderTraversal(root.right);
        System.out.println(root.val);
    }

     非递归

    public ArrayList<Integer> postorderTraversal(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();
        if (root == null) {
            return list;
        }
        Stack<TreeNode> s = new Stack<TreeNode>(); // 第一个stack用于添加node和它的左右孩子
        Stack<TreeNode> output = new Stack<TreeNode>();// 第二个stack用于翻转第一个stack输出
        s.push(root);
        while (!s.isEmpty()) { // 确保所有元素都被翻转转移到第二个stack
            TreeNode cur = s.pop(); 
            output.push(cur);
            // 把栈顶元素的左孩子和右孩子分别添加入第一个stack
            if (cur.left != null) { 
                s.push(cur.left);
            }
            if (cur.right != null) {
                s.push(cur.right);
            }
        }
    
        while (!output.isEmpty()) { // 遍历输出第二个stack,即为后序遍历
            list.add(output.pop().val);
        }
        return list;
    }

     分层遍历

     递归

    public ArrayList<ArrayList<Integer>> levelTraversalRec(TreeNode root) {
        ArrayList<ArrayList<Integer>> ret = new ArrayList<ArrayList<Integer>>();
        dfs(root, 0, ret);
        return ret;
    }
    private void dfs(TreeNode root, int level, ArrayList<ArrayList<Integer>> ret) {
        if (root == null) {
            return;
        }
        // 添加一个新的ArrayList表示新的一层
        if (level >= ret.size()) {
            ret.add(new ArrayList<Integer>());
        }
        ret.get(level).add(root.val); // 把节点添加到表示那一层的ArrayList里
        dfs(root.left, level + 1, ret); // 递归处理下一层的左子树和右子树
        dfs(root.right, level + 1, ret);
    }

     非递归

    public ArrayList<Integer> levelTraversal(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();
        if (root == null) {
            return list;
        }
        
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
        while (!queue.isEmpty()) {
            TreeNode cur = queue.remove();
            list.add(cur.val);
            if (cur.left != null) {
                queue.add(cur.left);
            }
            if (cur.right != null) {
                queue.add(cur.right);
            }
        }
        return list;
    }

     

     二叉树分层左右交替遍历(先从左到右,再从右到左,交替) 

    public ArrayList<ArrayList<Integer>> zigzagLevelOrder(TreeNode root) {
        ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
        if(root == null){
            return result;
        }
        
        // 出栈顺序是从左到右
        Stack<TreeNode> leftstack = new Stack<TreeNode>();
        leftstack.push(root);
        
        // 出栈顺序是从右到左
        Stack<TreeNode> rightstack = new Stack<TreeNode>();
        
        boolean left = true;
        
        while(!leftstack.empty() || !rightstack.empty()){
            ArrayList<Integer> list = new ArrayList<Integer>();
            
            if(left){
                int size = leftstack.size();
                for(int i=0; i<size; i++){
                    TreeNode node = leftstack.pop();
                    list.add(node.val);
                    if(node.left!=null){
                        rightstack.push(node.left);
                    }
                    if(node.right!=null){
                        rightstack.push(node.right);
                    }
                }
            }else{
                int size = rightstack.size();
                for(int i=0;i<size;i++){
                    TreeNode node = rightstack.pop();
                    list.add(node.val);
                    if(node.right!=null){
                        leftstack.push(node.right);
                    }
                    if(node.left!=null){
                        leftstack.push(node.left);
                    }
                }
            }
            
            left=!left;
            result.add(list);
        }
        return result;
    } 

     求二叉树第K层的节点个数

     递归:求以root为根的第k层节点数目 == 求以root.left 为根的k-1层(因为少了root那一层)节点数目 + 以root.right 为根的k-1层节点数目

    /**
     *  求二叉树第K层的节点个数 递归解法: 
     * (1)如果二叉树为空或者k<1返回0 
     * (2)如果二叉树不为空并且k==1,返回1 
     * (3)如果二叉树不为空且k>1,返回root左子树中k-1层的节点个数与root右子树k-1层节点个数之和
     */
    public int getNodeNumKthLevelRec(TreeNode root, int k) {
        if (root == null || k < 1)
            return 0;
        if (k == 1) 
            return 1;
    int numLeft = getNodeNumKthLevelRec(root.left, k - 1); int numRight = getNodeNumKthLevelRec(root.right, k - 1); return numLeft + numRight; }

     非递归

    // 与求二叉树深度迭代方法一样
    public int getNodeNumKthLevel(TreeNode root, int k) {
        if (root == null) {
            return 0;
        }
    
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        int i = 0;
        int currentLevelNodes = 1;
        int nextLevelNodes = 0;
    
        queue.add(root);
        while (!queue.isEmpty() && i < k) {
            TreeNode cur = queue.remove();
            currentLevelNodes--;
            if (cur.left != null) {
                queue.add(cur.left);
                nextLevelNodes++;
            }
            if (cur.right != null) {
                queue.add(cur.right);
                nextLevelNodes++;
            }
    
            if (currentLevelNodes == 0) { 
                currentLevelNodes = nextLevelNodes;
                nextLevelNodes = 0;
                i++;
            }
        }
        return currentLevelNodes;
    }

     

     二叉树中叶子节点的个数

     递归

    public int getNodeNumLeafRec(TreeNode root) {
        if (root == null)
            return 0;
        if (root.left == null && root.right == null)
            return 1;
        
        return getNodeNumLeafRec(root.left) + getNodeNumLeafRec(root.right);
    }

     非递归

    // 基于分层遍历方法
    public int getNodeNumLeaf(TreeNode root) {
        if (root == null) {
            return 0;
        }
    
        int leafNodes = 0;
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
    
        while (!queue.isEmpty()) {
            TreeNode cur = queue.remove();
            if (cur.left != null) {
                queue.add(cur.left);
            }
            if (cur.right != null) {
                queue.add(cur.right);
            }
            if (cur.left == null && cur.right == null) {
                leafNodes++;
            }
        }
        return leafNodes;
    }

     

     判断两棵二叉树是否相同

     递归

    /**
     *  判断两棵二叉树是否相同的树。 递归解法: 
     * (1)如果两棵二叉树都为空,返回真 
     * (2)如果两棵二叉树一棵为空,另一棵不为空,返回假
     * (3)如果两棵二叉树都不为空,如果对应的左子树和右子树都相同返回真,其他返回假
     */
    public boolean isSameRec(TreeNode t1, TreeNode t2){
        if(t1==null && t2==null){
            return true;
        }
        if(t1==null || t2==null){
            return false;
        }
        if(t1.val==t2.val){
            return isSameRec(t1.left, t2.left) && isSameRec(t2.right, t2.right);
        }
        return false;
    }

     非递归

    /**
     *  判断两棵二叉树是否相同的树(迭代) 遍历一遍即可,这里用preorder
     */
    public boolean isSame(TreeNode r1, TreeNode r2) {
        if (r1 == null && r2 == null) {
            return true;
        } else if (r1 == null || r2 == null) {
            return false;
        }
    
        Stack<TreeNode> s1 = new Stack<TreeNode>();
        Stack<TreeNode> s2 = new Stack<TreeNode>();
        s1.push(r1);
        s2.push(r2);
    
        while (!s1.isEmpty() && !s2.isEmpty()) {
            TreeNode node1 = s1.pop();
            TreeNode node2 = s2.pop();
            if (node2 == null && node1 == null) {
                continue;
            } else if (node1 != null && node2 != null && node1.val == node2.val) {
                s1.push(node1.right);
                s1.push(node1.left);
                s2.push(node2.right);
                s2.push(node2.left);
            } else {
                return false;
            }
        }
        return true;
    }

     

     判断两个树是否互相镜像

    public boolean isMirrorRec(TreeNode r1, TreeNode r2) {
        if (r1 == null && r2 == null) {
            return true;
        }
        if (r1 == null || r2 == null) {
            return false;
        }
    
        if (r1.val != r2.val) {
            return false;
        }
    
        return isMirrorRec(r1.left, r2.right) && isMirrorRec(r1.right, r2.left);
    }

     

     求二叉树的镜像

     递归

    public TreeNode mirrorCopyRec(TreeNode root) {
        if (root == null) {
            return null;
        }
    
        TreeNode newNode = new TreeNode(root.val);
        newNode.left = mirrorCopyRec(root.right);
        newNode.right = mirrorCopyRec(root.left);
        return newNode;
    }

     非递归

    // 1. 破坏原来的树,把原来的树改成其镜像
    public void mirror(TreeNode root) {
        if (root == null) {
            return;
        }
    
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode cur = stack.pop();
    
            TreeNode temp = cur.left;
            cur.right = cur.left;
            cur.left = temp;
    
            if (cur.right != null) {
                stack.push(cur.right);
            }
            if (cur.left != null) {
                stack.push(cur.left);
            }
        }
    }
    
    // 2. 不破坏原来的树,返回一个新的镜像树
    public static TreeNode mirrorCopy(TreeNode root) {
        if (root == null) {
            return root;
        }
    
        Stack<TreeNode> stack = new Stack<TreeNode>();
        Stack<TreeNode> newStack = new Stack<TreeNode>();
        stack.push(root);
        TreeNode newRoot = new TreeNode(root.val);
        newStack.push(newRoot);
    
        while (!stack.isEmpty()) {
            TreeNode cur = stack.pop();
            TreeNode newCur = newStack.pop();
    
            if (cur.right != null) {
                stack.push(cur.right);
                newCur.left = new TreeNode(cur.right.val);
                newStack.push(newCur.left);
            }
            if (cur.left != null) {
                stack.push(cur.left);
                newCur.right = new TreeNode(cur.left.val);
                newStack.push(newCur.right);
            }
        }
        return newRoot;
    }
  • 相关阅读:
    P3834 【模板】可持久化线段树 (静态主席树)
    P3834 【模板】可持久化线段树 (静态主席树)
    2019 南昌网络赛 I. Max answer
    Linux从入门到精通——系统的进程
    Linux从入门到精通——文件权限
    Linux从入门到精通——命令行使用技巧
    Linux从入门到精通——Linux系统的文件及其管理
    Linux从入门到精通——vim及管理输入输出
    Linux从入门到精通——用户管理
    thiny mission 2021 10 15
  • 原文地址:https://www.cnblogs.com/hesier/p/5572869.html
Copyright © 2011-2022 走看看