- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
6.2.2
邻接表
边结点的结构为:
adjvex
next
adjvex是该边或弧依附的顶点在数组中的下 标,next是指向下一条边或弧结点的指针。
图 6-6
构成一维数组的顶点结构为: 顶点域 Vertex 边表头指针 firstedge 顶点表
Vertex 是顶点内容,firstedge是指向第一条边或弧结
6.2 图的存储结构
6.2.1 邻接矩阵
1. 有向图的邻接矩阵
具有n个顶点的有向图可以用一个nn的方形矩阵
表示。假设该矩阵的名称为M,则当<vi,vj>是该有向 图中的一条弧时,M[i,j]=1;否则M[i,j]=0。第i个顶点 的出度为矩阵中第i行中“1”的个数;入度为第i列中 “1”的个数,并且有向图弧的条数等于矩阵中“1”
阵中“1”的个数的一半,这是因为每条边在矩阵中描
述了两次。
图 6-4
图 6-5
在C 语言中,实现邻接矩阵表示法的类型定义如下所示: #define MaxVertexNum 100 /*最大顶点数设为100*/ typedef char VertexType; /*顶点类型设为字符型*/ typedef int EdgeType; /*边的权值设为整型*/ typedef struct { VertexType vexs[MaxVertexNum]; /*顶点表*/ EdgeType edges[MaxVertexNum][MaxVertexNum]; /*邻接矩阵,即边表*/ int n,e; /*顶点数和边数*/ }Mgragh; /*Maragh是以邻接矩阵存储的图类型*/
(3)顶点、边、弧、弧头、弧尾:图中,数据元素 vi称为顶点(vertex );P(vi, vj)表示在顶点vi和 顶点vj之间有一条直接连线。如果是在无向图 中,则称这条连线为边;如果是在有向图中, 一般称这条连线为弧。边用顶点的无序偶对 (vi, vj)来表示,称顶点vi和顶点vj互为邻接 点,边(vi, vj)依附于顶点vi与顶点vj;弧用 顶点的有序偶对<vi, vj>来表示,有序偶对的第 一个结点vi被称为始点(或弧尾),在图中就 是不带箭头的一端;有序偶对的第二个结点vj 被称为终点(或弧头),在图中就是带箭头的 一端。
(9)回路、简单路径、简单回路:序列中顶点不重复出 现的路径称为简单路径。路径中第一个顶点与最后一 个顶点相同的路径称为回路或者环(cycle)。除第一 个顶点与最后一个顶点之外,其他顶点不重复出现的 回路称为简单回路,或者简单环。
(10) 子图:对于图G=(V,E),G’=(V’,E’),若 存在V’是V的子集 ,E’是E的子集 ,则称图G’是G的 一个子图 (11)连通的、连通图、连通分量:在无向图中,如果从一 个顶点vi到另一个顶点vj(i≠j)有路径,则称顶点vi和vj是连 通的。如果图中任意两顶点都是连通的,则称该图是连通 图。无向图的极大连通子图称为连通分量。 (12)强连通图、强连通分量:对于有向图来说,若图中任 意一对顶点vi 和vj(i≠j)均有从一个顶点vi到另一个顶点vj有 路径,也有从vj到vi的路径,则称该有向图是强连通图。有 向图的极大强连通子图称为强连通分量。
的个数。
2. 无向图的邻接矩阵 具有n个顶点的无向图也可以用一个nn的方形矩 阵表示。假设该矩阵的名称为M,则当(vi,vj)是该无 向图中的一条边时,M[i,j]=M[j,i]=1;否则,
M[i,j]=M[j,i]=0。第i个顶点的度为矩阵中第i 行中“1”
的个数或第i列中“1”的个数。图中边的数目等于矩
点的指针。 在C语言中,实现邻接表表示法的类型定义如下所示: 邻接表表示的形式描述如下: #define MaxVerNum 100 /*最大顶点数为100*/
typedef struct node{ /*边表结点*/ int adjvex; /*邻接点域*/ struct node * next; /*指向下一个邻接点的指针域*/ /*若要表示边上信息,则应增加一个数据域info*/ }EdgeNode; typedef struct vnode{ /*顶点表结点*/ VertexType vertex; /*顶点域*/ EdgeNode * firstedge; /*边表头指针*/ }VertexNode; typedef VertexNode AdjList[MaxVertexNum]; /*AdjList是邻接 表类型*/ typedef struct{ AdjList adjlist; /*邻接表*/ int n,e; /*顶点数和边数*/ }ALGraph; /*ALGraph是以邻接表方式存储的图类型*/
复习
1.用邻接表表示法表示图a 2.用邻接矩阵表示法表示无向网b
图a
图b
答案
课堂练习
1若无向连通图G 具有n个顶点,则以下关于图G的叙述 中,错误的是(43)。 A. G 的边数一定多于顶点数 B.G 的生成树中一定包含n个顶点 C.从G 中任意顶点出发一定能遍历图中所有顶点 C.G 的邻接矩阵一定是n阶对称矩阵
建立一个图的邻接矩阵存储的算法如下: void CreateMGraph(MGraph *G) {/*建立有向图G的邻接矩阵存储*/ int i,j,k,w; char ch; printf("请输入顶点数和边数(输入格式为:顶点数,边数):\n"); scanf("%d,%d",&(G->n),&(G->e));/*输入顶点数和边数*/ printf("请输入顶点信息(输入格式为:顶点号<CR>):\n"); for (i=0;i<G->n;i++) scanf("\n%c",&(G->vexs[i])); /*输入顶点信息,建立 顶点表*/ for (i=0;i<G->n;i++) for (j=0;j<G->n;j++) G->edges[i][j]=0; /*初始化邻接矩阵*/ printf("请输入每条边对应的两个顶点的序号(输入格式为:i,j):\n"); for (k=0;k<G->e;k++) {scanf("\n%d,%d",&i,&j); /*输入e条边,建立邻接矩阵*/ G->edges[i][j]=1; /*若加入G->edges[j][i]=1;,*/ /*则为无向图的邻接矩阵存储建立*/ } }/*CreateMGraph*/
其形式化定义为: G=(V,E) V={vi| vi∈dataobject} E={( vi,vj)| vi, vj ∈V ∧P(vi, vj)}
其中,G表示一个图,V是图G中顶点的集合,E 是图G中边的集合,集合E中P(vi,vj)表示顶点vi和 顶点vj之间有一条直接连线,即偶对(vi,vj)表示一 条边。
(a)
(b)
图 6-1
2.图的相关术语
(1)无向图:在一个图中,如果任意两个顶点构成的偶对(vi, vj) ∈E是无序的,即顶点之间的连线是没有方向的,则称该图为无 向图。如图6.1(b)所示是一个无向图。 (2)有向图:在一个图中,如果任意两个顶点构成的偶对(vi, vj) ∈E是有序的,即顶点之间的连线是有方向的,则称该图为有向 图。如图6.1(a)所示是一个有向图
6.1.2
图的基本操作
(1) CreatGraph(G)输入图G的顶点和边,建立图G的存储。 (2)DestroyGraph(G)释放图G占用的存储空间。 (3)GetVex(G,v)在图G中找到顶点v,并返回顶点v的相关 信息。 (4)PutVex(G,v,value)在图G中找到顶点v,并将value值 赋给顶点v。 (5)InsertVex(G,v)在图G中增添新顶点v。 (6)DeleteVex(G,v)在图G中,删除顶点v以及所有和顶点 v相关联的边或弧。 (7)InsertArc(G,v,w)在图G中增添一条从顶点v到顶点w 的边或弧。 (8)DeleteArc(G,v,w)在图G中删除一条从顶点v到顶点w 的边或弧。 (9)DFSTraverse(G,v)在图G中,从顶点v出发深度优先遍 历图G。 (10)BFSTtaverse(G,v)在图G中,从顶点v出发广度优先 遍历图G。
6.3 图的遍历
常见的图遍历方式有两种:深度优先遍历和广度 优先遍历,这两种遍历方式对有向图和无向图均适用。
6.3.1 深度优先遍历
深度优先遍历的思想类似于树的先序遍历。其遍 历过程可以描述为:从图中某个顶点v出发,访问该顶 点,然后依次从v的未被访问的邻接点出发继续深度优 先遍历图中的其余顶点,直至图中所有与v有路径相通 的顶点都被访问完为止。
(7)边的权、网:与边有关的数据信息称为权 (weight)。在实际应用中,权值可以有某种含义。
边上带权的图称为网或网络(network)。
(8)路径、路径长度:顶点vp到顶点vq之间的路径 (path)是指顶点序列vp,vi1,vi2, …, vim,vq.。其中, (vp,vi1),(vi1,vi2),…,(vim,.vq)分别为图中的边。路径 上边的数目称为路径长度。
6.3.2 广度优先遍历 对图的广度优先遍历方法描述为:从图中某个顶 点v出发,在访问该顶点v之后,依次访问v的所有未被 访问过的邻接点,然后再访问每个邻接点的邻接点,
下面我们讨论一下如何实现深度优先算法。 为了便于在算法中区分顶点是否已被访问过,需要创 建一个一维数组visited[0..n-1](n是图中顶点的数目), 用来设置访问标志,其初始值visited[i](0≤i≤n-1)为 “0”,表示邻接表中下标值为i的顶点没有被访问过,一 旦该顶点被访问,将visited[i]置成“1”。 int visited[0..n-1]={0,0,...0}; void DFS(Graph G, int v ) { /*从第v个顶点出发递归地深度优先遍历图G*/ visited[v]=TRUE;VisitFunc(v); /*访问第v个顶点*/ for (w=FirstAdjVex(G,v);w; w=NextAdjVex(G,v,w)) if (!visited[w]) DFS(G,w); /*对v的尚未访问的邻 接顶点w递归调用DFS*/ }