图的邻接表算法
Posted 超浪*牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图的邻接表算法相关的知识,希望对你有一定的参考价值。
邻接表是图的一种顺序存储与链式存储的结合的存储方式。他包括两种结点结构,顶点表和边表。
- 顶点表的结点结构由顶点域和指向第一条邻接边的指针域。(建议多读几遍熟悉逻辑)
- 边表结点由邻接点域和指向下一条邻接边的指针域构成。
也就是以下结构体的嵌套** ↓ **
#define MAX 100
typedef char VertexType;
typedef struct node{/*定义边表结点*/
int adjvex;//邻接点域
struct node *next;//指向下一个邻接点域的指针域
}EdgeNode;
typedef struct vexnode{/*定义顶点表结点*/
VertexType data;//顶点域
EdgeNode *firstedge;//指向第一条边结点
}VHeadeNode;
typedef struct{
VHeadeNode adjlist[MAX];/*邻接表头结点数组*/
int n,e;//顶点数,边数
}AdjList;
AdjList类型:就是图的邻接表类型
接下里创建图的邻接表:
- 根据参数或者要求实现选择建立无向图还是有向图。
void GreateAGraph(AdjList *g,int flag){//根据flag的值0,1选择是有向图还是无向图}
- 输入图的边与顶点个数信息:
printf("请输入图的顶点数:");
scanf("%d",&g->n);
printf("请输入图的边数:");
scanf("%d",&g->e);
getchar();//吃掉这个回车,防止影响下一个字符的输入
printf("顶:%d,边:%d",g->n,g->e);
for(i=0;i<g->n;i++){
printf("+%c+",g->adjlist[i].data);//校验顶点输出
}
- 建立图的边表的信息(比较难理解):
代码里有详细注释
printf("\\n请输入边的信息,输入格式为:序号1,序号2(序号依次为0,1,2……)\\n");
int x,y;//关系结点数
EdgeNode *p;
for(i=0;i<g->e;i++){
printf("请输入第%d条边:",i);
scanf("%d,%d",&x,&y);//输入第一条边,将编号为x的结点添加到邻接表中
p = (EdgeNode*)malloc(sizeof(EdgeNode));
p->adjvex = y;
p->next = g->adjlist[x].firstedge;//头插法
g->adjlist[x].firstedge = p;
if(flag == 0){//无向图对称建立
p = (EdgeNode*)malloc(sizeof(EdgeNode));
p->adjvex = x;//y的邻接点(邻接序号)
p->next = g->adjlist[y].firstedge;//无向图的边相等,也将编号为y的结点添加到邻接表中
g->adjlist[y].firstedge = p;
}
}
- 输出邻接表的函数
void DisPlay(AdjList *g){
int i;
EdgeNode *p;
printf("\\n=======输出邻接表========\\n");
for(i=0;i<g->n;i++){
printf("%2d [%c]",i,g->adjlist[i].data);
p = g->adjlist[i].firstedge;
while(p!=NULL){//p不为空时
printf("-->[%d]",p->adjvex);
p = p->next;
}
printf("\\n");
}
}
用邻接表要比邻接矩阵更加节省空间存储空间。
整体代码描述以及演示结果:
#include <stdio.h>
#include <stdlib.h>
/*三步走,从一个存储顶点的数组,里面又有点数和边数*/
/*数组是存储顶点信息的,后面有一个链表结点*/
/*这个链表结点又是一个结构体类型,包含一个一个点数和指向下一个的点数*/
#define MAX 100
typedef char VertexType;
typedef struct node{/*定义边表结点*/
int adjvex;//邻接点域
struct node *next;//指向下一个邻接点域的指针域
}EdgeNode;
typedef struct vexnode{/*定义顶点表结点*/
VertexType data;//顶点域
EdgeNode *firstedge;//指向第一条边结点
}VHeadeNode;
typedef struct{
VHeadeNode adjlist[MAX];/*邻接表头结点数组*/
int n,e;//顶点数,边数
}AdjList; //图的邻接表类型
void GreateAGraph(AdjList *g,int flag){//根据flag的值0,1选择是有向图还是无向图
int i;
if(flag == 0){
printf("=============建立一个无向图==============\\n");
}else{
printf("=============建立一个有向图=============\\n");
}
printf("请输入图的顶点数:");
scanf("%d",&g->n);
printf("请输入图的边数:");
scanf("%d",&g->e);
getchar();//吃掉这个回车,防止影响下一个字符的输入
printf("顶:%d,边:%d",g->n,g->e);
/*建立图的顶点信息*/
printf("\\n请的输入图的各顶点信息:\\n");
for(i=0;i<g->n;i++){
printf("第%d个顶点信息:",i+1);
scanf("%c",&(g->adjlist[i].data));//给图的每个结点的顶点域赋值
getchar();
g->adjlist[i].firstedge = NULL;//首先点的边表头指针都设为空
}
for(i=0;i<g->n;i++){
printf("+%c+",g->adjlist[i].data);//校验顶点输出
}
/*建立图的边表的信息*/
printf("\\n请输入边的信息,输入格式为:序号1,序号2(序号依次为0,1,2……)\\n");
int x,y;//关系结点数
EdgeNode *p;
for(i=0;i<g->e;i++){
printf("请输入第%d条边:",i);
scanf("%d,%d",&x,&y);//输入第一条边,将编号为x的结点添加到邻接表中
p = (EdgeNode*)malloc(sizeof(EdgeNode));
p->adjvex = y;
p->next = g->adjlist[x].firstedge;//头插法
g->adjlist[x].firstedge = p;
if(flag == 0){
p = (EdgeNode*)malloc(sizeof(EdgeNode));
p->adjvex = x;//y的邻接点(邻接序号)
p->next = g->adjlist[y].firstedge;//无向图的边相等,也将编号为y的结点添加到邻接表中
g->adjlist[y].firstedge = p;
}
}
}
/*输出邻接表的函数*/
void DisPlay(AdjList *g){
int i;
EdgeNode *p;
printf("\\n=======输出邻接表========\\n");
for(i=0;i<g->n;i++){
printf("%2d [%c]",i,g->adjlist[i].data);
p = g->adjlist[i].firstedge;
while(p!=NULL){
printf("-->[%d]",p->adjvex);
p = p->next;
}
printf("\\n");
}
}
int main() {
AdjList G;
GreateAGraph(&G,0);//建立无向图
DisPlay(&G);
return 0;
}
以上是关于图的邻接表算法的主要内容,如果未能解决你的问题,请参考以下文章
用c语言编程 1创建图的邻接矩阵和邻接表 2验证图的深度优先、广度优先遍历算法 3验证最短路径