图的深度优先遍历DFS和广度优先遍历BFS(邻接矩阵存储)超详细完整代码进阶版


前言

 关于图的深度优先遍历(DFS)和广度优先遍历(BFS)的基本概念以及图的邻接矩阵存储,可参考文章图的深度优先遍历DFS和广度优先遍历BFS(邻接矩阵存储)超详细完整代码简单版

 在上篇文章中,我们已经介绍了图的深度优先遍历和广度优先遍历的基本概念及简单实现(顶点值与数组下标对应),那么对于任意类型的顶点的图,该如何实现对其的深度优先遍历和广度优先遍历呢?在下面的内容中将会给出答案。

 下面从零开始,一步一步实现图的深度优先遍历和广度优先遍历。

邻接矩阵存储的结构定义

首先,给出邻接矩阵存储的结构定义:

#define maxvertexnum 30  //最大顶点个数
typedef char VertexType; //顶点的类型
typedef int EdgeType; 

typedef struct{
    VertexType Vertex[maxvertexnum];  //顶点表
    EdgeType Edge[maxvertexnum][maxvertexnum];  //边表
    int vexnum, edgenum; //顶点数和边数
}MGraph;

构建一个无权有向图(邻接矩阵存储)

图的顶点保存在数组v[n]中,图的边(顶点对)保存在数组edge[e][2]中。

//返回顶点的存储下标,将顶点值转换为顶点号
int getPos(MGraph G, VertexType v){
    int i;
    for(i=0; i<G.vexnum; i++){
        if(G.Vertex[i] == v){
            break;
        }
    }
    return i;
}
//无权有向图的邻接矩阵存储
void CreateMGraph(MGraph &G, VertexType v[], VertexType edge[][2], int n, int e){
    //v[n]存放顶点,edge[e][2]存放有向边
    //初始化
    G.vexnum = n; //顶点数
    G.edgenum = e;  //边数
    for(int i=0; i<G.vexnum; i++){
        G.Vertex[i] = v[i];
        for(int k=0; k<G.vexnum; k++){
            G.Edge[i][k] = 0; //邻接矩阵初始化全为0
        }
    }
    //根据输入边形成邻接矩阵
    for(int i=0; i<G.edgenum; i++){
        int j = getPos(G, edge[i][0]); //顶点edge[i][0]的存储位置
        int k = getPos(G, edge[i][1]); //顶点edge[i][1]的存储位置
        G.Edge[j][k] = 1;
    }
}

查找顶点v的第一个邻接点FirstNeighbor

//第一个邻接点
VertexType FirstNeighbor(MGraph G, VertexType v){
    int i = getPos(G, v); //找到顶点v的存储位置
    for(int j=0; j<G.vexnum; j++){
        if(G.Edge[i][j] >0) //找到第一个大于0的边
            return G.Vertex[j];
    }
    return '0'; //不存在则返回'0'
}

查找顶点v的邻接点w的下一个邻接点NextNeighbor

//下一个邻接点
VertexType NextNeighbor(MGraph G, VertexType v, VertexType w){
    int i = getPos(G, v);
    int j = getPos(G, w);
    for(int k=j+1; k<G.vexnum; k++){ //从w开始找,找到w后面第一个大于0的边
        if(G.Edge[i][k] >0)
            return G.Vertex[k];
    }
    return '0'; //不存在则返回'0'
}

深度优先遍历DFS

int visited[maxvertexnum]; //访问标记数组
//深度优先遍历
void DFS(MGraph G,VertexType v){
    cout<<v;
    visited[getPos(G,v)] = 1;
    for(VertexType w=FirstNeighbor(G,v); w!='0'; w=NextNeighbor(G,v,w)){ 
        if(!visited[getPos(G,w)])
            DFS(G,w);
    }
}
void DFSTraverse(MGraph G){
    for(int i=0; i<G.vexnum; i++){
        visited[i] = 0; //初始化标记数组
    }
    for(int i=0; i<G.vexnum; i++){
        if(!visited[i]){
            DFS(G,G.Vertex[i]);
        }
    }
}

广度优先遍历BFS

广度优先遍历需要借助队列暂存邻接顶点

//广度优先遍历
void BFS(MGraph G, VertexType v){
    queue<VertexType> vex; //借助队列存储邻接顶点
    cout<<v;
    visited[getPos(G,v)] = 1;
    vex.push(v);
    while(!vex.empty()){
        VertexType u = vex.front(); //获取队首元素
        vex.pop(); //出队
        for(VertexType w=FirstNeighbor(G,u); w!='0'; w=NextNeighbor(G,u,w)){
            if(!visited[getPos(G,w)]){
                cout<<w;
                visited[getPos(G,w)] = 1;
                vex.push(w); //入队
            }
        }
    }
}
void BFSTraverse(MGraph G){
    for(int i=0; i<G.vexnum; i++){
        visited[i] = 0; //初始化标记数组
    }
    for(int i=0; i<G.vexnum; i++){
        if(!visited[i]){
            BFS(G, G.Vertex[i]);
        }
    }
}

主函数

int main(){
    MGraph G;
    int n,e;
    cin>>n>>e;
    VertexType v[n];
    VertexType edge[e][2];
    for(int i=0; i<n; i++){
        cin>>v[i];
    }
    for(int i=0; i<e; i++){
        cin>>edge[i][0]>>edge[i][1];
    }
    CreateMGraph(G, v, edge, n, e);
    DFSTraverse(G);
    cout<<endl;
    BFSTraverse(G);
    return 0;
}

运行结果

在这里插入图片描述
在这里插入图片描述

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
以下是使用邻接矩阵存储的无向深度优先广度优先的C++代码: ```c++ #include <iostream> #include <queue> using namespace std; const int MAXN = 100; // 最大顶点数 int graph[MAXN][MAXN]; // 邻接矩阵存储 bool visited[MAXN]; // 标记是否已经访问过 // 深度优先 void dfs(int u) { visited[u] = true; cout << u << " "; for (int v = 0; v < MAXN; v++) { if (graph[u][v] && !visited[v]) { dfs(v); } } } // 广度优先 void bfs(int u) { queue<int> q; visited[u] = true; q.push(u); while (!q.empty()) { int u = q.front(); q.pop(); cout << u << " "; for (int v = 0; v < MAXN; v++) { if (graph[u][v] && !visited[v]) { visited[v] = true; q.push(v); } } } } int main() { // 初始化邻接矩阵和visited数组 for (int i = 0; i < MAXN; i++) { visited[i] = false; for (int j = 0; j < MAXN; j++) { graph[i][j] = 0; } } // 读入无向 int n, m; cin >> n >> m; for (int i = 0; i < m; i++) { int u, v; cin >> u >> v; graph[u][v] = graph[v][u] = 1; } // 深度优先 cout << "DFS: "; for (int i = 0; i < n; i++) { if (!visited[i]) { dfs(i); } } cout << endl; // 广度优先 for (int i = 0; i < MAXN; i++) { visited[i] = false; } cout << "BFS: "; for (int i = 0; i < n; i++) { if (!visited[i]) { bfs(i); } } cout << endl; return 0; } ``` 其中,`dfs(int u)` 函数实现了从顶点 `u` 开始的深度优先,`bfs(int u)` 函数实现了从顶点 `u` 开始的广度优先。在遍时,需要使用 `visited` 数组来标记每个顶点是否已经访问过,避免重复访问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值