邻接矩阵实现--图的深度优先遍历DFS和广度优先遍历BFS

          图论中一个基本的概念就是遍历。就是访问到图的每一个顶点,同时每个顶点只访问一次。

          DFS和BFS的概念和思路网上说明的很详细了。但是网上很多代码实现有缺陷,基本都没有考虑图不连通的情况,比如某个顶点A和其它任何一个顶点都不关联,那么这个顶点A就访问不到了。如果遍历的起点刚好是孤立的顶点A,就只能访问顶点A了,其它顶点就访问不到了。

          我这边的代码就是增加了这些情况的处理,确保每个顶点都能可以访问到。

          完整的代码如下(通过邻接矩阵实现图):

#define MAX_VERTEX 16

typedef enum
{
    UNDIRECTED_GRAPH = 0, //无向图
    DIRECTED_GRAPH = 1, //有向图
    UNDIRECTED_NET = 2, //无向网
    DIRECTED_NET = 3, //有向网
}GRAPH_TYPE;

typedef struct
{
    GRAPH_TYPE type; //图的类型
    int vertexCount;//顶点个数
    BOOL visitFlag[MAX_VERTEX];
    char vertex[MAX_VERTEX]; //顶点数组
    int edge[MAX_VERTEX][MAX_VERTEX]; //邻接矩阵
}GRAPH,*PGRAPH;

void Visit(PGRAPH graph,int vIndex)
{
    graph->visitFlag[vIndex] = TRUE; //设置已访问标志
    printf("Visit Vertex: %c\r\n",graph->vertex[vIndex]);
}

void DFS(PGRAPH graph,int startVertexIndex)
{
    stack<int> s; //访问栈
    s.push(startVertexIndex);
    while(!s.empty())
    {
        int vertexIndex = s.top();
        if(!graph->visitFlag[vertexIndex])//未访问过
        {
            Visit(graph,vertexIndex);
        }

        s.pop();//vertexIndex顶点出栈

        for(int j=graph->vertexCount-1;j>=0;j--)
        {
            if(!graph->visitFlag[j] && graph->edge[vertexIndex][j])
            {
                s.push(j); //于vertexIndex相邻的顶点并且未访问过的顶点全部入栈
            }
        }
    }

    //图并不一定是连通的,因此要确保每个顶点都遍历过
    for(int i=0;i<graph->vertexCount;i++)
    {
        if(!graph->visitFlag[i])
        {
            printf("Not Connected vertex start DFS: %c\r\n",graph->vertex[i]);
            DFS(graph,i);
        }
    }
}

void BFS(PGRAPH graph,int startVertexIndex)
{
    queue<int> q; //访问队列
    q.push(startVertexIndex);//起始访问的顶点入队

    while(!q.empty())
    {
        int vertexIndex = q.front();
        if(!graph->visitFlag[vertexIndex])//未访问过
        {
            Visit(graph,vertexIndex);
        }

        q.pop();//vertexIndex顶点出队

        for(int j=0;j<graph->vertexCount;j++)
        {
            if(!graph->visitFlag[j] && graph->edge[vertexIndex][j])
            {
                q.push(j); //于vertexIndex相邻的顶点并且未访问过的顶点全部入队
            }
        }
    }

    //图并不一定是连通的,因此要确保每个顶点都遍历过
    for(int i=0;i<graph->vertexCount;i++)
    {
        if(!graph->visitFlag[i])
        {
            printf("Not Connected vertex start BFS: %c\r\n",graph->vertex[i]);
            BFS(graph,i);
        }
    }
}

void InitGraph(PGRAPH graph)
{
    graph->type = UNDIRECTED_GRAPH; //无向图
    graph->vertexCount = 10;
    for(int i=0;i<graph->vertexCount;i++)
    {
        graph->vertex[i] = 'A'+i; //顶点为'A','B','C'等等
    }

    graph->edge[0][1] = 1;//AB有边
    graph->edge[1][0] = 1;

    graph->edge[0][4] = 1;//AE有边
    graph->edge[4][0] = 1;

    graph->edge[1][3] = 1;//BD有边
    graph->edge[3][1] = 1;

    graph->edge[2][4] = 1;//EC有边
    graph->edge[4][2] = 1;

    graph->edge[2][5] = 1;//CF CG CH 有边
    graph->edge[5][2] = 1;
    graph->edge[2][6] = 1;
    graph->edge[6][2] = 1;
    graph->edge[2][7] = 1;
    graph->edge[7][2] = 1;

    graph->edge[6][8] = 1;//GI GJ 有边
    graph->edge[8][6] = 1;
    graph->edge[6][9] = 1;
    graph->edge[9][6] = 1;
}

void InitVistFlag(PGRAPH graph)
{
    for(int i=0;i<graph->vertexCount;i++)
    {
        graph->visitFlag[i] = FALSE;
    }
}

void TestGraph()
{
    GRAPH graph = {UNDIRECTED_GRAPH,0};
    InitGraph(&graph);

    printf("Test BFS,Start vertex 0:\r\n");
    BFS(&graph,0);

    InitVistFlag(&graph);
    printf("\r\nTest DFS,Start vertex 0:\r\n");
    DFS(&graph,0);

    InitVistFlag(&graph);
    for(int i=0;i<graph.vertexCount;i++)
    {
        graph.edge[2][i] = 0;
        graph.edge[i][2] = 0;//使得第3个顶点和任何顶点都不连通
    }
    printf("\r\nTest BFS,Start vertex 5:\r\n");
    BFS(&graph,5);

    InitVistFlag(&graph);
    printf("\r\nTest DFS,Start vertex 5:\r\n");
    DFS(&graph,5);
}

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/faithzzf/article/details/78055538
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞