A - 数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历

Description
给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列。(同一个结点的同层邻接点,节点编号小的优先遍历)

Input
输入第一行为整数n(0< n <100),表示数据的组数。
对于每组数据,第一行是三个整数k,m,t(0<k<100,0<m<(k-1)*k/2,0< t<k),表示有m条边,k个顶点,t为遍历的起始顶点。
下面的m行,每行是空格隔开的两个整数u,v,表示一条连接u,v顶点的无向边。

Output
输出有n行,对应n组输出,每行为用空格隔开的k个整数,对应一组数据,表示BFS的遍历结果。

Sample
Input
1
6 7 0
0 3
0 4
1 4
1 5
2 3
2 4
3 5
Output
0 3 4 2 5 1
Hint
以邻接矩阵作为存储结构。

两种实现方法:

第一种做法:非递归实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct map {
    int vex[101];//顶点数组
    int arc[101][101];//边数组
} MGraph;

int u, v; //表示一条连接u,v顶点的无向边。

void BFS(MGraph G, int k, int m, int t) {
    //给顶点赋值
    for(int i = 0; i < k; i++) {
        G.vex[i] = i;
    }
    //矩阵初始化
    for(int i = 0; i < k; i++) {
        for(int j = 0; j < k; j++) {
            G.arc[i][j] = 0;
        }
    }
    //构造关系网
    for(int i = 0; i < m; i++) {
        scanf("%d%d", &u, &v);
        G.arc[u][v] = G.arc[v][u] = 1;
    }

    int visited[101] = {0};//访问数组
    int q[500] = {-1}; //队列数组

    int in = 0; //队列存进下标
    int out = 0; //队列弹出下标
    int i, j;
    int len = 0; //队列中的元素个数

    //  for(i = 0; i < k; i++) { //对每一个顶点做循环(若是说明连通图,可以不用循环)
    i = t; //起始顶点//因为是连通图,所以不需要用循环
    //for循环的作用:防止图有单独的子图或着单个的点遗漏,所以用循环检查

    if(visited[i] == 0) { //如果当前顶点没有被访问过则对它进行访问
        visited[i] = 1; //做标记
        printf("%d", G.vex[i]); //打印顶点(第一个)

        q[in] = i; //用队列保存当前顶点下标
        in++;
        len++;
        while(len != 0) {
            i = q[out]; //队列元素出队列,赋值给i(i的值变为对应的顶点下标)
            out++;
            len--;//元素出队列,个数减一
            for(j = 0; j < k; j++) {//利用for循环,查找与当前顶点相连并且没有被访问过的顶点

                //此循环相当于找到与当前顶点相连且没有访问过的顶点,并将其下标存入队列中
                //当下一次while循环时相当于从队列中取出的顶点开始,重复同样的操作
                //直到每一个顶点都被访问完(因为是连通图,所以能找到所有的顶点),队列中不再存有
                //顶点下标,元素个数变为0,此时结束循环。

                if(G.arc[i][j] == 1 && visited[j] == 0) {
                    visited[j] = 1;//标记找到的顶点
                    printf(" %d", G.vex[j]); //打印顶点//将相连但没被访问过的打印出来
                    q[in] = j;//将找到的顶点下标入队列
                    in++;
                    len++;//元素进队列,个数加一
                }
            }
        }
    }
    // }
}
//非递归实现
//可行代码
int main() {
    int n;
    scanf("%d", &n);
    int k;//顶点
    int m;//边数
    int t;//遍历起始顶点
    while(n--) {
        scanf("%d%d%d", &k, &m, &t);
        MGraph G;
        BFS(G, k, m, t);
    }
    return 0;
}

第二种做法:递归实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//BFS递归实现
int map[220][220];//边数组
int vis[220];//访问数组
int ans[220];//顶点数组
int a = 0;
int b = 1;
int k, t;
//没有预先建立顶点数组,因为只要求打印顶点编号所以用顶点下标来
//表示顶点,并且在遍历的同时给顶点数组赋值
void BFS(int t) {
    a++;
    for(int i = 0; i < k; i++) {
        //通过循环遍历与当前开始顶点 n 相连的顶点,并且
        //将满足相连且没被访问过的顶点存入顶点数组。对遍历
        //好的顶点进行标记
        if(map[t][i] == 1 && vis[i] == 0) {
            //[b++],b先被用再++;
            ans[b++] = i; //给顶点数组赋值
            vis[i] = 1; //对已访问顶点标记
        }
    }
    //将与当前开始顶点相连且没被访问过的顶点获取之后,将获取的 邻接顶点 又做为
    //新的开始顶点重复同样操作。
    //如果a小于等于b表示获取到的邻接顶点还没有全部作为开始顶点重复操作完,递归进行重复操作
    if(a <= b)
        BFS(ans[a]);

    //退出递归的条件就是每一个顶点都被访问完,此时再没有满足“没有访问过”这个条件
    //的邻接顶点,b不再递增,而a递增访问,当a大过b时递归结束
}
int main() {
    int n, m, u, v, i;
    scanf("%d", &n);
    while(n--) {
        memset(map, 0, sizeof(map));
        memset(vis, 0, sizeof(vis));
        scanf("%d%d%d", &k, &m, &t);
        //建立边关系
        for(i = 0; i < m; i++) {
            scanf("%d%d", &u, &v);
            //对称矩阵
            map[u][v] = map[v][u] = 1;
        }
        ans[0] = t; //顶点数组赋初值(遍历开始顶点)
        vis[t] = 1; //标记开始数组
        BFS(t);
        for(i = 0; i < b; i++) {
            printf("%d%c", ans[i], i == b - 1 ? '\n' : ' ');
        }
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心醉瑶瑾前

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值