图的定义及存储

1.图的定义

图是一种相对较为复杂的数据结构,由结点及各结点之间的相互关系组成。图中结点之间的关系可以是任意的,也就是说图中任何两个结点之间都可能是有关系的。图中的各个结点称为顶点(vertex)。图分为有向图和无向图。图一中左边是有向图,右边是无向图。


图一

2.图的存储结构

2.1数组表示法

数组表示法又称为邻接矩阵表示法,是用两个数组分别存储顶点信息和顶点之间的关系即边的信息。

#define VERTEXNUM 100 //存储顶点数目
typedef int VertexType;
typedef int EdgeType;
typedef struct
{
	VertexType vertexs[VERTEXNUM]; //顶点表
	EdgeType edges[VERTEXNUM][VERTEXNUM]; //邻接矩阵存储顶点间关系
	int vernum, edgenum; //图中当前的顶点和边数
}Graph;
邻接矩阵表示中建立邻接矩阵及输出程序如下:

#include <cstdio>
#include <cstdlib>

#define VERTEXNUM 100 //存储顶点数目
typedef int VertexType;
typedef int EdgeType;
typedef struct
{
	VertexType vertexs[VERTEXNUM]; //顶点表
	EdgeType edges[VERTEXNUM][VERTEXNUM]; //邻接矩阵存储顶点间关系
	int vernum, edgenum; //图中当前的顶点和边数
}Graph;

void MakeGraph(Graph *&graph)
{
	int v1, v2;
	int i, j, k;
	printf("请输入图的顶点数n和边数e:\n");
	scanf("%d%d", &graph->vernum, &graph->edgenum);
	printf("顶点编号设置为1~n.\n");
	for(i = 0; i < graph->vernum; i++)
	{
		graph->vertexs[i] = i + 1;
	}
	for(i = 0; i < graph->vernum; i++) //边信息初始化
	{
		for(j = 0; j < graph->vernum; j++)
		{
			graph->edges[i][j] = 0;
		}
	}

	printf("请输入每条边对应的两个顶点的序号(格式为i,j):\n");
	for(k = 0; k < graph->edgenum; k++)
	{
		scanf("%d,%d", &v1, &v2);
		
		graph->edges[v1 - 1][v2 - 1] = 1;
	}
}

int main()
{
	Graph *graph = (Graph *)malloc(sizeof(Graph));
	MakeGraph(graph);

	//输出邻接矩阵
	for(int i = 0; i < graph->vernum; i++)
	{
		for(int j = 0; j < graph->vernum; j++)
		{
			printf("%d ", graph->edges[i][j]);
		}
		printf("\n");
	}

	return 0;
}
2.2邻接表表示法

邻接表中,对图中每个顶点建立一个单链表,单链表i中的结点表示依附于顶点vi的边。将这些单个的单链表连接组成的链式存储结构就是图的邻接表(Adjacency List)。结构如下:

#define VERTEXNUM 100 //顶点个数
typedef int VertexType;
typedef int EdgeType;
typedef struct node
{
	int adjvex; //顶点位置
	struct node *next; //指向下一条边的指针
}EdgeNode;

typedef struct vnode
{
	VertexType vertex; //顶点信息
	EdgeNode *firstedge; //指向第一条依附该顶点的边的指针
}AdjList[VERTEXNUM];

typedef struct
{
	AdjList vertexs; //邻接表
	int vernum, edgenum; //图中当前的顶点和边数
}Graph;
建立邻接表及其输出程序如下:

#define VERTEXNUM 100 //顶点个数
typedef int VertexType;
typedef int EdgeType;
typedef struct node
{
	int adjvex; //顶点位置
	struct node *next; //指向下一条边的指针
}EdgeNode;

typedef struct vnode
{
	VertexType vertex; //顶点信息
	EdgeNode *firstedge; //指向第一条依附该顶点的边的指针
}AdjList[VERTEXNUM];

typedef struct
{
	AdjList vertexs; //邻接表
	int vernum, edgenum; //图中当前的顶点和边数
}Graph;

void MakeGraph(Graph *graph)
{
	int i, j, k;
	printf("请输入图的顶点数n和边数e:\n");
	scanf("%d%d", &graph->vernum, &graph->edgenum);
	printf("顶点编号设置为1~n.\n");
	for(i = 0; i < graph->vernum; i++)
	{
		graph->vertexs[i].vertex = i + 1;       //顶点编号为1~n
		graph->vertexs[i].firstedge = NULL; //初始第一条边为空
	}

	printf("请输入每条边对应的两个顶点的序号(格式为i,j):\n");
	EdgeNode *p;
	for(k = 0; k < graph->edgenum; k++)
	{
		scanf("%d,%d", &i, &j);  //读入边<vi,vj>的序号
		p = (node *)malloc(sizeof(node)); //生成新的结点
		p->adjvex = j;
		p->next = graph->vertexs[i - 1].firstedge;
		graph->vertexs[i - 1].firstedge = p;
	}
}

int main()
{
	Graph *graph = (Graph *)malloc(sizeof(Graph));
	MakeGraph(graph);

	EdgeNode *p;
	//输出邻接表
	for(int i = 0; i < graph->vernum; i++)
	{
		p = graph->vertexs[i].firstedge;
		while(p != NULL)
		{
			printf("%d ", p->adjvex);
			p = p->next;
		}
		printf("\n");
	}
	return 0;
}
2.3十字链表

十字链表可以看成是将有向图的邻接表和逆邻接表结合得到的一种链表。在十字链表中,因为容易找到以某顶点为尾的边,也容易找到以其为头的边,因而比较容易求得顶点的出度和入度。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值