使用邻接表创建无向图和有向图

图的邻接表表示法:

邻接表(Adjacency List) 是图的 一 种链式存储结构。在邻接表中,对图中每个顶点V建立一个单链表,把与 V相邻接的顶点放在这个链表中。邻接表中每个单链表的第一个结点存放有关顶点的信息, 把这 一 结点看成链表的表头, 其余结点存放有关边的信息, 这样邻接表便由两部分组成:表头结点表和边表。

(1) 表头结点表:由所有表头结点以顺序结构的形式存储, 以便可以随机访问任 一 顶点的边链表。表头结点包括数据域 (data) 和链域 (firstarc) 两部分。其中, 数据域用于存储顶点 V 的名称或其他有关信息;链域用千指向链表中第 一 个结点(即与顶点 V邻接的第 一 个邻接点)。

(2)边表:由表示图中顶点间关系的 2n个边链表组成。边链表中边结点包括邻接点域

(adjvex) 、数据域 (info) 和链域 (nextarc) 三部分。其中, 邻接点域指示与顶点 V邻接的点在图中的位置;数据域存储和边相关的信息, 如权值等;链域指示与顶点v邻接的下 一 条边的结点。

datafirstarc

                                                                  表头节点

adjvexinfonextarc

                                                             边结点

【算法步骤】

1.输入总顶点数和总边数。

2.依次输入点的信息存入顶点表中,使每个表头结点的指针域初始化为NULL。

3.创建邻接表。依次输入每条边依附的两个顶点, 确定这两个顶点的序号i和j之后, 将此边结点分别插入 Vi 和vj 对应的两个边链表的头部。

//邻接矩阵法构造无向图 
void CreateUGD(ALGraph &G){
	printf("请输入图的总顶点数:");
	cin>>G.vexnum;
	printf("请输入图的总边数:");
	cin>>G.arcnum;
	//输入各点,构造表头结点表
	for(int i=0;i<G.vexnum;i++){
		printf("请输入第%d个顶点信息:",(i+1));
		cin>>G.vertices[i].data;
		G.vertices[i].firstarc=NULL;
	} 
	//输入各边,构造邻接表 
	for(int k=0;k<G.arcnum;k++){
		printf("输入第%d条边的信息:\n", (k+1));
		printf("输入边依附的第一个顶点:");
		VerTexType v1;
		cin>>v1;
		printf("输入边依附的第二个顶点:");
		VerTexType v2;
		cin>>v2;
		//确定v1,v2在图G中的位置,即在G.vertices中的序号
		int i= LocateVex(G, v1);
		int j= LocateVex(G, v2);
		struct ArcNode *p1, *p2;
		p1=new ArcNode; //生成一个新的边结点 
		p1->adjvex=j;
		p1->nextarc=G.vertices[i].firstarc;
		G.vertices[i].firstarc=p1;
		p2=new ArcNode; //生成另一个对称边结点p2 
		p2->adjvex=i;
		p2->nextarc=G.vertices[j].firstarc;
		G.vertices[j].firstarc=p2;
	}
} 

完整的实现代码如下:

#include<stdio.h>
#include<stack> 
#include <iostream>
#define MAXSIZE 100
#define MaxInt 32767 //表示最大值,即正无穷大 
#define MVNum 100 //定义最大顶点数 
using namespace std;

typedef char VerTexType; //假设顶点数据类型为字符型
typedef int ArcType; //假设边的权值为整型
//定义边结点 
typedef struct ArcNode{
	int adjvex;//该边所指向的顶点的位置
	struct ArcNode *nextarc; //下一条边的指针 
}ArcNode; 
//定义顶点结点信息
typedef struct VNode{
	VerTexType data;
	ArcNode *firstarc; //指向第一条依附该顶点的边的指针 
}VNode, AdjList[MVNum]; 
//定义邻接表的结构
typedef struct {
	AdjList vertices;
	int vexnum, arcnum; //当前图的点数和边数 
}ALGraph; 

//确定顶点vex在G.vertices中的序号
int LocateVex(ALGraph &G, VerTexType vex){
	for(int i=0;i<G.vexnum;i++){
		if(G.vertices[i].data==vex){
			return i;
		}
	}
} 

//邻接矩阵法构造无向图 
void CreateUGD(ALGraph &G){
	printf("请输入图的总顶点数:");
	cin>>G.vexnum;
	printf("请输入图的总边数:");
	cin>>G.arcnum;
	//输入各点,构造表头结点表
	for(int i=0;i<G.vexnum;i++){
		printf("请输入第%d个顶点信息:",(i+1));
		cin>>G.vertices[i].data;
		G.vertices[i].firstarc=NULL;
	} 
	//输入各边,构造邻接表 
	for(int k=0;k<G.arcnum;k++){
		printf("输入第%d条边的信息:\n", (k+1));
		printf("输入边依附的第一个顶点:");
		VerTexType v1;
		cin>>v1;
		printf("输入边依附的第二个顶点:");
		VerTexType v2;
		cin>>v2;
		//确定v1,v2在图G中的位置,即在G.vertices中的序号
		int i= LocateVex(G, v1);
		int j= LocateVex(G, v2);
		struct ArcNode *p1, *p2;
		p1=new ArcNode; //生成一个新的边结点 
		p1->adjvex=j;
		p1->nextarc=G.vertices[i].firstarc;
		G.vertices[i].firstarc=p1;
		p2=new ArcNode; //生成另一个对称边结点p2 
		p2->adjvex=i;
		p2->nextarc=G.vertices[j].firstarc;
		G.vertices[j].firstarc=p2;
	}
} 

//遍历图的邻接表 
void PrintfG(ALGraph &G){
	printf("遍历图的邻接表:\n");
	for(int i=0;i<G.vexnum;i++){
		printf("顶点%c ", G.vertices[i].data);
		ArcNode *p;
		p=G.vertices[i].firstarc;
		while(p){
			printf("%d ", p->adjvex);
			p=p->nextarc;
		}
	}
}

int main(){
	ALGraph G;
	CreateUGD(G);
	PrintfG(G);
}

 

邻接表法创建有向图的算法:

//邻接矩阵法构造有向图 
void CreateUGD(ALGraph &G){
	printf("请输入图的总顶点数:");
	cin>>G.vexnum;
	printf("请输入图的总边数:");
	cin>>G.arcnum;
	//输入各点,构造表头结点表
	for(int i=0;i<G.vexnum;i++){
		printf("请输入第%d个顶点信息:",(i+1));
		cin>>G.vertices[i].data;
		G.vertices[i].firstarc=NULL;
	} 
	//输入各边,构造邻接表 
	for(int k=0;k<G.arcnum;k++){
		printf("输入第%d条边的信息:\n", (k+1));
		printf("输入边依附的第一个顶点:");
		VerTexType v1;
		cin>>v1;
		printf("输入边依附的第二个顶点:");
		VerTexType v2;
		cin>>v2;
		//确定v1,v2在图G中的位置,即在G.vertices中的序号
		int i= LocateVex(G, v1);
		int j= LocateVex(G, v2);
		struct ArcNode *p1, *p2;
		p1=new ArcNode; //生成一个新的边结点 
		p1->adjvex=j;
		p1->nextarc=G.vertices[i].firstarc;
		G.vertices[i].firstarc=p1;
		//与无向图相反,有向图不需要生成对称边结点
        //p2=new ArcNode; //生成另一个对称边结点p2 
		//p2->adjvex=i;
		//p2->nextarc=G.vertices[j].firstarc;
		//G.vertices[j].firstarc=p2;
	}
} 

完整的代码实现如下:

#include<stdio.h>
#include<stack> 
#include <iostream>
#define MAXSIZE 100
#define MaxInt 32767 //表示最大值,即正无穷大 
#define MVNum 100 //定义最大顶点数 
using namespace std;

typedef char VerTexType; //假设顶点数据类型为字符型
typedef int ArcType; //假设边的权值为整型
//定义边结点 
typedef struct ArcNode{
	int adjvex;//该边所指向的顶点的位置
	struct ArcNode *nextarc; //下一条边的指针 
}ArcNode; 
//定义顶点结点信息
typedef struct VNode{
	VerTexType data;
	ArcNode *firstarc; //指向第一条依附该顶点的边的指针 
}VNode, AdjList[MVNum]; 
//定义邻接表的结构
typedef struct {
	AdjList vertices;
	int vexnum, arcnum; //当前图的点数和边数 
}ALGraph; 

//确定顶点vex在G.vertices中的序号
int LocateVex(ALGraph &G, VerTexType vex){
	for(int i=0;i<G.vexnum;i++){
		if(G.vertices[i].data==vex){
			return i;
		}
	}
} 

//邻接矩阵法构造有向图 
void CreateUGD(ALGraph &G){
	printf("请输入图的总顶点数:");
	cin>>G.vexnum;
	printf("请输入图的总边数:");
	cin>>G.arcnum;
	//输入各点,构造表头结点表
	for(int i=0;i<G.vexnum;i++){
		printf("请输入第%d个顶点信息:",(i+1));
		cin>>G.vertices[i].data;
		G.vertices[i].firstarc=NULL;
	} 
	//输入各边,构造邻接表 
	for(int k=0;k<G.arcnum;k++){
		printf("输入第%d条边的信息:\n", (k+1));
		printf("输入边依附的第一个顶点:");
		VerTexType v1;
		cin>>v1;
		printf("输入边依附的第二个顶点:");
		VerTexType v2;
		cin>>v2;
		//确定v1,v2在图G中的位置,即在G.vertices中的序号
		int i= LocateVex(G, v1);
		int j= LocateVex(G, v2);
		struct ArcNode *p1, *p2;
		p1=new ArcNode; //生成一个新的边结点 
		p1->adjvex=j;
		p1->nextarc=G.vertices[i].firstarc;
		G.vertices[i].firstarc=p1;
		//p2=new ArcNode; //生成另一个对称边结点p2 
		//p2->adjvex=i;
		//p2->nextarc=G.vertices[j].firstarc;
		//G.vertices[j].firstarc=p2;
	}
} 

//遍历图的邻接表 
void PrintfG(ALGraph &G){
	printf("遍历图的邻接表:\n");
	for(int i=0;i<G.vexnum;i++){
		printf("顶点%c ", G.vertices[i].data);
		ArcNode *p;
		p=G.vertices[i].firstarc;
		while(p){
			printf("%d ", p->adjvex);
			p=p->nextarc;
		}
	}
}

int main(){
	ALGraph G;
	CreateUGD(G);
	PrintfG(G);
}

 

  • 31
    点赞
  • 225
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值