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

Posted 薛定谔的猫ovo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图的深度优先遍历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,v); w!='0'; w=NextNeighbor(G,v,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;
}

运行结果

以上是关于图的深度优先遍历DFS和广度优先遍历BFS(邻接矩阵存储)超详细完整代码进阶版的主要内容,如果未能解决你的问题,请参考以下文章

数据结构学习笔记——图的遍历算法(深度优先搜索和广度优先搜索)

数据结构学习笔记——图的遍历算法(深度优先搜索和广度优先搜索)

图的遍历:深度优先遍历,广度优先遍历

广度优先遍历和深度优先遍历的真正区别

算法导论—无向图的遍历(BFS+DFS,MATLAB)

s中的广度优先遍历(BFS)和深度优先遍历(DFS)简单理解