BFS(Breadth First Search)广度优先遍历
-
广度遍历的方式:从根节点出发,横向遍历树的结点,横向结束之后,纵向延伸。简而言之:一层一层的遍历。(可以使用队列对其遍历)
-
定义二叉树
TreeNode.java
public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int val) { this.val = val; } }
-
使用 队列 遍历 二叉树
BFS.java
public static List<Integer> BFSByQueue(TreeNode root) { if (root == null) { return null; } Queue<TreeNode> queue = new LinkedList<>(); queue.add(root); //存放遍历结果,然后返回 List<Integer> result = new ArrayList<>(); while (!queue.isEmpty()) { TreeNode treeNode = queue.poll(); /* 处理 TreeNode 节点 的逻辑 */ result.add(treeNode.val); if (treeNode.left != null) { queue.add(treeNode.left); } if (treeNode.right != null) { queue.add(treeNode.right); } } return result; }
-
测试方法
Test.java
public class Test { public static void main(String[] args) { TreeNode treeNode = new TreeNode(1); TreeNode treeNode2 = new TreeNode(2); TreeNode treeNode3 = new TreeNode(3); TreeNode treeNode4 = new TreeNode(4); TreeNode treeNode5 = new TreeNode(5); TreeNode treeNode6 = new TreeNode(6); TreeNode treeNode7 = new TreeNode(7); TreeNode treeNode8 = new TreeNode(8); TreeNode treeNode9 = new TreeNode(9); TreeNode treeNode10 = new TreeNode(10); TreeNode treeNode11 = new TreeNode(11); TreeNode treeNode12 = new TreeNode(12); treeNode.left = treeNode2; treeNode.right = treeNode3; treeNode2.left = treeNode4; treeNode2.right = treeNode5; treeNode3.left = treeNode6; treeNode3.right = treeNode7; treeNode4.left = treeNode8; treeNode5.left = treeNode9; treeNode6.left = treeNode10; treeNode7.left = treeNode11; treeNode7.right = treeNode12; List<Integer> result = BFS.BFSByQueue(treeNode); Iterator<Integer> iterator = result.iterator(); while (iterator.hasNext()) { System.out.print(iterator.next() + " "); } } }
-
运行结果
DFS(Depth First Search)深度优先遍历
-
深度遍历:先从根节点出发,沿着左子树进行纵向遍历直到找到叶子节点为止。然后回溯到前一个节点,进行右子树节点的遍历,直到遍历完所有可达节点为止。
-
递归代码
DFS.java
public static List<Integer> DFSByRecursion(TreeNode root) { if (root == null) { return null; } /* 处理节点的逻辑(由于是递归的调用,定义ArrayList的时候不能写在方法内部) private static List<Integer> result = new ArrayList<>(); 我把 此处的 result 的定义为了一个全局变量 */ result.add(root.val); if (root.left != null) { DFSByRecursion(root.left); } if (root.right != null) { DFSByRecursion(root.right); } return result; }
-
测试结果
Test.java
-
List<Integer> result = DFS.DFSByRecursion(treeNode); Iterator<Integer> iterator = result.iterator(); while (iterator.hasNext()) { System.out.print(iterator.next() + " "); }
-
栈 遍历
DFS.java
public static List<Integer> DFSByStack(TreeNode root) { if (root == null) { return null; } Stack<TreeNode> stack = new Stack<>(); stack.push(root); List<Integer> result = new ArrayList<>(); while (!stack.isEmpty()) { TreeNode treeNode = stack.pop(); /* 处理 TreeNode 节点 的逻辑 */ result.add(treeNode.val); if (treeNode.right != null) { stack.push(treeNode.right); } if (treeNode.left != null) { stack.push(treeNode.left); } } return result; }
-
测试结果
List<Integer> result = DFS.DFSByStack(treeNode); Iterator<Integer> iterator = result.iterator(); while (iterator.hasNext()) { System.out.print(iterator.next() + " "); }
图
-
图和树的最大区别在于图的下一个节点可能指向已访问过的结点,所以在使用BFS和DFS遍历时,需要维护一个 Set ,Set中存放已被访问过的结点,在遍历时先判断结点,未被访问过再遍历。
//使用Queue实现BFS public void BFSWithQueue(Node root) { Queue<Node> queue = new LinkedList<>(); if (root != null) queue.add(root); Set<Node> visited = new HashSet<>(); while (!queue.isEmpty()) { Node node = queue.poll(); visited.add(node); //在这里处理遍历到的Node节点(未写) if (node.children != null) { for (Node child : node.children) { if (child != null && !visited.contains(child){ queue.add(child); } } } } }