求连通图的所有深度优先遍历序列

在图论中,连通图基于连通的概念。在一个无向图G 中,若从顶点vi到顶点vj有路径相连(当然从vj到vi也一定有路径),则称vi和vj是连通的。如果 G 是有向图,那么连接vi和vj的路径中所有的边都必须同向。如果图中任意两点都是连通的,那么图被称作连通图。如果此图是有向图,则称为强连通图(注意:需要双向都有路径)。图的连通性是图的基本性质。

                                                                   图1-连通图

连通分量:无向图G的一个极大连通子图称为G的一个连通分量(或连通分支)。连通图只有一个连通分量,即其自身;非连通的无向图有多个连通分量。

强连通图:有向图G=(V,E) 中,若对于V中任意两个不同的顶点 x和 y,都存在从x到 y以及从 y到 x的路径,则称 G是强连通图。相应地有强连通分量的概念。强连通图只有一个强连通分量,即是其自身;非强连通的有向图有多个强连分量。

单向连通图:设G=<V,E>是有向图,如果u->v意味着图G至多包含一条从u到v的简单路径,则图G为单连通图。

弱连通图:将有向图的所有的有向边替换为无向边,所得到的图称为原图的基图。如果一个有向图的基图是连通图,则有向图是弱连通图。

/**
*    实验题目:
*        求连通图的所有深度优先遍历序列
*    实验目的:
*        领会图的深度优先遍历算法
*    实验内容:
*        编写程序,假设一个连通图采用邻接表存储,输出它的所有深度优先
*    遍历序列。
*/

#include <stdio.h>
#include <malloc.h>

#define INF     32767               //定义∞
#define MAXV    100                 //最大顶点个数

typedef char InfoType;
/*-------------------------以下定义邻接矩阵类型---------------------------*/
typedef struct
{
    int no;                         //顶点编号
    InfoType info;                  //顶点信息
}VertexType;                        //顶点类型

typedef struct
{
    int edges[MAXV][MAXV];          //邻接矩阵数组(用一个二维数组存放顶点间关系(边或弧)的数据)
    int n;                          //顶点数
    int e;                          //边数
    VertexType vexs[MAXV];          //存放顶点信息(用一个一维数组存放图中所有顶点数据)
}MatGraph;                          //完整的图邻接矩阵类型

//邻接表表示法-将每个顶点的邻接点串成一个单链表
/*-----------以下定义邻接表类型--------------*/
typedef struct ArcNode
{
    int adjvex;                     //该边的邻接点编号
    struct ArcNode *nextarc;        //指向下一条边的指针
    int weight;                     //该边的相关信息,如权值(用整型表示)
}ArcNode;                           //边结点类型

typedef struct VNode
{
    InfoType info;                  //顶点其他信息
    int cnt;                        //存放顶点入度,仅用于拓扑排序
    ArcNode *firstarc;              //指向第一条边
}VNode;                             //邻接表结点类型

typedef struct
{
    VNode adjlist[MAXV];            //邻接表头结点数组
    int n;                          //图中顶点数
    int e;                          //图中边数
}AdjGraph;                          //完整的图邻接表类型

/*-------------------------邻接矩阵的基本运算算法---------------------------*/
/*------------由边数组A、顶点数n和边数e创建图的邻接矩阵g--------------------*/
void CreateMat(MatGraph &g, int A[MAXV][MAXV], int n, int e)
{
    int i, j;

    g.n = n;
    g.e = e;
    for(i = 0; i < g.n; i++)
        for(j = 0; j < g.n; j++)
            g.edges[i][j] = A[i][j];
}

/*------------输出邻接矩阵g--------------------*/
void DispMat(MatGraph g)
{
    int i, j;

    for(i = 0; i < g.n; i++)
    {
        for(j = 0; j < g.n; j++)
        {
            if(g.edges[i][j] != INF)
                printf("%4d", g.edges[i][j]);
            else
                printf("%4s", "∞");
        }
        printf("\n");
    }
}

/*-------------------------邻接表的基本运算算法---------------------------*/
/*-------------------由边数组A、顶点数n和边数e创建图的邻接表G--------------------*/
void CreateAdj(AdjGraph *&G, int A[MAXV][MAXV], int n, int e)
{
    int i, j;
    ArcNode *p;

    G = (AdjGraph *)malloc(sizeof(AdjGraph));
    for(i = 0; i < n; i++)                              //给邻接表中所有头结点的指针域置初值NULL
    {
        G->adjlist[i].firstarc = NULL;
    }

    for(i = 0; i < n; i++)                              //检查邻接矩阵中的每个元素
    {
        for(j = n - 1; j >= 0; j--)
        {
            if(A[i][j] != 0 && A[i][j] != INF)          //存在一条边
            {
                p = (ArcNode *)malloc(sizeof(ArcNode)); //创建一个结点p
                p->adjvex = j;                          //邻接点编号
                p->weight = A[i][j];                    //边的权重
                p->nextarc = G->adjlist[i].firstarc;    //采用头插法插入结点p
                G->adjlist[i].firstarc = p;
            }
        }
    }
    G->n = n;
    G->e = e;
}

/*-------------------输出邻接表G--------------------*/
void DispAdj(AdjGraph *G)
{
    ArcNode *p;

    for(int i = 0; i < G->n; i++)
    {
        p = G->adjlist[i].firstarc;
        printf("%d: ", i);
        while(p != NULL)
        {
            printf("%3d[%d]->", p->adjvex, p->weight);  //邻接点编号[权重]
            p = p->nextarc;
        }
        printf("∧\n");
    }
}

/*-------------------销毁图的邻接表G--------------------*/
void DestroyAdj(AdjGraph *&G)
{
    ArcNode *pre, *p;

    for(int i = 0; i < G->n; i++)
    {
        pre = G->adjlist[i].firstarc;                   //pre指向第i个单链表的首结点
        if(pre != NULL)
        {
            p = pre->nextarc;
            while(p != NULL)                            //释放第i个单链表的所有边结点
            {
                free(pre);
                pre = p;
                p = p->nextarc;
            }
            free(pre);
        }
    }
    free(G);                                            //释放头结点数组
}

int visited[MAXV];                                  //全局数组

/**
*   功能:
*       求图G中从顶点v出发的所有深度优先遍历序列
*   @param path:记录访问过的顶点序列
*   @param d:记录访问的顶点数,其初值为0,当d=n时输出path中的访问序列
*
*/
void DFSALL(AdjGraph *G, int v, int path[], int d)
{
    ArcNode *p;

    visited[v] = 1;                                         //置已访问标记
    path[d] = v;
    d++;
    if(d == G->n)                                           //如果已访问所有顶点,则输出访问序列
    {
        for(int k = 0; k < d; k++)
            printf("%3d", path[k]);
        printf("\n");
    }
    p = G->adjlist[v].firstarc;                             //p指向顶点v的第一个相邻点
    while(p != NULL)
    {
        if(visited[p->adjvex] == 0)                         //若p->adjvex顶点未访问,递归访问它
        {
            DFSALL(G, p->adjvex, path, d);
        }
        p = p->nextarc;                                     //找顶点v的下一个相邻点
    }
    visited[v] = 0;
}


int main(void)
{
    AdjGraph *G;
    int n = 5;                                  //图顶点数
    int e = 8;                                  //图边数
    int A[MAXV][MAXV] = {
        {0, 1, 0, 1, 1}, {1, 0, 1, 1, 0},
        {0, 1, 0, 1, 1}, {1, 1, 1, 0, 1},
        {1, 0, 1, 1, 0}
    };

    CreateAdj(G, A, n, e);
    printf("图的邻接表:\n");
    DispAdj(G);
    int path[MAXV];
    int v = 1;
    printf("从顶点%d出发的所有深度优先序列:\n", v);
    DFSALL(G, v, path, 0);
    printf("销毁图的邻接表\n");
    DestroyAdj(G);

    return 0;
}
输出结果:

图G的邻接表:
0:   1[1]->  3[1]->  4[1]->∧
1:   0[1]->  2[1]->  3[1]->∧
2:   1[1]->  3[1]->  4[1]->∧
3:   0[1]->  1[1]->  2[1]->  4[1]->∧
4:   0[1]->  2[1]->  3[1]->∧
从顶点1出发的所有深度优先序列:
  1  0  3  2  4
  1  0  3  4  2
  1  0  4  2  3
  1  0  4  3  2
  1  2  3  0  4
  1  2  3  4  0
  1  2  4  0  3
  1  2  4  3  0
  1  3  0  4  2
  1  3  2  4  0
销毁图的邻接表

  • 8
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值