快速理解DFS与BFS及其C语言代码实现

目录

DFS深度优先算法

BFS广度优先算法


DFS深度优先算法

DFS可以理解为一条“路”走到底,没“路”可以走了再回到上一个“路(jie)口(dian)”,找有没有路可以走,直到没有可以遍历的节点,类似于树的先序遍历。

以树为例,我们先选择根节点1作为初始节点,一条路往下走,1-2-4,发现4号节点没有子节点,于是返回2号节点,访问5号节点,发现5号没有子节点,我们返回2号,2号也没有子节点,我们就返回1号,前往3号,以此类推,完成遍历。

最终完成遍历的结果应当是:1-2-4-5-3-6-7

b77903e17a4a4e67aa4bb4bfb42d43b7.png

图的DFS与树相似,我们直接上图和结果

我们以2号节点为根节点,则结果为:2-1-5-6-3-4-8-7

f87ed5842a8142b58b778364097d0d58.png

下面上DFS的代码:

int visited[MAX_NODES]; // 标记节点是否已经访问过  
int graph[MAX_NODES][MAX_NODES]; // 邻接矩阵  
int n; // 图的大小  
  
void dfs(int node) {  
    //无效节点这直接返回,结束递归
    if (node < 0 || node >= n) {  
        printf("Error: Invalid node index %d\n", node);  
        return;  
    }  
    visited[node] = 1;  
    printf("%d ", node);  
  
    for (int i = 0; i < n; i++) {  
        if (graph[node][i] && !visited[i]) {  
            dfs(i);  
        }  
    }  
}  

BFS广度优先算法

BFS可以理解为寻找相邻节点并遍历,直到没有可以遍历的节点

以树为例,若从根结点出发,则先遍历根节点的子节点,然后再遍历子节点的所有子节点,直到全部遍历完。

用容易记忆的方法讲即为一层一层往下走,类比宿管查房,从最顶层(假设为n层)的房间开始查,第n层的每个房间查完,查第n-1层的每一间房间,直到查到1层的最后一间房间停止。

以下图为例,访问的顺序为1-2/3-4/5/6/7

f67fcc251ab84ecda2959bb7c1f34afb.png

接下来看一下图的例子,与树类似,先查找与当前节点相临近的节点,访问他,再寻找相邻节点的相邻节点并访问,直到所有节点都访问完成。

可以类比洪水爆发,若洪水在A点爆发,则先通过连通B点的“空路”到B点,但是不会去没有“空路”连接的C点。

同样我们以下图为例,若我们从节点2出发,则访问顺序为:2-1/6-5/3-4/7-8

d02ae9d42e4b4043aeb6669960eea369.png

原理为:若我们从节点2出发,则与2相邻且连通的节点为1和6,则我们访问1和6,但是由于2不和5、3两个节点直接相连通,就不访问5和3。接下来1和6相邻且连通的节点为5和3,则继续访问5和3。以此类推访问剩下三个节点。

PS:需要注意的是图中可能存在回路,因此实现代码时需要为每一个节点设置标记值,避免访问已经访问过的节点。树中就不存在回路问题,无需担心这类问题。不过在有向图中可能需要多次调用BFS函数,因为可能从A节点到B节点可以走通,但是B节点到A节点无法走通,导致可能出现最终不能一次遍历完的情况。

PSS:采用邻接矩阵和邻接表两种方法产生的遍历序列不一定一样,具有可变性。

下面是BFS的代码实现

int visited[MAX_NODES] = {0}; // 初始化一个辅助数组为0用于表示所有节点都未被访问  
int graph[MAX_NODES][MAX_NODES] = {0}; // 初始化邻接矩阵为0,表示没有边  
int n; // 图的大小
  
void bfs(int start_node) {  
    // 处理无效的起始节点 
    if (start_node < 0 || start_node >= n) {   
        printf("Invalid start node\n");  
        return;  
    } 
    int queue[MAX_NODES];  
    int front = 0, rear = 0;  
    queue[rear++] = start_node;  
    visited[start_node] = 1;  
    while (front < rear) {  
        int curr_node = queue[front++];  
        printf("%d ", curr_node);  
  
        for (int i = 0; i < n; i++) {  
            if (graph[curr_node][i] && !visited[i]) {  
                visited[i] = 1;  
                queue[rear++] = i;  
            }  
        }  
    }  
    printf("\n"); 
}

PS:在强连通图中,从任意节点出发都只需要调用一次BFS或DFS

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值