Loading

【力扣】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;
    }

 

posted @ 2020-07-28 20:32  冯廷鑫  阅读(255)  评论(0编辑  收藏  举报