蓝桥杯考点:DFS与BFS的算法应用

深度优先搜索(DFS)和广度优先搜索(BFS)是图和树的两种重要遍历算法。

DFS是什么?

深度优先搜索是一种用于遍历或搜索树或图的算法。沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点 v 的所在边都己被探寻过,搜索将回溯到发现节点 v 的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。

Java 代码示例
import java.util.ArrayList;
import java.util.List;

// 图的节点类
class Node {
    int val;
    List<Node> neighbors;

    public Node(int val) {
        this.val = val;
        this.neighbors = new ArrayList<>();
    }
}

public class DFS {
    // 标记节点是否被访问过
    private boolean[] visited;

    public void dfs(Node node) {
        int n = 100; // 假设节点数量不超过 100
        visited = new boolean[n];
        dfsHelper(node);
    }

    private void dfsHelper(Node node) {
        if (node == null || visited[node.val]) {
            return;
        }
        // 标记当前节点为已访问
        visited[node.val] = true;
        System.out.print(node.val + " ");
        // 递归访问相邻节点
        for (Node neighbor : node.neighbors) {
            dfsHelper(neighbor);
        }
    }

    public static void main(String[] args) {
        // 创建图
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);

        node1.neighbors.add(node2);
        node1.neighbors.add(node3);
        node2.neighbors.add(node4);
        node3.neighbors.add(node4);

        DFS dfs = new DFS();
        dfs.dfs(node1);
    }
}

BFS是什么?

广度优先搜索是一种用于遍历或搜索树或图的算法。它从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。广度优先搜索使用队列来实现,先将根节点入队,然后循环取出队列中的节点,将其未访问的相邻节点入队,直到队列为空。

Java 代码示例
import java.util.*;

// 图的节点类
class Node {
    int val;
    List<Node> neighbors;

    public Node(int val) {
        this.val = val;
        this.neighbors = new ArrayList<>();
    }
}

public class BFS {
    public void bfs(Node node) {
        if (node == null) {
            return;
        }
        // 标记节点是否被访问过
        boolean[] visited = new boolean[100]; // 假设节点数量不超过 100
        // 使用队列来实现 BFS
        Queue<Node> queue = new LinkedList<>();
        queue.offer(node);
        visited[node.val] = true;

        while (!queue.isEmpty()) {
            Node current = queue.poll();
            System.out.print(current.val + " ");
            // 访问相邻节点
            for (Node neighbor : current.neighbors) {
                if (!visited[neighbor.val]) {
                    queue.offer(neighbor);
                    visited[neighbor.val] = true;
                }
            }
        }
    }

    public static void main(String[] args) {
        // 创建图
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);

        node1.neighbors.add(node2);
        node1.neighbors.add(node3);
        node2.neighbors.add(node4);
        node3.neighbors.add(node4);

        BFS bfs = new BFS();
        bfs.bfs(node1);
    }
}

复杂度分析

  • 时间复杂度:DFS 和 BFS 的时间复杂度均为 O(V+E),其中 V 是节点数,E 是边数。
  • 空间复杂度:DFS 的空间复杂度为 O(V),主要是递归调用栈的空间;BFS 的空间复杂度也为 O(V),主要是队列的空间。

区别:

1.搜索策略
  • DFS:沿着树的深度遍历树的节点,尽可能深地搜索树的分支。当节点的所有子节点都被访问过后,搜索将回溯到上一个节点,继续探索其他未被访问的分支。可以理解为 “一条路走到黑”,直到无法继续才回头。
  • BFS:从根节点开始,沿着树的宽度逐层遍历节点。即先访问离根节点最近的所有节点,再依次访问距离根节点更远的层次。可以看作是像水波纹一样逐层扩散的搜索方式。
2.数据结构
  • DFS:通常使用递归或栈(Stack)来实现。递归调用本身就是基于系统栈来保存函数调用的上下文信息;手动实现时可以使用栈来模拟递归过程。
  • BFS:使用队列(Queue)来实现。队列的先进先出(FIFO)特性保证了节点按照层次顺序被访问。
3.空间复杂度
  • DFS:空间复杂度主要取决于递归调用栈的深度或栈中存储的节点数。在最坏情况下,树的深度为 O(V)(V 是节点数),因此空间复杂度为 O(V)。对于一些非常深的树,DFS 可能会导致栈溢出。
  • BFS:空间复杂度主要取决于队列中存储的节点数。在最坏情况下,队列可能需要存储某一层的所有节点,对于完全二叉树,最后一层的节点数接近 V/2,所以空间复杂度也是 O(V)。但在某些情况下,BFS 所需的空间可能比 DFS 更大,尤其是树的宽度较大时。
4.搜索结果
  • DFS:更适合寻找从起点到目标节点的一条路径,因为它会沿着一条路径一直深入,可能会较快地找到一条可行路径,但不一定是最短路径。
  • BFS:由于是逐层遍历,当找到目标节点时,所经过的路径一定是最短路径(在无权图中)。

适用问题

DFS 适用问题
  • 路径搜索:当需要找到从起点到终点的任意一条路径时,DFS 是一个不错的选择。例如,在迷宫问题中,找到一条从起点到终点的通路。
  • 连通分量:在无向图中找出所有的连通分量。通过 DFS 可以遍历一个连通分量中的所有节点,然后再对未访问的节点进行新的 DFS 遍历,直到所有节点都被访问。
  • 拓扑排序:在有向无环图(DAG)中进行拓扑排序。DFS 可以用于确定节点的完成时间,从而得到拓扑排序的结果。
  • 回溯算法:许多回溯算法本质上就是 DFS 的应用,如八皇后问题、数独求解等。通过递归地尝试不同的选择,当发现当前选择无法得到有效解时,回溯到上一步继续尝试其他选择。
BFS 适用问题
  • 最短路径问题:在无权图中,BFS 可以保证找到从起点到目标节点的最短路径。例如,在地图导航中寻找两点之间的最少步数路径。
  • 层序遍历:需要按层遍历树或图的节点时,BFS 是首选算法。比如,在二叉树的层序遍历中,使用 BFS 可以方便地按层输出节点值。
  • 广度优先的状态搜索:当问题的状态空间较大,且需要快速找到满足条件的最浅层次的解时,BFS 更合适。例如,在一些游戏中,通过不断扩展当前状态来寻找最优解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值