Java中的广度优先搜索和深度优先搜索是常见的搜索算法,适用于各种数据结构中的搜索问题。下面介绍一下这两种算法的特点和优缺点,代码中使用pre标签。
一、广度优先搜索(BFS)
/** * 广度优先搜索 * @param root 初始节点 * @return 目标节点 */ public Node bfs(Node root) { // 使用队列保存待搜索的节点 Queuequeue = new LinkedList<>(); // 使用set保存已访问过的节点,避免重复访问 Set visited = new HashSet<>(); queue.offer(root); visited.add(root); while (!queue.isEmpty()) { Node node = queue.poll(); if (node.isTarget()) { return node; } for (Node neighbor : node.neighbors()) { if (!visited.contains(neighbor)) { queue.offer(neighbor); visited.add(neighbor); } } } return null; }
BFS的特点是先访问根节点,然后依次访问其相邻节点。这个依次访问的过程可以使用一个队列来完成,先将根节点入队,然后弹出队首节点,访问完其所有相邻节点后,再将这些相邻节点依次入队。这样依次访问每一层节点,直到找到目标节点或队列为空。
BFS的缺点是空间复杂度较高,需要使用队列和set来记录节点,同时对于深度较大的树或图,其搜索效率也会下降。
二、深度优先搜索(DFS)
/** * 深度优先搜索 * @param node 当前节点 * @param visited 已访问的节点 * @return 目标节点 */ public Node dfs(Node node, Setvisited) { if (node.isTarget()) { return node; } visited.add(node); for (Node neighbor : node.neighbors()) { if (!visited.contains(neighbor)) { Node target = dfs(neighbor, visited); if (target != null) { return target; } } } return null; }
DFS的特点是优先访问深度较深的节点,访问完成之后再回溯到其祖先节点继续访问。这个过程可以使用递归函数来完成,访问一个节点时,先将其标记为已访问,然后以其相邻未访问节点为当前节点递归调用dfs函数,直到找到目标节点或所有节点都已访问。
DFS的优点是在不断深度搜索时没有记录下每条路径,使用空间较小,但是当深度较大的时候,它的效率会明显变低。同时,需要注意避免出现无限递归,防止stackoverflow错误。