图的概念,图的存储结构(邻接矩阵,邻接表)及相关算法

一. 图的相关概念和术语

概念

  1. 图形结构中,结点之间的关系可以是任意的,图中任意个数元素之间都可能相关。
  2. 任何复杂的图都是由顶点和边(弧)构成的。
  3. 采用形式化的定义,图G由两个集合V和E组成,记为G=(V,E),其中V是顶点的有限集合,记为V(G),E是连接V中两个不同顶点的边(弧)的有限集合,记为E(G).
  4. 对于含有n个顶点的图,通常用字母或自然数来唯一标识图中顶点(顶点的编号)。
    如在所给的图中,顶点可以使用字符Vi来表示,也可以用数字i(0<=i<=n-1)来表示第i个顶点Vi的编号。

无向图

  1. 对于一个图G,若边集E(G)为无向边,则称该图为无向图。如下图。
    在这里插入图片描述
  2. 在一个无向图中,若存在一条边 (i,j),则称顶点i,j为该边的两个顶点,并称它们互为邻接点(或者相邻点)。如上图,0和1互为邻接点。

有向图

  1. 对于一个图G,若边集E(G)为有向边,则称该图为有向图。如下图。
    在这里插入图片描述
  2. 在一个有向图中,若存在一条边(弧)<i,j>,则称此边(弧)是顶点(弧尾)i 的一条出边,同时也是顶点(弧头)j 的一条入边,称顶点 i 和 j 分别是此边的起始顶点(简称为起点)和终止顶点(简称为终点)。
    如上图,对于边<0,1>,该边是顶点0的出边,顶点1是入边,同时,顶点0称为起点,顶点1称为终点。
  3. 对于边<0,1>,则称顶点0“邻接到”顶点1,顶点1“邻接自”顶点0,弧<0,1>与顶点0和1“相关联”。

度,入度和出度

  1. 顶点v的度记为D(v)
  2. 对于无向图,每个顶点v的度定义为和v顶点相关联的边的数目。
  3. 对于有向图,顶点的度分为入度出度
  4. 入度是以该顶点为弧头(终点)的入边数目。
  5. 出度是以该顶点为弧尾(起点)的出边数目。
  6. 该顶点的度D(v)=其出度ID(v)+其入度OD(v)
    在这里插入图片描述
  7. 若一个图中(无论有向图还是无向图)中有n个顶点和e条边,每个顶点的度为Di(0<=i<=n-1),则有:
    在这里插入图片描述
    即一个图中所有顶点的度之和=边数的两倍。

子图

  1. 设有两个图G=(V,E)和G’=(V’,E’),若V’是V的子集,且E’是E的子集,则称G’是G的子图。
  2. 注:对于一个图G=(V,E),V’是V的子集,且E’是E的子集。而(V’,E’)可能不是一个图,所以由V的子集和E的子集并非一定构成G的子图。
    在这里插入图片描述

完全无向图和完全有向图

  1. 对于无向图,若具有n(n-1)/2条边,则称之为完全无向图。如左图。
  2. 对于有向图,若具有n(n-1)条边,则称之为完全有向图。如右图。
    在这里插入图片描述

稀疏图和稠密图

边数较少(边数e<<log2(n),其中n为顶点数)的图称为稀疏图,边数较多的称为稠密图。

简单路径,回路(环)

  1. 若一条路径的顶点序列中顶点不重复出现,则该路径为简单路径
  2. 若一条路径上的开始点和结束点为同一个顶点,则称该路径为回路(环)
  3. 除开始点和结束点相同外,其余顶点不重复出现的回路称为简单回路(简单环)

连通,连通图和连通分量(无向图)

  1. 无向图G中,若从顶点 i 到顶点 j 有路径,则称顶点 i 和 j 是连通的
  2. 若G中任意两个顶点都是连通的,则称无向图G为连通图,否则为非连通图。
  3. 无向图G中极大连通子图称为G的连通分量

强连通图和强联通分量(有向图)

  1. 有向图G中,若任意两个顶点 i 和 j 都是连通的,即从顶点 i 到 j 和从顶点 j 到 i 都存在路径,则称该图是强连通图
  2. 有向图G中极大强联通子图称为G的强联通分量

权和网

在一个图中,每条边可以标上具有某种含义的数值,该数值称为该边的,边上带权的图称为带权图,也称为。一般规定所有边的权均为非负数

二. 图的存储结构—邻接矩阵

邻接矩阵是表示顶点之间相邻关系的矩阵。设G=(V,E)是具有n个顶点的图,顶点编号依次为0,1,…,n-1,则G的邻接矩阵是具有如下定义的n阶方阵A。
若G是不带权的图:
在这里插入图片描述
若G是带权图或网:
在这里插入图片描述
Wij 为边(i,j)或<i,j>的权

无向图

在这里插入图片描述

  1. 无向图的矩阵一定是一个对称矩阵
  2. 每一行或每一列代表相应顶点的度

有向图

在这里插入图片描述

  1. 有向图的矩阵不一定是一个对称矩阵。
  2. 每一行代表相应顶点的出度
  3. 每一列代表相应顶点的入度

有权图(网)

在这里插入图片描述

  1. 有向图时不一定是一个对称矩阵。
  2. 入度和出度与有向图的计算方式一样。

图的邻接矩阵的特点

  1. 对于n个顶点e条边的图采用邻接矩阵存储时占据存储空间为O(n*n),与边数e无关(不考虑压缩存储),特别适合存储稠密图
  2. 任何图的邻接矩阵表示是唯一的。
  3. 图采用邻接矩阵存储时判断两个顶点 i 和 j 之间是否有边十分容易。

图的邻接矩阵类型声明

#define INF  INT_MAX    //用整型最大值代替∞ 
#define MAXVEX 30       //图中最大顶点个数 
typedef char VertexType[4]; //定义VertexType为字符串类型 

typedef struct vertex
{
	int adjvex;         //顶点编号 
	VertexType data;    //顶点的信息 
}VType;					//顶点类型 

typedef struct graph
{
	int n,el			//n为实际顶点数,e为实际边数 
	VType vexs[MAXVEX]; //顶点集合 
	int edges[MAXVEX][MAXVEX];  //边的集合 
}MGraph;				//图的邻接矩阵类型 

三. 图的存储结构—邻接表

  1. 邻接表是图的一种链式存储结构
  2. 在邻接表中,对图中每个顶点建立一个单链表,把该顶点的所有相邻点串起来。
  3. 所有的头指针构成一个数组,称为表头结点数组,用adjlist表示,第 i 个单链表adjlist[ i ] 中的结点表示依附于顶点 i 的边,也就是说头指针数组元素的下标与顶点编号一致。
  4. 表头结点的设置:
    在这里插入图片描述
  5. 单链表中的每个结点由3个域组成:
顶点域adjvex  :   用以指示该相邻点在头结点数组中的下标
权值域weight  :   存放对应边的权值
指针域naxtarc :   用以指向依附于顶点i的下一条边所对应的结点
  1. 对于不带权的图,weight域可以不设置;对于带权图,weight域设置为相应边的权值
    在这里插入图片描述

无向图

在这里插入图片描述
每个单链表的长度就是相应顶点的度

有向图

在这里插入图片描述

每个单链表的长度表示相应点的出度大小
对所有的单链表进行遍历可以计算出相应点的入度大小

有向图的逆邻接表

在有向图中求入度大小很麻烦,因此建立一个有向图的逆邻接表,即对每个顶点Vi建立一个链接以Vi为头的弧的表。
每条单链表的长度为相应点的入度大小

图的邻接表的特点

  1. 对于n个顶点e条边的图采用邻接矩阵存储时占据存储空间为O(n+e),与边数e有关,特别适合存储稀疏图
  2. 任何图的邻接矩阵表示不一定是唯一的。这是因为邻接表的每个单链表中,各结点的顺序是任意的。
  3. 图采用邻接表存储时查找一个顶点 的所有相邻顶点十分容易。

图的邻接表存储结构的类型声明

typedef char VertexType[10];  //VertexType为字符串类型 


typedef struct edgenode
{
	int adjvex;               //相邻点序号 
	int weight;				  //边的权值
	struct edgenode *nextatc; // 下一条边的顶点 
}ArcNode;					  //每个顶点建立的单链表中边结点的类型 


typedef struct vexnode
{
	VertexType data;		  //存放一个顶点的信息 
	ArcNode *firstarc;        //指向第一条边结点 
}VHeadNode;                   //单链表的头结点类型 

typedef struct
{
	int n,e;                  //n为实际顶点数,e为实际边数 
	VHeafNode adjlist[MAXVEX];//单链表头结点数组 
}ALGraph;                     //图的邻接表类型 

四. 邻接矩阵的相关算法

建立图的邻接矩阵算法

void CreateGraph(MGraph &g, int a[][MAXVEX],int n, int e)
{
	int i,j;
	g.n=n;
	g.e=e;
	for(i=0;i<n;i++)
	{
		for(j=0;j<n;j++)
		{
			g.edges[i][j]=A[i][j];
		}
	}
}

求无向图顶定度算法

int Degree(MGraph g, int v)
{
	int i,d=0;
	if(v<0 || v>=g.n)
		return -1;      //顶点编号错误返回-1 
	for(i=0;i<g.n;i++)
	{
		if(g.edges[v][i]>0 && g.edges[v][i]<INF)
			d++;       //统计第v行既不为0也不为∞的边数即度 
	}
	return d;
}

求有向图顶点度算法

int Degree(MGraph g, int v)
{
	int i,d1=0,d2=0,d;
	if(v<0 || v>=g.n)
		return -1;      //顶点编号错误返回-1 
	for(i=0;i<g.n;i++)
	{
		if(g.edges[v][i]>0 && g.edges[v][i]<INF)
			d1++;       //统计第v行既不为0也不为∞的边数即出度 
	}
	for(i=0;i<g.n;i++)
	{
		if(g.edges[i][v]>0 && g.edges[i][v]<INF)
			d2++;       //统计第v列既不为0也不为∞的边数即入度 
	}
	d=d1+d2;
	return d;
}

五. 邻接表的相关算法

建立图的邻接表算法

基本思路:
先创建邻接表头结点数组,并置所有头结点的firstarc为NULL。
遍历邻接矩阵数组A,当A[i][j]不等0且不等∞时,说明有一条从 i 到 j 的边,建立一个结点p,并置其adjvex域为j,其weight域为A[i][j],将p结点插入到顶点i的单链表头部

void CreateGraph(ALGraph *&G, int A[][MAXVEX],int n, int e)
{
	int i,j;
	ArcNode *p;
	G=(ALGraph *)malloc(sizeof(ALGraph));
	G->n=n;
	G->e=e;
	for(i=0;i<G->n;i++)    //邻接表中所有头结点的指针域置空 
		G->adjlist[i].firstarc=NULL;
	for(i=0;i<G->n;i++)    //检查A中每个元素 
	{
		for(j=G->n-1;j>=0;j--)
		{
			if(A[i][j]>0 && A[i][j]<INF)//存在一条边 
			{
				p=(ArcNode *)malloc(sizeof(ArcNode))//创建结点p 
				p->adjvex=j;
				p->weight=A[i][j];
				p->nextarc=G->adjlist.firstarc;  //头插法插入p 
				G->adhlist.firstarc=p;
			}
		}
	}
}

求无向图顶定度算法

int Degree(ALGraph *G, int v)
{
	int d=0;
	ArcNode *p;
	if(v<0 || v>=G->n)
		return -1;      //顶点编号错误返回-1 
	p=G->adjlist.firstarc; 
	while(p!=NULL)//统计v顶点的单链表中边结点个数即度
	{
		d++; 
		p=p->nextarc;
	}
	return d;
}

求有向图顶点度算法

int Degree(ALGraph *G, int v)
{
	int i,d1=0,d2=0,d;
	ArcNode *p;
	if(v<0 || v>=G->n)
		return -1;      //顶点编号错误返回-1 
	p=G->adjlist.firstarc; 
	while(p!=NULL)//统计v顶点的单链表中边结点个数即出度
	{
		d1++; 
		p=p->nextarc;
	}
	for(i=0;i<G->n;i++)//统计边结点中adjvex为v的个数即入度
	{
		p=G->adjlist.firstarc; 
		while(p!=NULL)
		{
			d2++; 
			p=p->nextarc;
		}
	}
	d=d1+d2;
	return d;
}
  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值