图的邻接表与邻接矩阵相互转换

如题 自用笔记 如有错误欢迎及时指正


两种存储结构的转换涉及以下数据:

        a.顶点数目与边数目

        b.顶点信息

        c.边信息

        d.为要转换的结构申请空间

        e.其他存储结构中保存的信息包括顶点度数,边权值等等

下面以无向带权图讨论该问题,有向图转换类似不再赘述。


存储结构定义

邻接表

*顶点表中带顶点度数域,边表中带权值域

/* ===预定义=== */
#define MAX_VEX_NUM 10
#define INF 2147483647

typedef int VertexType;            //顶点数据类型
typedef int EdgeType;               //边权值

/*===邻接表结构===*/
//边表结点
typedef struct ArcNode{
    int adjvex;     //以上一个顶点起始的边 所指向结尾顶点 在顶点表中的下标
    EdgeType weight;        //边权值
    struct ArcNode *nextarc;        //指向边表下一个结点
}ArcNode;
//顶点表结点
typedef struct VexNode{
    VertexType data;        //顶点的数据域
    int degree;     //度数
    ArcNode *firstarc;       //指向第一条出边 也就是指向第一个邻接顶点
} VexNode, AdjList[MAX_VEX_NUM];       //结构体数组    即为一个顺序存储的顶点表  用来保存顶点信息
//邻接表
typedef struct AdjacentList{
    AdjList List;       
    int vexnum;
    int edgenum;        
}ALGraph,*AdjListGraph;

/* ===建立邻接表=== */
void CreateGraph_AdjList(AdjListGraph &G){
    int numV, numE;     //要创建图的总顶点数与边数
    //建立初始结构
    printf("输入图的总顶点数与边数,使用空格隔开: ");
    scanf("%d%d", &numV, &numE);
    if(numV>MAX_VEX_NUM){
        printf("结点数超出限制!\n");
        return;
    }
    G = (ALGraph *)malloc(sizeof(ALGraph));
    G->vexnum = numV;
    G->edgenum = numE;
    printf("\n");
    
    int i, j;       //遍历控制器
    int start, end;     //一条弧的弧尾与弧头结点序号
    int w;      //弧权值
    
    //设置顶点表List 输入顶点信息存入list的data域并初始化firstarc指针域
    for (i = 0; i < G->vexnum; i++){
        printf("请输入第%d个结点的信息: ", i + 1);
        scanf("%d",&G->List[i].data);
        G->List[i].firstarc = NULL;     //初始化firstarc域
        G->List[i].degree = -1;
    }
    printf("\n");

    //创建边表数据
    for (i = 0; i < G->edgenum; i++){
        printf("依次输入第%d条边的'起始节点序号start','结束结点序号end','权值w',使用空格隔开(satrt与end在(1,...,n)取值)\n: ",i+1);
        scanf("%d%d%d", &start, &end, &w);
        printf("在无向图G中建立权值为%d的边(V%d,V%d)...\n", w, start, end);
        //注意无向图特性 邻接表中 边要记录两次
        //建立边<satrt,end>
        ArcNode *arc1 = (ArcNode *)malloc(sizeof(ArcNode));
        arc1->adjvex = end-1;      //边的结束结点下标为end-1
        arc1->weight = w;        //权值
        /* 采用头插法将边结点插入到顶点表表头结点之后 */
        arc1->nextarc = G->List[start-1].firstarc;
        G->List[start-1].firstarc = arc1;
        /* 采用头插法将边结点插入到顶点表表头结点之后 */
        //建立边<end,start>,若建立有向图,无此步
        ArcNode *arc2 = (ArcNode *)malloc(sizeof(ArcNode));
        arc2->adjvex = start-1;      //边的结束结点下标为start-1
        arc2->weight = w;          //权值
        /* 采用头插法将边结点插入到顶点表表头结点之后 */
        arc2->nextarc = G->List[end-1].firstarc;
        G->List[end - 1].firstarc = arc2;
        /* 采用头插法将边结点插入到顶点表表头结点之后 */
    }
}

/* ===输出图的邻接矩阵=== */
void PrintGraph_AdjList(AdjListGraph G){
    ArcNode *p; //工作指针
    int i, j;       //遍历控制器
    printf(" [顶点表]    [边表]  \n");
    for (int i = 0; i < G->vexnum; i++){
        //输出顶点表 第一个是下标 第二个是顶点信息
        printf("%d[ V%d |   ]->",i, G->List[i].data);     
        p = G->List[i].firstarc;
        while(p!=NULL){     //p不空
            //第一个是邻接点在顶点表中下标 第二个是边权值
            printf("[ %d | %d |   ]->", p->adjvex, p->weight);
            p = p->nextarc;
        }
        printf("[ ∞ | ∞ | ^ ]");
        printf("\n");
    }
}

邻接矩阵

*内含一个数组保存顶点度数

/* ===预定义=== */
#define MAX_VEX_NUM 10
#define INF 2147483647

typedef int VertexType;            //顶点数据类型
typedef int EdgeType;               //边权值

/* ===邻接矩阵结构=== */
typedef struct AdjacentMatrix{
    VertexType Vex[MAX_VEX_NUM];       //顶点表 保存顶点信息
    int Degree[MAX_VEX_NUM];        //存储顶点度数
    EdgeType Edge[MAX_VEX_NUM][MAX_VEX_NUM];      //边表  保存边信息
    int vexnum,edgenum;     //图当前顶点数与边数
} MGraph,*MatrixGraph;

/* ===创建图的邻接矩阵=== */
void CreateGraph_Matrix(MatrixGraph &G){
    int numV, numE;     //要创建图的总顶点数与边数
    printf("输入图的总顶点数与边数,使用空格隔开: ");
    scanf("%d%d", &numV, &numE);
    if(numV>MAX_VEX_NUM){
        printf("结点数超出限制!\n");
        return;
    }
    G = (MGraph *)malloc(sizeof(MGraph));
    G->vexnum = numV;
    G->edgenum = numE;
    memset(G->Degree, -1, MAX_VEX_NUM);
    printf("\n");

    int i, j;       //遍历控制器
    int start, end;     //一条弧的弧尾与弧头结点序号
    int w;      //弧权值

    //邻接矩阵即二维数组Edge初始化
    for (i = 0; i < G->vexnum;i++){
        for (j = 0; j < G->vexnum;j++){
            if(i==j){       //主对角线结点值为0
                G->Edge[i][j] = 0;
            }else{      //其他结点值为INF
                G->Edge[i][j] = INF;
            }//if
        }//for
    }//for

    //将顶点信息存入顶点表vex中
    for (i = 0; i < G->vexnum;i++){
        printf("请输入第%d个结点的信息: ", i + 1);
        scanf("%d", &G->Vex[i]);
    }
    printf("\n");

    //输入图的边信息
    for (i = 0; i < G->edgenum;i++){
        printf("依次输入第%d条边的'起始节点序号start','结尾结点序号end','权值w',使用空格隔开(satrt与end在(1,...,n)取值): ",i+1);
        scanf("%d %d %d", &start, &end, &w);
        G->Edge[start - 1][end - 1] = w;
        G->Edge[end - 1][start - 1] = w;        //无向图邻接矩阵对称性
        //若建立的是有向图 把这一句去掉即可
    }
}

/* ===输出图的邻接矩阵=== */
void PrintGraph_Matrix(MatrixGraph G){
	int i, j;
	printf("\n图的顶点为:");
	for (i = 0; i < G->vexnum; i++)
		printf("%d ", G->Vex[i]);
	printf("\n输出邻接矩阵:\n");
	printf("\t");
	for (i = 0; i < G->vexnum; i++)
		printf("\t%8d", G->Vex[i]);
		
	for (i = 0; i < G->vexnum; i++)
	{
		printf("\n\n%8d", G->Vex[i]);
		for (j = 0; j < G->vexnum; j++)
		{
			if (G->Edge[i][j] == INF)
				printf("\t%8s", "∞");
			else
				printf("\t%8d", G->Edge[i][j]);
		}
		printf("\n");
	}	
}

代码实现

邻接表转换邻接矩阵

/* ===邻接表转换为邻接矩阵=== */
void ListToMatrix(AdjListGraph ALG,MatrixGraph &MTG){
    MTG = (MGraph *)malloc(sizeof(MGraph));       //建立邻接矩阵结构
    MTG->vexnum = ALG->vexnum;          //矩阵图顶点数
    MTG->edgenum = ALG->edgenum;        //矩阵图边数
    memset(MTG->Degree, -1, MAX_VEX_NUM);
    int i, j;       //遍历控制器
    //邻接矩阵即二维数组Edge初始化
    for (i = 0; i < MTG->vexnum;i++){
        for (j = 0; j < MTG->vexnum;j++){
            if(i==j){       //主对角线结点值为0
                MTG->Edge[i][j] = 0;
            }else{      //其他结点值为INF
                MTG->Edge[i][j] = INF;
            }//if
        }//for
    }//for
    /* ===开始转换=== */
    //将顶点信息存入顶点表vex中
    for (int v = 0; v < MTG -> vexnum; v++){
        MTG->Vex[v] = ALG->List[v].data;        //MTG中顶点信息为ALG中顶点表信息
        MTG->Degree[v] = ALG->List[v].degree;
    }
    for (int v = 0; v < MTG -> edgenum; v++){
        for (ArcNode *p = ALG->List[v].firstarc; p != NULL;p=p->nextarc){     //p找到顶点信息
            MTG->Edge[v][p->adjvex] = p->weight;      //带权无向图 矩阵元素值为权值
            MTG->Edge[p->adjvex][v] = p->weight;      //由ALG中v到v的adjvex边建立MTG中对应元素
        }
    }
    printf("\n");
    /* ===开始转换=== */
}

邻接矩阵转换邻接表


/* ===邻接矩阵转换为邻接表=== */
void MatrixToList(MatrixGraph MTG,AdjListGraph &ALG){
    ALG = (ALGraph *)malloc(sizeof(ALGraph));     //建立邻接表结构
    ALG->vexnum = MTG->vexnum;      //设置顶点数与边数
    ALG->edgenum = MTG->edgenum;
    /* ===开始转换=== */
    //设置顶点表List 输入顶点信息存入list的data域并初始化firstarc指针域
    for (int v = 0; v < ALG->vexnum; v++){
        ALG->List[v].data = MTG->Vex[v];        //设置顶点信息
        ALG->List[v].firstarc = NULL;     //初始化firstarc域
        ALG->List[v].degree = MTG->Degree[v];
    }
    //设置边表
    //创建边表数据   遍历整个邻接矩阵
    for (int v = 0; v < ALG->vexnum; v++){      //遍历每个元素
        for (int w = 0; w <ALG->vexnum; w++){
            if(MTG->Edge[v][w]!=INF&&v!=w){       //v到w边存在 去除对角线元素
                ArcNode *p = (ArcNode *)malloc(sizeof(ArcNode));
                p->adjvex = w;      //终点为w 起点为v的边 采用头插入插入到对应的顶点表之后
                p->weight = MTG->Edge[v][w];        //设置权值
                p->nextarc=ALG->List[v].firstarc;       //头插
                ALG->List[v].firstarc = p;
            }
        }
    }
    printf("\n");
    /* ===开始转换=== */
}

2021.12.29

11:30

以上

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值