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开发,越学习越感觉知识太多,自身了解太少,只能不断追寻
  • 相关阅读:
    Java 数组
    【转】Centos 设置IP地址的几种方式
    【转】CentOS 使用yum命令安装出现错误提示”could not retrieve mirrorlist http://mirrorlist.centos.org ***”
    【转】CentOS图形界面的开启与关闭
    【转】linux Centos 6.5 安装桌面环境GNOME
    VirtualBox 更改主机和虚拟机之间的鼠标切换热键
    【转】Virtualbox虚拟机配置安装CentOS 6.5图文教程
    0622 python 基础05
    0617 python 基础04
    0610 python 基础03
  • 原文地址:https://www.cnblogs.com/fengtingxin/p/13393669.html
Copyright © 2011-2022 走看看