zoukankan      html  css  js  c++  java
  • 【力扣】104. 二叉树的最大深度-及二叉树的遍历方式

    给定一个二叉树,找出其最大深度。

    二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

    说明: 叶子节点是指没有子节点的节点。

    示例:
    给定二叉树 [3,9,20,null,null,15,7],

    3
    /
    9 20
    /
    15 7
    返回它的最大深度 3 。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree

    public class TreeNode {
    
    
    
        public int val;
        public TreeNode left;
        public TreeNode right;
    
        public TreeNode(int x) {
            val = x;
        }
        
    }

    解法1:递归

    public int maxDepth(TreeNode root) {
            if (root == null){
                return 0;
            }
            return Math.max(maxDepth(root.left),maxDepth(root.right)) + 1;
        }

    借此学习下二叉树的遍历方法:

    二叉树有两种遍历方式,第一种是深度优先遍历算法,深度优先又分为前序遍历、中序遍历、后序遍历,第二种是广度优先遍历算法,也就是层次遍历

    前序遍历:1  2  4  5  7  8  3  6 

    中序遍历:4  2  7  5  8  1  3  6

    后序遍历:4  7  8  5  2  6  3  1

    层次遍历:1  2  3  4  5  6  7  8

    深度优先:

    深度优先中的前序遍历:根结点 ---> 左子树 ---> 右子树
    /**
         * 二叉树的深度优先遍历算法中的前序遍历 (递归)
         */
        public List preOrder(TreeNode root) {
            if (root == null){
                return null;
            }
            List<Integer> list = new ArrayList<>();
            search(list,root);
            return list;
        }
    
        public void search(List<Integer> list,TreeNode root){
            if (root != null){
                list.add(root.val);
                search(list,root.left);
                search(list,root.right);
            }
        }
    /**
         * 二叉树的深度优先遍历算法中的前序遍历 使用栈
         *
         */
        public List preOrderUseStack(TreeNode root) {
            if (root == null){
                return null;
            }
            List<Integer> list = new ArrayList<>();
            Stack<TreeNode> stack = new Stack();   //也可以用栈实现 栈的特性是先进后出
            stack.push(root);
    
            //若栈不空
            while(!stack.isEmpty()){
                //取出响应的节点
                TreeNode node=stack.pop();
                list.add(node.val);
    
                //考虑到先进后出的特性,所以先放右子节点
                if(node.right!=null){
                    stack.push(node.right);
                }
                if(node.left!=null){
                    stack.push(node.left);
                }
            }
            return list;
        }

     

    深度优先中的中序遍历:左子树 --->根结点 --->  右子树
    /**
         * 中序遍历
         */
        public List centerOrderUseStack(TreeNode root) {
            if (root == null){
                return null;
            }
            List<Integer> list = new ArrayList<>();
            Stack<TreeNode> stack = new Stack();   //也可以用栈实现 栈的特性是先进后出
            TreeNode currentNode = root;
    
            //若栈不空
            while(currentNode != null || !stack.isEmpty()){
                while(currentNode != null){
                    stack.push(currentNode);
                    currentNode = currentNode.left;
                }
                //取出响应的节点
                currentNode=stack.pop();
                list.add(currentNode.val);
                currentNode = currentNode.right;
            }
            return list;
        }
    深度优先中的后序遍历:左子树--->  右子树 --->根结点 
    /**
         * 后序遍历,后序遍历的特殊点在于我们要最后获取到根节点  还是很复杂的!!!!!!
         */
        public List afterWordUseStack(TreeNode root) {
            if (root == null){
                return null;
            }
            List<Integer> list = new ArrayList<>();
            Stack<TreeNode> stack = new Stack();   //也可以用栈实现 栈的特性是先进后出
            TreeNode currentNode = root;
            TreeNode rightNode = null;
            //若栈不空
            while(currentNode != null || !stack.isEmpty()){
                //一直循环到最左端的叶子结点(currentNode是null)
                while(currentNode != null){
                    stack.push(currentNode);
                    currentNode = currentNode.left;
                }
                //取出相应的节点
                currentNode=stack.pop();
                //若右节点是空,或者 当前节点的右节点为右节点  这样循环完成可以得到currentNode 父节点
                while(currentNode.right == null || currentNode.right == rightNode){
                    list.add(currentNode.val);
                    rightNode = currentNode; // 设置右节点为当前节点
    
                    if (stack.isEmpty()){
                        return list;
                    }
                    currentNode=stack.pop();
                }
                stack.push(currentNode); //还有右结点没有遍历
                currentNode = currentNode.right;
            }
            return list;
        }

    后序遍历的更方便理解的一种方式(上面那种写完之后我都不记得了):

    /**
         * 后序遍历,后序遍历的特殊点在于我们要最后获取到根节点  还是很复杂的!!!!!!
         */
        public List afterWordUseStackEasy(TreeNode root) {
            if (root == null){
                return null;
            }
            List<Integer> list = new ArrayList<>();
            Stack<TreeNode> stack = new Stack();   //也可以用栈实现 栈的特性是先进后出
            TreeNode currentNode = null;
            TreeNode preNode = null;
            stack.push(root);
            //若栈不空
            while(!stack.isEmpty()){
                currentNode = stack.peek();
                if ((currentNode.left == null && currentNode.right == null) || (preNode != null && (preNode == currentNode.left || preNode == currentNode.right))){
                    stack.pop();
                    list.add(currentNode.val);
                    preNode = currentNode;
                } else {
                    if (currentNode.right != null){
                        stack.push(currentNode.right);
                    }
                    if (currentNode.left != null){
                        stack.push(currentNode.left);
                    }
                }
            }
            return list;
        }

    广度优先:

    /**
         * 广度优先遍历 又称层级遍历 需要借助数据结构 : 队列
         */
        public List spanUseStack(TreeNode root) {
            if (root == null){
                return null;
            }
    
            //队列的特性为:先进先出
            ArrayDeque<TreeNode> deque = new ArrayDeque<TreeNode>();
            List<Integer> list = new ArrayList<>();
            deque.add(root);
    
            while(!deque.isEmpty()){
                TreeNode current = deque.remove();
                list.add(current.val);
                if (current.left != null){
                    deque.add(current.left);
                }
                if (current.right != null){
                    deque.add(current.right);
                }
            }
            return list;
        }

    二叉树层级遍历(打印层级):

    public Node connect(Node root) {
            if(root == null){
                return root;
            }
            Deque<Node> deque = new LinkedList<Node>();
            deque.offer(root);
            int count = 0;
            while(!deque.isEmpty()){
                count = deque.size();
                Node pre = null;
                while(count > 0){
                    Node node = deque.remove();
                    node.next = pre;
                    pre=node;
                    if(node.right != null){
                        deque.offer(node.right);
                    }
                    if(node.left != null){
                        deque.offer(node.left);
                    }
                    count--;
                }
            }
            return root;
        }
    一个入行不久的Java开发,越学习越感觉知识太多,自身了解太少,只能不断追寻
  • 相关阅读:
    Apache Ant 1.9.1 版发布
    Apache Subversion 1.8.0rc2 发布
    GNU Gatekeeper 3.3 发布,网关守护管理
    Jekyll 1.0 发布,Ruby 的静态网站生成器
    R语言 3.0.1 源码已经提交到 Github
    SymmetricDS 3.4.0 发布,数据同步和复制
    beego 0.6.0 版本发布,Go 应用框架
    Doxygen 1.8.4 发布,文档生成工具
    SunshineCRM 20130518发布,附带更新说明
    Semplice Linux 4 发布,轻量级发行版
  • 原文地址:https://www.cnblogs.com/fengtingxin/p/13393669.html
Copyright © 2011-2022 走看看