图:存储方法+基本运算算法详解

目录

1.利用两种存储方法创建图,实现基本声明。

2.基本运算算法设计。


1.利用两种存储方法创建图,实现基本声明。

存储方法有两种

1)邻接矩阵存储方法。

创建图时,我们需要包含的要素有,顶点(结构体),顶点之间的关系(矩阵),边数顶点数常用信息。因此先用一个结构体表示每个单独的顶点(类似链表中会有Node),再用另一个结构体,利用数组包含所有顶点信息,矩阵表示顶点关系,边数顶点数单独表示。代码如下:

#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#define InofType char//顶点其它信息
#define MAXV 100//MAXV为最大顶点个数

#define INF 32767//定义无穷

//邻接矩阵存储:n个顶点,n*n型矩阵,i行n列指第i个对第j个之间的关系
//有边记权值,没有边记0

//顶点信息
typedef struct
{
	int no;//顶点编号
	InofType inof;
}VertexType;

typedef struct
{
	VertexType vexs[MAXV];//存放顶点信息
	int edges[MAXV][MAXV];//邻接矩阵数组
	int n,e;//顶点数,边数
}MatGraph;
 

2)邻接表存储方法。声明注释如下:

这是一种顺序和链式结合的方法。

链式:每个顶点与之相连的其它顶点之间的关系为链式---边结点,头结点。

顺序:将每个链式之间的头结点用顺序存储,便于查找---头结点用数组存储,便于查找。


//边结点(类似于链表)
typedef struct ANode
{
	ANode *nextarc;
	int weight;//该条边的权重
	int adjvex;//该条边的邻接点编号
}ArcNode;

//头结点
typedef struct Vnode
{
	ArcNode*firstarc;//上述边界点链表的头结点
	InofType inof;
}VNode;

//图
typedef struct
{
	VNode adjlist[MAXV];//头结点
	int n,e;//顶点数,边数
}AdjGraph;

2.基本运算算法设计(邻接表)。

1)创建图的运算算法。

void CreatAdj(AdjGraph *G, int A[MAXV][MAXV], int n, int e) {
	G = (AdjGraph*)malloc(sizeof(AdjGraph));

	for (int i = 0; i < n; i++) {
		G->adjlist[i].firstarc = NULL; //将每个链表的头结点指针域置为空
	}

	ArcNode *p;
	for (int i = 0; i < n; i++) {
		for (int j = n - 1; j >= 0; j--) { //头插法,倒叙
			p = (ArcNode*)malloc(sizeof(ArcNode));
			p->adjvex = j; //存放邻接点
			p->weight = A[i][j]; //存放权重

			p->nextarc = G->adjlist[i].firstarc; //头插法
			G->adjlist[i].firstarc = p;
		}
	}
	G->e = e;
	G->n = n;
}

2)输出图的运算算法。

void DispAdj(AdjGraph*G) {
	ArcNode*p;
	for (int i = 0; i < G->n; i++) {
		p = G->adjlist[i].firstarc;
		printf("%3d: ", i);
		while (p != NULL) {
			printf("%3d[%d]", p->adjvex, p->weight);
			p = p->nextarc;
		}
		printf("\n");
	}
}

3)销毁图的运算算法。

void DestoryGraph(AdjGraph*&G) {
	ArcNode*pre, *p;
	for (int i = 0; i < G->n; i++) {
		pre = G->adjlist[i].firstarc;
		if (pre != NULL) { //保证头结点不为空
			p = pre->nextarc; //链表的销毁方法
			while (p != NULL) {
				free(pre);
				pre = p;
				p = pre->nextarc;
			}
			free(pre);
		}
	}
	free(G);//释放头结点
}

完整代码如下:(邻接表存储)

 

#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#define InofType char//顶点其它信息
#define MAXV 100//MAXV为最大顶点个数
/*
#define INF 32767//定义无穷

//邻接矩阵存储:n个顶点,n*n型矩阵,i行n列指第i个对第j个之间的关系
//有边记权值,没有边记0

//顶点信息
typedef struct
{
	int no;//顶点编号
	InofType inof;
}VertexType;

typedef struct
{
	VertexType vexs[MAXV];//存放顶点信息
	int edges[MAXV][MAXV];//邻接矩阵数组
	int n,e;//顶点数,边数
}MatGraph;
 */

//边结点(类似于链表)
typedef struct ANode {
	struct ANode *nextarc;
	int weight;//该条边的权重
	int adjvex;//该条边的邻接点编号
} ArcNode;

//头结点
typedef struct Vnode {
	ArcNode*firstarc;//上述边界点链表的头结点
	InofType inof;
} VNode;

//图
typedef struct {
	VNode adjlist[MAXV];//头结点
	int n, e; //顶点数,边数
} AdjGraph;

void CreatAdj(AdjGraph *&G, int A[MAXV][MAXV], int n, int e) {
	G = (AdjGraph*)malloc(sizeof(AdjGraph));

	for (int i = 0; i < n; i++) {
		G->adjlist[i].inof = 'A' + i;
		G->adjlist[i].firstarc = NULL; //将每个链表的头结点指针域置为空
	}

	ArcNode *p;
	for (int i = 0; i < n; i++) {
		for (int j = n - 1; j >= 0; j--) { //头插法,倒叙
			p = (ArcNode*)malloc(sizeof(ArcNode));
			p->adjvex = j; //存放邻接点
			p->weight = A[i][j]; //存放权重

			p->nextarc = G->adjlist[i].firstarc; //头插法
			G->adjlist[i].firstarc = p;
		}
	}
	G->e = e;
	G->n = n;
}

void DispAdj(AdjGraph*G) {
	ArcNode*p;
	for (int i = 0; i < G->n; i++) {
		p = G->adjlist[i].firstarc;
		printf("%3d: ", i);
		while (p != NULL) {
			printf("%3d[%d]", p->adjvex, p->weight);
			p = p->nextarc;
		}
		printf("\n");
	}
}

void DestoryGraph(AdjGraph*&G) {
	ArcNode*pre, *p;
	for (int i = 0; i < G->n; i++) {
		pre = G->adjlist[i].firstarc;
		if (pre != NULL) { //保证头结点不为空
			p = pre->nextarc; //链表的销毁方法
			while (p != NULL) {
				free(pre);
				pre = p;
				p = pre->nextarc;
			}
			free(pre);
		}
	}
	free(G);//释放头结点
}
int main() {
	int A[MAXV][MAXV];
	memset(A, 0, sizeof(A));
	A[0][1] = 2; //给矩阵A赋一些有意义的值,表示图的连接情况和权重
	A[0][2] = 4;
	A[1][2] = 3;
	A[2][0] = 5;
	A[2][1] = 6;

	AdjGraph *G;
	CreatAdj(G, A, 3, 5);

	DispAdj(G);

	DestoryGraph(G);

	return 0;
}

参考书籍:李春葆《数据结构教程第六版》

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Daxiuy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值