二叉树的深度和广度优先遍历

简介

二叉树有两种存储方式,分别是顺序存储和链式存储。遍历算法的作用就是讲非线性结构转为线性结构,分为深度优先遍历和广度优先遍历。

深度优先遍历

深度优先遍历算法又分为三种,分别是前序遍历,中序遍历和后序遍历。这个前中后序指的是遍历根节点的顺序。依照下图:解决三种遍历方式的算法都可以用递归或者迭代法去实现,在二叉树或者链表的算法问题中,推荐使用递归去解决问题,当然递归的问题是思考起来会难一点,不易形成思路。迭代法的好处是符合正常思维,考虑起来简单,代码量会多一点。

  • 前序遍历:ABCDEFGHK
  • 中序遍历:BDCAEHGKF
  • 后续遍历:DCBHKGFEA

二叉树

前序遍历

根结点——> 左节点——>右节点

ABCDEFGHK

    /**
     * L144 二叉树的前序遍历
     *
     * 迭代法
     *
     * @param root
     * @return
     */
    public List<Integer> preorderTraversal2(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode curNode = root;
        while (curNode != null || !stack.isEmpty()) {
            while (curNode != null) {              
                //沿途的值全部添加到结果,
                result.add(curNode.val);
                //查到最左边的子节点,沿途经过的节点全部压栈,后面用。
                stack.push(curNode);
                curNode = curNode.left;
            }
            //左边无节点的话,找到上一个节点的右节点,继续判断即可。
            curNode = stack.pop().right;
        }

        return result;
    }

    /**
     * L144 二叉树的前序遍历
     *
     * 递归
     *
     * @param root
     * @return
     */
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        preorderTraversal(root, result);
        return result;
    }

    private void preorderTraversal(TreeNode root, List<Integer> result) {
        // 添加根节点的值
        result.add(root.val);
        //添加左节点的值
        if (root.left != null) {
            preorderTraversal(root.left, result);
        }
        //添加右节点的值
        if (root.right != null) {
            preorderTraversal(root.right, result);
        }
    }

中序遍历

左结点——> 根节点——>右节点

BDCAEHGKF

 /**
     * L94 二叉树的中序遍历
     *
     * 循环法:空间复杂度o(n), 时间复杂度o(n)
     *
     * @param root
     * @return
     */
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<> ();
        TreeNode curNode = root;
        while(!stack.isEmpty() || curNode != null) {
            while (curNode != null) {
                stack.push(curNode);
                curNode = curNode.left;
            }
            curNode = stack.pop();
            result.add(curNode.val);
            curNode = curNode.right;
        }
        return result;
    }

    /**
     * L94 二叉树的中序遍历
     * 递归法  时间复杂度o(n), 空间复杂度最坏o(n)
     *
     * @param root
     * @return
     */
    public List<Integer> inorderTraversal2(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        traversal(root, result);
        return result;
    }

    private void traversal(TreeNode root, List<Integer> result) {
        if (root.left != null) {
            result.addAll(inorderTraversal2(root.left));
        }
        result.add(root.val);
        if (root.right != null) {
            result.addAll(inorderTraversal2(root.right));
        }
    }

后序遍历

左结点——> 右节点——>根节点

DCBHKGFEA

/**
     * L145 二叉树的后序遍历
     *
     * @param root
     * @return
     */
    public List<Integer> postorderTraversal2(TreeNode root) {
        LinkedList<Integer> result = new LinkedList<>();
        if (root == null) {
            return result;
        }
        LinkedList<TreeNode> stack = new LinkedList<>();
        stack.push(root);
        while (!stack.isEmpty()) {
           TreeNode node = stack.pollLast();
           result.addFirst(node.val);
           if (node.left != null) {
               stack.add(node.left);
           }
           if (node.right != null) {
               stack.add(node.right);
           }
        }

        return result;
    }

    /**
     * L145 二叉树的后序遍历
     *
     * @param root
     * @return
     */
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        postorderTraversal(root, result);
        return result;
    }

    public void postorderTraversal(TreeNode root, List<Integer> result) {
        if (root.left != null) {
            postorderTraversal(root.left, result);
        }
        if (root.right != null) {
            postorderTraversal(root.right, result);
        }
        result.add(root.val);
    }

广度优先搜索

   /**
     * 广度优先遍历
     */
    public List<Integer> breadthFirst(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        LinkedList<TreeNode> linkedList = new LinkedList<>();
        linkedList.offer(root);
        result.add(root.val);
        while (!linkedList.isEmpty()) {
            TreeNode top = linkedList.poll();
            if (top.left != null) {
                linkedList.offer(top.left);
                result.add(top.left.val);
            }
            if (top.right != null) {
                linkedList.offer(top.right);
                result.add(top.right.val);
            }
        }
        return result;
    }

总结

二叉树因其特性,子树也是个二叉树。所以很多问题,都可以通过递归的方式解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值