图的存储结构:邻接矩阵、邻接多重表

图有5种存储结构:邻接矩阵、邻接多重表、邻接表、边集数组、十字链表。

一、邻接矩阵

对于无权无向图:若顶点 i 与顶点 j 间有边,则 V[i][j] = V[j][i] = 1,若无边,则为0。V[i][i] 必为0。此时邻接矩阵必为对称矩阵。

在这里插入图片描述
对于无权有向图:若顶点 i 与顶点 j 间有边,则 V[i][j] = 1,若无边,则为0。V[i][i] 必为0。
在这里插入图片描述
对于有权有向图:若顶点 i 与顶点 j 间有边,则 V[i][j] = 权,若无边,则为无穷。V[i][i] 必为0。
在这里插入图片描述
邻接矩阵存在一个问题:当顶点多而边很少时,极大地浪费了空间。

//建立无向网图的邻接矩阵表示
typedef char VertexType;	//顶点类型
typedef int EdgeType;		//边的权值类型
#define MAXVEX 100			//最大顶点数
#define INFINITY 65535		//用65535来代表无穷

typedef struct
{
	VertexType vexs[MAXVEX];			//顶点表
	EdgeType arc[MAXVEX][MAXVEX];		//邻接矩阵
	int numVertexes, numEdges;			//图中当前的定点数和边数
}MGraph;

void CreateMGraph(MGraph* G)
{
	int i, j, k, w;
	printf("输入顶点数和边数:");
	scanf("%d,%d", G->numVertexes, G->numEdges);
	for (i = 0; i < G->numVertexes; i++)	//读入顶点信息,建立顶点表
	{
		scanf(&G->vexs[i]);
	}
	for (i = 0; i < G->numVertexes; i++)	//初始化
		for (j = 0; j < G->numEdges; j++)		
			G->arc[i][j] = INFINITY;
	for (k = 0; k < G->numEdges; k++)		//输入numEdges条边,建立邻接矩阵
	{
		printf("输入边(vi,vj)的下标 i 、下标 j 和权 w :");
		scanf("%d,%d,%d", &i, &j, &w);
		G->arc[i][j] = w;
		G->arc[j][i] = w;
	}
}

二、邻接表

用链表解决矩阵有太多无用空间的问题。

  1. 建立一个数组表示每一个顶点元素,每一个元素包含两部分,一是顶点数据,而是指向其边表头部的指针。
  2. 每个顶点的所有邻接表构成一个链表
    在这里插入图片描述
//建立无向网图的邻接矩阵表示
typedef char VertexType;		//顶点类型
typedef int EdgeType;			//边的权值类型
#define MAXVEX 100				//最大顶点数

typedef struct EdgeNode			//边表结点
{
	int adjvex;					//邻接点域,存储该点对应的下标
	EdgeType wight;				//存储权值,非网图可以不需要
	struct EdgeNode* next;		//链域,指向下一个邻接点
}EdgeNode;

typedef struct VertexNode		//顶点表结点
{
	VertexType data;			//顶点域,存储顶点信息
	EdgeNode* firstedge;		//边表头指针
}VertexNode, AdjList[MAXVEX];	

typedef struct
{
	AdjList adjList;
	int numVertexes, numEdges;	//图中当前顶点数和边数
}GraphAdjList;

void CreatGraph(GraphAdjList* G)
{
	int i, j, k;
	EdgeNode* e;
	printf("输入顶点数和边数:");
	scanf("%d,%d", &G->numVertexes, &G->numEdges);
	for (i = 0; i < G->numVertexes; i++)		//读入顶点信息,建立顶点表
	{
		scanf(&G->adjList[i]->data);			//输入顶点信息
		G->adjList->firstedge = NULL;			//将边表置位空表
	}
	for (k = 0; k < G->numEdges; k++)				//建立边表
	{
		printf("输入边(vi,vj)变上的顶点序号:");
		scanf("%d,%d", &i, &j);
		e = (EdgeNode*)malloc(sizeof(EdgeNode));	//向内存申请空间形成边表结点
		e->adjvex = j;								//邻接序号为j
		e->next = G->adjList[i].firstedge;			//将e指针至于 vi 的边表的第一个
		G->adjList[i].firstedge = e;				//

		e->adjvex = i;								//无向图是对称矩阵
		e->next = G->adjList[j].firstedge;
		G->adjList[j].firstedge = e;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值