DFS(深度优先搜索)+BFS(广度优先搜索)+模板,这一篇就够了

DFS(深度优先搜索)

定义:
深度优先搜索算法(Depth First Search,简称DFS),一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止

属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。


核心思想:

  1. 为了求得问题的解,先选择某一种可能情况向前探索;
  2. 在探索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向前探索;
  3. 如此反复进行,直至得到解或证明无解。

应用场景:


模板(主要是其模板代码的逻辑,语言的话读者自行可以让ai书写对应不同语言的模板):

int a[510];   // 存储每次选出来的数据
bool book[510];   // 标记是否被访问
int ans = 0; // 记录符合条件的次数
int n, k; // n为总数,k为选择的数量

void DFS(int cur) {
    if(cur == k) { // k个数已经选完,可以进行输出等相关操作 
        for(int i = 0; i < cur; i++) {
            cout << a[i] << " ";
        } 
        cout << endl; // 输出结束后换行
        ans++;
        return;
    }
    
    for(int i = 0; i < n; i++) { // 遍历 n个数,并从中选择k个数 
        if(!book[i]) { // 若没有被访问 
            book[i] = true; // 标记已被访问 
            a[cur] = i;  // 选定本数,并加入数组 
            DFS(cur + 1);  // 递归,cur+1 
            book[i] = false; // 释放,标记为没被访问,方便下次引用 
        }
    }
}

BFS(广度优先搜索)

定义:
广度优先搜索(Breadth-First Search,简称BFS)是一种遍历或搜索树和图的算法,也称为宽度优先搜索,BFS算法从图的某个节点开始,依次对其所有相邻节点进行探索和遍历,然后再对这些相邻节点的相邻节点进行探索,直到遍历完所有的节点。

  • BFS算法使用队列来辅助实现,将起始节点放入队列中,然后依次取出队列中的节点,访问其相邻节点,并将其加入队列。这样可以保证从起始节点出发,依次按照距离顺序遍历节点。
  • BFS常用于寻找最短路径,因为它按照从起点到每个节点的距离来探索节点。

核心思想:(BFS算法通常使用队列来实现)

  1. 创建一个队列,将起始节点加入队列;
  2. 创建一个集合,用于存储已经访问过的节点;
  3. 从队列中取出一个节点,并将其标记为已访问;
  4. 访问该节点的所有相邻节点,如果相邻节点未被访问,则将其加入队列;
  5. 重复步骤3和步骤4,直到队列为空。

应用场景:例如图的遍历、最短路径搜索等。由于BFS算法保证了按照距离顺序遍历节点,因此可以用来寻找最短路径。另外,BFS算法还可以用来判断图是否连通,即从一个节点是否可以到达另一个节点


模板(主要是其模板代码的逻辑,语言的话读者自行可以让ai书写对应不同语言的模板):

struct node {
    int x, y; // 节点的坐标
};

const int MAXN = 510; // 定义一个合适的最大值
int vis[MAXN][MAXN]; // 访问标记数组
int bx[4] = {1, -1, 0, 0}; // 水平移动的方向
int by[4] = {0, 0, 1, -1}; // 垂直移动的方向
int m; // 移动方向的数量(这里为4)

void bfs(int startX, int startY) {
    queue<node> q;
    q.push(node{startX, startY}); // 初始化起始节点
    vis[startX][startY] = 1; // 标记起始节点为已访问

    while(!q.empty()) {
        node tmp = q.front(); // 队首元素
        q.pop(); // 出队
        
        // 检查是否到达目标终点
        if (tmp.x == targetX && tmp.y == targetY) { // 假设目标坐标为 (targetX, targetY)
            // 更新逻辑,例如记录路径或其他操作
            cout << "到达目标点: (" << tmp.x << ", " << tmp.y << ")\n";
            return;
        }

        // 遍历所有可能的方向
        for(int i = 0; i < m; i++) { // m个方向
            int dx = tmp.x + bx[i];
            int dy = tmp.y + by[i];

            // 检查下标是否越界
            if (dx < 0 || dx >= MAXN || dy < 0 || dy >= MAXN) {
                continue; // 越界则跳过
            }

            // 检查是否已经被标记过
            if (vis[dx][dy]) {
                continue; // 已访问则跳过
            }

            // 否则是合法的
            vis[dx][dy] = 1; // 先标记
            q.push(node{dx, dy}); // 再新点入队
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值