数据结构 图(一)

图(一)


简单小知识

弧头和弧尾

在有向图中,箭头指向的一端被称为弧头,箭头发出的一端被称为弧尾。

入度和出度
在有向图中,一个顶点有几个发出箭头它就有几个出度,有几个指向它的箭头它就有几个入度,而顶点的度等于入度数和出度数的和。

(v1,v2)和<v1,v2>

(v1,v2)指的是无向图中v1和v2的关系,证明v1和v2是邻接点(若某两个顶点之间有边或者弧,则这两个顶点就为邻接点),而<v1,v2>指的是有向图中v1和v2的关系,证明v1、v2之间有一个箭头,并且是v1指向v2。

图和网

带权的叫网,不带的叫图。

根据特征分图

完全图:每个顶点(除自身外)与图中其他的顶点都有关系,没有方向的叫完全图,而有方向的叫有向完全图。特点: 具有n个顶点的完全图,边的数量为n(n-1)/2,有向完全图弧的数量为n(n-1)。
稀疏图、稠密图:边或者弧多的图叫稠密图,反之叫稀疏图。判断条件为:e<nlogn,其中 e 表示图中边(或弧)的数量,n 表示图中顶点的数量。如果式子成立,则为稀疏图;反之为稠密图。

连通图

无向图中,若任意两个顶点之间都至少存在一条路径,则这个无向图成为连通图。若无向图不是连通图,而它的某个子图符合连通的性质,则称这个子图为连通分量(这里的子图指最大的连通子图)。若整个无向图都是连通图,则不可能存在连通分量。
在有向图中,若任意两个顶点,都满足从一个顶点a到另一个顶点b和b到a连通,即至少有一条路径,则这个有向图为强连通图,强连通分量与连通分量定义相同。

连通图的生成树

定义:
1.包含连通图的所有顶点
2.任意两个顶点之间有且只有一条通路

生成树 边的数量=顶点数-1.

非连通图的生成森林

非连通图可以分解为多个连通分量,而每个连通分量会有一个生成树,所以所有生成树构成了非连通图的生成森林。


图的顺序存储结构
利用数组,邻接矩阵来解决问题,一维数组记录数据,二维数组(邻接矩阵)记录关系。。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>

#define max_NUM 20//顶点个数
#define VRType int//顶点之间关系变量
#define InfoType char//边或者弧之间额外信息指针变量
#define VertexType int//顶点数据

typedef enum{DG,DN,UDG,UDN}Graphkind;//枚举的类型

typedef struct
{
	VRType adj;//图:1相邻0否 网:权值
	InfoType* info;//边或者弧之间指针变量
}AreCell,AdjMatrix[max_NUM][max_NUM];

typedef struct
{
	VertexType vexs[max_NUM];//顶点数据
	AdjMatrix arcs;//二维数组记录顶点之间关系
	int vexnum, arcnum;//顶点数  边数
	Graphkind kind;//图的种类(枚举类型)
}MGraph;
//根据顶点数据,判断顶点在二维数组中的位置
int LocateVex(MGraph* G, VertexType v)
{
	int i = 0;

	for (; i < G->vexnum; i++)
	{
		if (G->vexs[i] == v)
		{
			break;
		}
	}
	if (i > G->vexnum)
	{
		printf("nu such vertex\n");
		return -1;
	}
	return i;
}
//有向图
void CreateDG(MGraph* G)
{
	scanf("%d %d", &G->vexnum, &G->arcnum);
	for (int i = 0; i < G->vexnum; i++)
	{
		scanf("%d", &G->vexs[i]);
	}
	for (int i = 0; i < G->vexnum; i++)
	{
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = 0;
			G->arcs[i][j].info = NULL;
		}
	}
	for (int i = 0; i < G->arcnum; i++)
	{
		int v1, v2;
		scanf("%d %d", &v1, &v2);//边|弧的头与尾
		int n = (LocateVex(G, v1));
		int m = (LocateVex(G, v2));
		if (n == -1 || m == -1)
		{
			printf("no such vertex\n");
			return;
		}
		G->arcs[n][m].adj = 1;
	}
}
//无向图
void CreateDN(MGraph* G)
{
	scanf("%d %d", &G->vexnum, &G->arcnum);
	for (int i = 0; i < G->vexnum; i++)
	{
		scanf("%d", &G->vexs[i]);
	}
	for (int i = 0; i < G->vexnum; i++)
	{
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = 0;
			G->arcs[i][j].info = NULL;
		}
	}
	for (int i = 0; i < G->arcnum; i++)
	{
		int v1, v2;
		scanf("%d %d", &v1, &v2);
		int n = LocateVex(G, v1);
		int m = LocateVex(G, v2);
		if (m == -1 || n == -1)
		{
			printf("no such vertex\n");
			return;
		}
		G->arcs[n][m].adj = 1;
		G->arcs[m][n].adj = 1;//无向图二阶矩阵主对角线对称
	}
}
//有向网
void CreateUDG(MGraph* G)
{
	scanf("%d %d", &G->vexnum, &G->arcnum);
	for (int i = 0; i < G->vexnum; i++)
	{
		scanf("%d", &G->vexs[i]);
	}
	for (int i = 0; i < G->vexnum; i++)
	{
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = 0;
			G->arcs[i][j].info = NULL;
		}
	}
	for (int i = 0; i < G->arcnum; i++)
	{
		int v1, v2, w;
		scanf("%d %d %d", &v1, &v2, &w);
		int n = (LocateVex(G, v1));
		int m = (LocateVex(G, v2));
		if (n == -1 || m == -1)
		{
			printf("no such vertex\n");
			return;
		}
		G->arcs[n][m].adj = w;
	}
}
//无向网
void CreateUDN(MGraph* G)
{
	scanf("%d %d", &G->vexnum, &G->arcnum);
	for (int i = 0; i < G->vexnum; i++)
	{
		scanf("%d", &G->vexs[i]);
	}
	for (int i = 0; i < G->vexnum; i++)
	{
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = 0;
			G->arcs[i][j].info = NULL;
		}
	}
	for (int i = 0; i < G->arcnum; i++)
	{
		int v1, v2, w;
		scanf("%d %d %d", &v1, &v2, &w);
		int n = LocateVex(G, v1);
		int m = LocateVex(G, v2);
		if (m == -1 || n == -1)
		{
			printf("no such vertex\n");
			return;
		}
		G->arcs[n][m].adj = w;
		G->arcs[m][n].adj = w;
	}
}
//选择图的类型
void CreateGraph(MGraph* G)
{
	scanf("%d", &G->kind);
	switch (G->kind)
	{
	case DG:
		return CreateDG(G);
		break;
	case DN:
		return CreateDN(G);
		break;
	case UDG:
		return CreateUDG(G);
		break;
	case UDN:
		return CreateUDN(G);
		break;
	defalut:
		break;
	}
}
//输出
void PrintGraph(MGraph G)//这里的G是结构体变量
{
	for (int i = 0; i < G.vexnum; i++)
	{
		for (int j = 0; j < G.vexnum; j++)
		{
			printf("%d ", G.arcs[i][j].adj);
		}
		printf("\n");
	}
}

int main()
{
	MGraph G;
	CreateGraph(&G);
	PrintGraph(G);
	return 0;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值