图的邻接表的建立

图的邻接表表示法类似于树的孩子链表表示法。对于图G中的每个顶点vi,该方法把所有邻接于vi的顶点vj链成一个带头节点的单链表,这个单链表就称为顶点vj的邻接表。

单链表中的每个结点至少包含两个域,一个为邻接点域(adjvex),它指示与顶点vi邻接的顶点在图中的位序;另一个为链域(next),它指示与顶点vi邻接的下一个节点。如果是网络,可以在单链表的头节点中增加一个数据域用于存储和边(弧)相关的信息,如权值等。在每个链表上需附设一个表头结点,在表头结点中,除了设有头指针域(firstedge)指向链表中的第一个结点之外,还设有存储顶点vi数据域(vertex)或其他有关信息的数据域。

头结点与链表结点的结构可表示为:
在这里插入图片描述

对于无向图,vi的邻接表中每个表结点都对应于与vi相关联的一条边;

例如,对于如图所示的无向图:
在这里插入图片描述
它的邻接表如图所示:
在这里插入图片描述
建立思想(输入顶点对(a,b)表示一条连接着两个顶点的边):
先将b所在结点连接到a所在结点的后面,再将a所在结点连接到b所在结点的后面:
在这里插入图片描述
对于有向图,如果每一顶点vi的邻接表中每个表结点都存储以vi为始点射出的一条边,则称这种图为有向图的出边表(邻接表);反之,若每一顶点vi的邻接表中每个表结点都对应于以vi为终点的边(即射入vi的边),则称这种表为有向图的入边表(逆邻接表)。

例如,对于如图所示的有向图:
在这里插入图片描述
出边表(邻接表):
在这里插入图片描述
建立思想(输入顶点对(a,b)表示一条连接着两个顶点的边):
将b所在结点连接到a所在结点的后面(与无向图相比只有第一步):在这里插入图片描述

入边表:
在这里插入图片描述

邻接表的建立:

邻接表存储结构:

#include<stdio.h>
#include<stdlib.h>
#define M 20                     //图的最大顶点数

typedef struct node {             //边表结点
	int adjvex;                   //邻接点
	struct node* next;
}EdgeNode;

typedef struct vnode {            //头结点类型
	char vertex;                  //顶点信息
	EdgeNode* FirstEdge;          //邻接表头指针
}VertexNode;

typedef struct {                 //邻接表类型
	VertexNode adjlist[M];       //存放头结点的顺序表
	int n, e;                    //图的顶点数与边数
}LinkedGraph;

邻接表建立算法:

void create(LinkedGraph* g,  int c) {
	                            //c为0表示建立无向图,否则表示建立有向图
	int a, b;
	EdgeNode* s;
	scanf_s("%d", &g->n);        //顶点数
	scanf_s("%d", &g->e);        //边数
	for (int i = 0; i < g->n; i++) {
		scanf_s("%s", g->adjlist[i].vertex,20);    //输入顶点信息
		g->adjlist[i].FirstEdge = NULL;        //边表置空
	}
	for (int j = 0; j < g->e; j++) {          //建立边表
		scanf_s("%d%d", &a, &b);              //输入无序对(a,b)表示边的顶点对
		//有向图(出边表)
		s = (EdgeNode*)malloc(sizeof(EdgeNode));
		s->adjvex = b;                       //邻接点序号为b
		s->next = g->adjlist[a].FirstEdge;
		g->adjlist[a].FirstEdge = s;          //将新的节点*s插入到顶点Vi的边表头部
		if (c == 0) {                         
			//无向图
			s = (EdgeNode*)malloc(sizeof(EdgeNode));
			s->adjvex = a;                      //邻接点序号为a
			s->next = g->adjlist[b].FirstEdge;
			g->adjlist[b].FirstEdge = s;      //将新的节点*s插入到顶点Vi的边表头部
		}
	}
}

建立好图的邻接表后,我们将其命名为”ljb.h":

/*ljb.h*/
#include<stdio.h>
#include<stdlib.h>
#define M 20                     //图的最大顶点数

typedef struct node {             //边表结点
	int adjvex;                  //邻接点
	struct node* next;
}EdgeNode;

typedef struct vnode {            //头结点类型
	char vertex;                 //顶点信息
	EdgeNode* FirstEdge;          //邻接表头指针
}VertexNode;

typedef struct {                 //邻接表类型
	VertexNode adjlist[M];        //存放头结点的顺序表
	int n, e;                    //图的顶点数与边数
}LinkedGraph;

void create(LinkedGraph* g, int c) {
	//c为0表示建立无向图,否则表示建立有向图
	int a, b;
	EdgeNode* s;
	scanf_s("%d", &g->n);        //顶点数
	scanf_s("%d", &g->e);        //边数
	for (int i = 0; i < g->n; i++) {
		scanf_s("%s", &g->adjlist[i].vertex, 20);    //输入顶点信息
		g->adjlist[i].FirstEdge = NULL;        //边表置空
	}
	for (int j = 0; j < g->e; j++) {          //建立边表
		scanf_s("%d%d", &a, &b);              //输入无序对(a,b)表示边的顶点对
		//有向图(出边表)
		s = (EdgeNode*)malloc(sizeof(EdgeNode));
		s->adjvex = b;                       //邻接点序号为b
		s->next = g->adjlist[a].FirstEdge;
		g->adjlist[a].FirstEdge = s;          //将新的节点*s插入到顶点Vi的边表头部
		if (c == 0) {
			//无向图
			s = (EdgeNode*)malloc(sizeof(EdgeNode));
			s->adjvex = a;                      //邻接点序号为a
			s->next = g->adjlist[b].FirstEdge;
			g->adjlist[b].FirstEdge = s;      //将新的节点*s插入到顶点Vi的边表头部
		}
	}
}

接下来我们就可以基于这个邻接表对图进行遍历了:
基于图的邻接表的深度优先遍历(DFS)和广度优先遍历(BFS)

  • 16
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值