广度优先搜索

Posted 浮云神码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了广度优先搜索相关的知识,希望对你有一定的参考价值。

    这是关于广度优先搜索的第二遍文章,本次会分享两个LeetCode题目。和上一篇使用队列来实现广度优先搜索的方式不同,本次使用到了栈来实现广度优先搜索。


103. 二叉树的锯齿形层序遍历

import java.util.*;
/** * https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal * 103. 二叉树的锯齿形层序遍历 * 难度 中等 * 给定一个二叉树,返回其节点值的锯齿形层序遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 * * 例如: * 给定二叉树[3,9,20,null,null,15,7], * * 3 * / \ * 9 20 * / \ * 15 7 * 返回锯齿形层序遍历如下: * * [ * [3], * [20,9], * [15,7] * ] * * 来源:力扣(LeetCode) * 链接:https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal */public class ZigZagLevelOrderTree {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) { List<List<Integer>> result = new ArrayList<>(); if (root == null) { return result; } /** * 利用栈【先进后出】的特性来实现二叉树的锯齿形遍历 * 两个栈 * 1. 从左向右遍历的栈 * 2. 从右向左遍历的栈 */ Stack<TreeNode> leftToRightStack = new Stack<>(); Stack<TreeNode> rightToLeftStack = new Stack<>(); leftToRightStack.add(root); while(!leftToRightStack.isEmpty() || !rightToLeftStack.isEmpty()) { // 每次遍历只有一个栈中存在数据, 下面的代码保证了这一点 boolean leftFlag = !leftToRightStack.isEmpty(); List<Integer> currentLevelList = new ArrayList<>(); if (leftFlag) { while (!leftToRightStack.isEmpty()) { // leftToRightStack每pop一条数据, 就将左子节点、右子节点依次压入rightToLeftStack中 // 这样在处理rightToLeftStack时, 就可以从右向左处理节点了 TreeNode current = leftToRightStack.pop(); if (current.left != null) { rightToLeftStack.push(current.left); } if (current.right != null) { rightToLeftStack.push(current.right); } currentLevelList.add(current.val); } } else { while (!rightToLeftStack.isEmpty()) { // 同理, rightToLeftStack每pop一条数据, 就将右子节点、左子节点依次压入leftToRightStack中 // 这样在处理leftToRightStack时, 就可以从左向右处理节点了 TreeNode current = rightToLeftStack.pop(); if (current.right != null) { leftToRightStack.push(current.right); } if (current.left != null) { leftToRightStack.push(current.left); } currentLevelList.add(current.val); } } result.add(currentLevelList); } return result; }}

107. 二叉树的层序遍历 II

import java.util.*;
/** * https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii * 107. 二叉树的层序遍历 II * 给定一个二叉树,返回其节点值自底向上的层序遍历。(即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历) * * 例如: * 给定二叉树 [3,9,20,null,null,15,7], * * 3 * / \ * 9 20 * / \ * 15 7 * 返回其自底向上的层序遍历为: * * [ * [15,7], * [9,20], * [3] * ] * * 来源:力扣(LeetCode) * 链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii */public class LevelOrderBottomTree {
public List<List<Integer>> levelOrderBottom(TreeNode root) { List<List<Integer>> result = new ArrayList<>(); if (root == null) { return result; } /** * 使用栈临时存储结果, 按照先进后出的规则, 后面将栈元素依次取出存入最终结果即可 */ Stack<List<Integer>> tempResult = new Stack<>();
/** * 以下步骤就和【102. 二叉树的层序遍历】一样 * 广度优先搜索 借助【队列】来实现 */ Queue<TreeNode> queue = new LinkedList<>(); queue.add(root);
while (!queue.isEmpty()) { /** * size为当前队列的长度(即当前层级的元素个数), 有以下两个作用 * 1. 设置存储最终结果的List的长度 * 2. 决定for循环的次数, 初始长度决定了本次while循环应该获取多少个元素 */ int size = queue.size(); List<Integer> levelList = new ArrayList<>(); for (int i = 0; i < size; i++) { TreeNode current = queue.remove(); // 将当前元素的左右子节点依次加入队列, 实现从左到右访问 if (current.left != null) { queue.add(current.left); } if (current.right != null) { queue.add(current.right); } levelList.add(current.val); } tempResult.push(levelList); }
// 最终将栈临时存储的数据添加到最终的结果list中 while (!tempResult.isEmpty()) { result.add(tempResult.pop()); } return result; }}


以上是关于广度优先搜索的主要内容,如果未能解决你的问题,请参考以下文章

Prolog中的广度优先搜索

面试题算法: 广度优先搜索

图相关算法

图解:深度优先搜索与广度优先搜索

广度优先搜索遍历图

无向图 广度优先搜索 和 深度优先搜索