1、第七章 图,四类基本结构:,1.线性结构,2.树形结构,3.图状结构,4.集 合,7.1 图的定义与基本术语 7.2 图的存储结构 7.3 图的遍历 7.4 图的应用 生成树 拓扑排序 关键路径 最短路径,本章主要内容,7.1 图的定义与基本术语,图是由顶点非空集合 V 和两个顶点之间关系的集合R构成的数据结构Graph = (V , R ),1. 图的定义:,其中: V=|vDataObject R=VRVR=| P(v,w) 且 (v,wV) 表示从 v 到 w 的一条弧,并称 v 为弧尾,w 为弧头。 P(v,w) 定义了弧 的意义或信息, 表示从v到w的一条单向通道。,图的抽象数据类型
2、定义,ADT Graph 数据对象V:数据关系R基本操作:1. CreatGraph(G); 2. DestroyGraph(G);3. LocateVertex(G, v); 4. GetVertex(G, i); 5. InsertVertex(G, u); ADT Graph,R=VR VR=| P(v,w) (v,wV ),一个集合,该集合中的所有元素具有相同的特性。,了解各种操作的功能即可,有向图:,由顶点集和弧集构成的图为有向图。,例如:,其中 顶点集V1=A, B, C, D, E 关系集VR1=, , , , , , ,在有向图中,若表示从 x 到 y 的一条弧,并称x 为弧尾
3、,y 为弧头。,“弧”是有方向的 ,无向图:,由顶点集和边集构成的图为无向图。,例如:,其中 顶点集V1=A, B, C, D, E, F 关系集VR1=(A,B),(A,E),(B,E),(C,D),(D,F),(B,F),(C,F),在图中,若VR 必有VR, 则称(x,y)为顶点x和顶点y之间存在一条边。,“边”是无方向的= ,网、子图 完全图、稀疏图、稠密图 邻接点、度、入度、出度 路径、路径长度、简单路径、简单回路 连通图、连通分量、 强连通图、强连通分量 生成树、生成森林,2. 名词和基本术语:,有向网:,有向图中的弧带权后的图称作有向网。,无向网:,无向图中的边带权后的图称作无向
4、网。,15,3,7,21,11,9,2,15,7,9,19,3,2,21,有向网,无向网,2. 名词和基本术语:,2. 名词和基本术语:,例如:,子图:设图G=(V,VR) 和图 G=(V,VR),且 VV, VRVR,则称 G 为 G 的子图,A,无向完全图:,含 e=n(n-1)/2 条边的无向图。,有向完全图:,含 e=n(n-1) 条弧的有向图。,2. 名词和基本术语:,假设图中有 n 个顶点,e 条边,则,若边或弧的个数 enlogn,则称作稀疏图, 否则称作稠密图,2. 名词和基本术语:,对于无向图,若顶点x 和y 之间存在一条边(x,y), 则称顶点x 和y 互为邻接点,称边(x
5、,y)依附于顶点x 和y 或边(x,y)与顶点x 和y相关联。,与顶点x 关联的边的数目定义为x的度(TD)。,例如:,TD(B) = ?,TD(A) = ?,2,3,2. 名词和基本术语:,对于有向图,若顶点x 和y 之间存在一条弧, 则称顶点x 和y 互为邻接点,称弧与顶点x 和y相关联。,例如:,OD(B) = ?,ID(B) = ?,2,1,以x为尾的弧的数目定义为x的出度(OD),以x为头的弧的数目定义为x的入度(ID)。,出度+入度=该顶点的度(TD),TD(B) = ?,3,2. 名词和基本术语:,设图G=(V,VR)中的 u=vi,0,vi,1, , vi,m=w顶点序列中,
6、有 (vi,j-1,vi,j)VR 1jm, 则称从顶点u到顶点w之间存在一条路径。路径上边的数目称作路径长度,有向图的路径也是有向的。,路径:A,E,C,D,B,C,D,路径长度为: ?,6,例如:,2. 名词和基本术语:,回路:首尾顶点相同的路径。,B,C,D,B,A,E,C,D,B,C,D,A,简单路径:顶点不重复的路径。,A,E,C,D,简单回路:中间顶点不重的回路,A,E,C,D,A,连通图:若无向图G中任意两个顶点之间都 有路径相通。,例如:,连通分量:若无向图为非连通图,则图中各个极大连通子图称作此图的连通分量。,A,B,C,D,E,F,2. 名词和基本术语:,注:1.任何连通图
7、的连通分量只有一个, 即其自身2.非连通图的无向图有多个连通分量,强连通图:若有向图, 若任意两个顶点之间都存在一条有向路径。,例如:,强连通分量:若有向图不是强连通图,则图中各个极大强连通子图称作它的强连通分量。,2. 名词和基本术语:,注:1.强连通图的强连通分量只有一个,即其自身2.非强连通图的有向图有多个强连通分量,n个顶点的强连通图至少有 ? 条弧,B,A,C,D,n,生成树:假设一个连通图有 n 个顶点和 e 条边, 其中 n-1 条边和 n 个顶点构成一个极小连通子图, 称该极小连通子图为此连通图的生成树。,2. 名词和基本术语:,B,A,C,D,F,E,生成森林:对非连通图,则
8、称由各个连通分量的生成树的集合为此非连通图的生成森林。,2. 名词和基本术语:,A,B,C,D,E,F,7.2 图的存储结构,图的存储方式,一、图的数组(邻接矩阵)存储表示,二、图的邻接表存储表示,三、有向图的十字链表存储表示,四、无向图的邻接多重表存储表示,一、图的数组(邻接矩阵)存储表示,定义:矩阵的元素为,一维数组:,二维数组:,用于存储顶点信息。,用于存储图中顶点之间关联关系,无向图,TD(Vi) :,对 称 矩 阵,第i行非零元素的个数,或 第i列非零元素的个数,1,1,1,1,1,1,1,1,1,1,一、图的数组(邻接矩阵)存储表示,定义:矩阵的元素为,一维数组:,二维数组:,用于
9、存储顶点信息。,用于存储图中顶点之间关联关系,OD(Vi) : ID(Vi) :,非 对 称 矩 阵,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,第i行非零元素的个数 第i列非零元素的个数,有向图,一、图的数组(邻接矩阵)存储表示,定义:矩阵的元素为,一维数组:,二维数组:,用于存储顶点信息。,用于存储图中顶点之间关联关系,OD(Vi) : ID(Vi) :,非 对 称 矩 阵,0,0,0,1,1,0,0,0,0,0,0,0,0,1,1,0,第i行非零元素的个数 第i列非零元素的个数,有向图,一、图的数组(邻接矩阵)存储表示,定义:矩阵的元素为,一维数组:,二维数组:,用于
10、存储顶点信息。,用于存储图中顶点之间关联关系,邻接矩阵,无向网,wij,33,4,19,33,14,11,21,4,14,6,6,6,5,11,6,5,16,19,21,16,对 称 矩 阵,一、图的数组(邻接矩阵)存储表示,定义:矩阵的元素为,一维数组:,二维数组:,用于存储顶点信息。,用于存储图中顶点之间关联关系,邻接矩阵,21,7,11,2,3,9,15,有向网,非 对 称 矩 阵,.存储空间,.便于运算,无向图:,n(n-1)/2,有向图(网):,n2,无向图:,有向图(网):,一、图的数组(邻接矩阵)存储表示,特点:,一、图的数组(邻接矩阵)存储表示,#define MAX 20 t
11、ypedef enumDG,DN,UDG,UDNGraphKind; typedef char VertexData; typedef ArcNode int adj;OtherInfo info; ArcNode; typedef struct ArcNode arcsMAXMAX;int vernum, arcnum;GraphKind kind; MGraph;,VertexData vertexMAX;,一、图的数组(邻接矩阵)创建函数,操作步骤: 输入各顶点 邻接矩阵的初始化(图是0,网是INFINITY) 创建边或弧 确定顶点v1,v2的位置i, j 有向图: 有向网: 无向图:无
12、向网:,G.arcsij.adj=1; G.arcsij.adj=weight; G.arcsij.adj=1; G.arcsji.adj=1; G.arcsij.adj=weight; G.arcsji.adj=weight;,一、图的数组(邻接矩阵)创建函数,void CreatDG(MGraph /*创建边*/ ,一、图的数组(邻接矩阵)创建函数,/*创建边*/ for(k=0;kG.arcnum;k+)flushall();printf(“please input v1,v2:“);scanf(“%c%c“,一、图的数组(邻接矩阵)打印函数,void OutPut(MGraph G)
13、int i,j;for(i=0;iG.vernum;i+)printf(“t%c“,G.vertexi);for(i=0;iG.vernum;i+) printf(“n%ct“,G.vertexi);for(j=0;jG.vernum;j+)printf(“%dt“,G.arcsij.adj);printf(“n“); ,一、图的数组(邻接矩阵),练习: 1. 求出图G中每个结点的入度; 2. 求出图G中每个结点的出度; 3. 判断图G中是否存在边v1,v2。,一、图的数组(邻接矩阵),1. 求结点的入度、出度,void DegreeDG(MGraph G, int od, int id) i
14、nt i,j;for(i=0;iG.vernum;i+) for(j=0;jG.vernum;j+)if(G.arcsij.adj!=0)odi+;for(j=0;jG.vernum;j+) for(i=0;iG.vernum;i+)if(G.arcsij.adj!=0)idj+; ,odi=0;,idj=0;,一、图的数组(邻接矩阵),3. 判断是否存在边v1,v2,int IsExist(MGraph G,VertexData v1,VertexData v2) int i,j;i=Locate(G,v1);j=Locate(G,v2);if(G.arcsij.adj!=0)return
15、1;elsereturn 0; ,.表头结点,.表结点,表头结点:所有表头结点以顺序结构存储。 边表:对图中每个顶点建立一个单链表,第i个单链表中的结点表示依附于顶点vi的边。,图,网,二、图的邻接表表示法,二、图的邻接表表示法,无向图,E,D,C,B,A,二、图的邻接表表示法,D,C,B,A,D,C,B,A,可见,在有向图的邻接表中不易找到以该顶点为弧头的弧。,邻接表,逆邻接表,有向图,二、图的邻接表表示法,E,D,C,B,A,有向网,二、图的邻接表表示法,#define MAX 20 #define enumDG,DN,UDG,UDNGraphKind; typedef struct Ar
16、cNode int adj;struct ArcNode *nextarc; OtherInfo info; ArcNode; typedef struct VertexNode VertexData data;struct ArcNode *firstarc; VertexNode; typedef struct VertexNode vertexMAX;int vernum, arcnum;GraphKind kind; ALGraph;,一、图的邻接表创建函数,操作步骤: 输入各顶点 邻接表的初始化(表头数组的初始化) 创建边或弧 确定顶点v1,v2的位置i, j 有向图或有向网:无向图
17、或无向网:,开辟空间,在G.vertexi连接结点;开辟空间,在G.vertexi连接结点; 开辟空间,在G.vertexj连接结点;,一、图的邻接表创建函数,void CreatDG(ALGraph /*创建边*/ ,一、图的邻接表创建函数,for(k=1;kadj=j;s-nextarc=NULL;/*插入结点s*/ ,一、图的邻接表创建函数,for(k=1;kadjj) s-nextarc=p;G.vertexi.firstarc=s;else while(p-nextarc ,一、图的邻接表打印函数,void OutPutDG(ALGraph G) int i;ArcNode *p;f
18、or(i=1;iadj);p=p-nextarc;printf(“n“); ,一、图的邻接表,练习: 1. 求出图G中每个结点的入度; 2. 求出图G中每个结点的出度; 3. 判断图G中是否存在边v1,v2。,一、图的邻接表,1. 求结点的入度、出度,void Degree(ALGraph G,int od, int id) int i,j;ArcNode *p;for(i=1;iadj;idj+;p=p-nextarc; ,p=G.vertexi.firstarc;,一、图的邻接表,3. 判断是否存在边v1,v2,int IsExist(ALGraph G,VertexData v1,Ver
19、texData v2) int i,j;ArcNode *p;i=Locate(G,v1);j=Locate(G,v2);p=G.vertexi.firstarc;while(p ,特点:,二、图的邻接表表示法,无向图:,TD(vi)= 第i个单链表上结点的个数,有向图(网):,OD(vi) =第i个单链表上结点的个数,ID(vi)扫描整个邻接表,逆邻接表,.存储空间,.便于运算,无向图:,n+2e,有向图(网):,n+e,三. 图的两种存储结构比较,第i个单链表上结点的个数: OD(Vi) 采用邻接矩阵比邻接表更方便,第i行: OD(Vi),第i列: ID(Vi), TD(Vi)= ID(V
20、i)+ OD(Vi),第i个单链表上结点的个数,第i行: TD(Vi) 或第i列: TD(Vi),稀疏图,稠密图,不唯一,唯一,7.3 图的遍历,遍历: 从图中某个顶点出发遍历图,访遍图中其余顶点,并且使图中的每个顶点仅被访问一次的过程。,深度优先搜索DFS,广度优先搜索BFS,1. 基本概念,一.深度优先搜索DFS基本思想,从图中某个顶点V0 出发,访问此顶点,然后依次从V0的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和V0有路径相通的顶点都被访问到。,连通图的深度优先搜索遍历,V,w1,SG1,SG2,SG3,W1、W2和W3 均为 V 的邻接点,SG1、SG2 和 SG3
21、分别为含顶点W1、W2和W3 的子图。,访问顶点 V : for (W1、W2、W3 )若该邻接点W未被访问,则从它出发进行深度优先搜索遍历。,w2,w3,w2,类似于树的先根次序遍历,深度优先搜索,例:,A,B,C,A,B,C,F,E,F,E,G,G,D,D,H,H,I,I,回到A 结束!,深 度 优 先 搜 索 树,一.深度优先搜索DFS基本思想,解决的办法是:,如何判别V的邻接点是否被访问?,访问标志:,访问次序:,A,C,H,D,E,K,F,F,E,K,D,H,C,A,T,T,T,T,T,T,T,一.深度优先搜索DFS基本思想,遍历结果还可以为: 从示意图出发,遍历结果不唯一。,E,K
22、,F,D,H,C,A,从A出发,深度优先遍历 顺序为:,B,A,C,D,F,E,A,E,B,F,D,C,一.深度优先搜索DFS基本思想,B,A,C,D,F,E,遍历结果还可以为: 从示意图出发,遍历结果不唯一。,D,C,F,E,B,A,从A出发,深度优先遍历 顺序为:,A,B,E,F,C,D,B,A,C,D,F,E,一.深度优先搜索DFS基本思想,T,T,T,T,T,T,问题: 从存储结构出发, 遍历结果唯一吗? 答案:唯一,一.深度优先搜索DFS基本思想,首先将图中每个顶点的访问标志设为 FALSE, 之后搜索图中每个顶点,如果未被访问,则以该顶点为起始点,进行深度优先搜索遍历,否则继续检查
23、下一顶点。,非连通图的深度优先搜索遍历,访问标志:,访问次序:,A,C,H,D,E,I,F,B,G,G,B,F,E,I,D,H,C,A,T,T,T,T,T,T,T,T,T,一.深度优先搜索DFS基本思想,#define TRUE 1 #define FALSE 0 int visitedMAX_VERTEX_NUM; void DFS(MGraph G, int vi) int vj;visit(G,vi);visitedvi=TRUE;vj=0;while(vjG.vernum)DFS(G,vj);vj+; ,一.深度优先搜索DFS,printf(“%c “,G.vertexi);,if(!
24、visitedvj & G.arcsvivj.adj=1),邻接矩阵存储形式,void TraverseDFS(MGraph G) int i;for(i=0;iG.vernum;i+)visitedi=FALSE;for(i=0;iG.vernum;i+)if(!visitedi)DFS(G,i); ,一.深度优先搜索DFS,邻接矩阵存储形式,#define TRUE 1 #define FALSE 0 int visitedMAX_VERTEX_NUM; void DFS(ALGraph G, int vi) ArcNode *p;visit(G,vi);visitedvi=TRUE;p=
25、G.vertexvi.firstarc;while(p) DFS(G,p-adj);p=p-nextarc; ,一.深度优先搜索DFS,printf(“%c “,G.vertexi.data);,if(!visitedp-adj),邻接表存储形式,void TraverseDFS(ALGraph G) int i;for(i=0;iG.vernum;i+)visitedi=FALSE;for(i=0;iG.vernum;i+)if(!visitedi)DFS(G,i); ,一.深度优先搜索DFS,邻接表存储形式,类似于树的层次遍历,连通图的深度优先搜索遍历,二.广度优先搜索BFS,.从图中某个
26、顶点v0出发,首先访问v0 ;,.依次访问v0各个未被访问的邻接点;,.分别从这些邻接点出发,依次访问它们的各个未被访问的邻接点。访问时应保证:如果vi和vk为当前端结点,且vi在vk之前被访问,则vi的所有未被访问的邻接点应在vk 所有未被访问的邻接点之前访问。重复 ,直到所有端结点均没有未被访问的邻接点为止。,例如:,A,B,D,E,C,G,F,H,I,广 度 优 先 搜 索 树,广度优先搜索,需要辅助队列Q,以便实现访问时应保证的一点!,二.广度优先搜索BFS,解决的办法是:,A,B,E,D,C,F,G,H,I,从A出发,广度优先遍历 顺序为:,A,E,C,B,F,D,二.广度优先搜索B
27、FS基本思想,B,A,C,D,F,E,从A出发,广度优先遍历 顺序为:,A,B,C,E,F,D,2,5,3,一.深度优先搜索BFS基本思想,B,A,C,D,F,E,T,T,T,T,T,T,#define TRUE 1 #define FALSE 0 int visitedMAX_VERTEX_NUM; void TraverseBFS(MGraph G) int i;for(i=1;i=G.vernum;i+)visitedi=FALSE;for(i=1;i=G.vernum;i+)if(!visitedi)BFS(G,i); ,邻接矩阵存储形式,二.广度优先搜索BFS,邻接矩阵存储形式,二.
28、广度优先搜索BFS,void BFS(MGraph G, int vi) int v, i; SqQueue Q; InitQueue(Q); visit(G,vi);visitedvi=TRUE;EnQueue(Q,vi);while(!IsEmpty(Q) i=0;while(iadj);i+; ,void visit(ALGraph G, int i) printf(“%c “,G.vertexi); ,DeQueue(Q,v);,if(!visitedi & G.arcsvi.adj=1),#define TRUE 1 #define FALSE 0 int visitedMAX_VE
29、RTEX_NUM; void TraverseBFS(ALGraph G) int i;for(i=1;i=G.vernum;i+)visitedi=FALSE;for(i=1;i=G.vernum;i+)if(!visitedi)BFS(G,i); ,邻接表存储形式,二.广度优先搜索BFS,邻接表存储形式,二.广度优先搜索BFS,void BFS(ALGraph G, int vi) int v; ArcNode *p;SqQueue Q; InitQueue(Q); visit(G,vi);visitedvi=TRUE;EnQueue(Q,vi);while(!IsEmpty(Q) p=G
30、.vertexv.firstarc;while(p) visit(G,p-adj);visitedp-adj=TURE;EnQueue(Q,p-adj);p=p-nextarc; ,void visit(ALGraph G, int i) printf(“%c “,G.vertexi.data); ,DeQueue(Q,v);,if(!visitedp-adj),7.4 图的应用,图中两个顶点之间是否存在路径,无向图的连通分量,图的生成树与最小生成树,图的连通性问题2. 有向无环图的应用3. 最短路径问题,拓扑排序,关键路径,可以利用图的遍历来判断一个图是否连通,如果 在遍历的过程中,不止一次
31、调用搜索过程,则说 明该图就是一个非连通图,并且几次调用搜索过 程,表明该图就有几个连通分量。,1.图的连通性问题,无向图的连通分量,A,B,D,C,I,E,F,G,H,J,void TraverseDFS(ALGraph G) int i;for(i=1;i=G.vernum;i+)visitedi=FALSE;for(i=1;i=G.vernum;i+)if(!visitedi)printf(“n“);DFS(G,i); ,1.图的连通性问题,无向图的连通分量,void TraverseBFS(ALGraph G),BFS(G,i),int DFS_IsPath(MGraph G, Ver
32、tex v1, Vertex v2) int i,j;for(i=0;iG.vernum;i+)visitedi=FALSE;i=Locate(G,v1);j=Locate(G,v2);DFS_Path(G,i);if(visitedj=FALSE)return 0;elsereturn 1; ,1.图的连通性问题,图中两个顶点之间是否存在路径,生成树:若图G是连通图,从图中某一顶点出发遍历图时,图中所有的顶点加上遍历时经过的边所构成的子图称为生成树。如果在生成树中加一条边,必定构成一个环。,1. 基本概念:,B,A,C,D,F,E,某连通图有n 个顶点,则其生成树应该有 ? 条边,n-1,生
33、成森林:对非连通图,则称由各个连通分量的生成树的集合为此非连通图的生成森林。,A,B,C,D,E,F,1. 基本概念:,1、深度优先生成树(生成森林) 2、广度优先生成树(生成森林),假设要在 n 个城市之间建立通讯联络网,则连通 n 个城市只需要修建 n-1条线路,如何在最节省经费的前提下建立这个通讯网?,最小生成树的问题提出:,构造网的一棵最小生成树,即:,该问题等价于:,在 e 条带权的边中选取 n-1 条边(不构成回路),使“权值之和”为最小。,算法二:(克鲁斯卡尔算法),算法一:(普里姆算法),尽可能选取权值小的边,但不能构成回路。 选取n-1条恰当的边以连接网的n个顶点。,最小生成
34、树的要解决的两个问题:,取图中任意一个顶点 v 作为生成树的根,之后往生成树上添加新的顶点 w。 在添加的顶点 w 和已经在生成树上的顶点v 之间必定存在一条边,并且该边的权值在所有连通顶点 v 和 w 之间的边中取值最小。 之后继续往生成树上添加顶点,直至生成树上含有 n 个顶点为止。,2.普里姆算法的基本思想:,E,A,F,B,D,C,所得生成树权值和 = 1+4+2+5+3 = 15,5,3,4,2,1,2.普里姆算法的基本思想:,生长法,在生成树的构造过程中,图中 n 个顶点分属两个集合:已落在生成树上的顶点集 U 和尚未落在生成树上的顶点集V-U ,则应在所有连通U中顶点和V-U中顶
35、点的边中选取权值最小的边。,一般情况下所添加的顶点应满足下列条件:,U,V-U,2.普里姆算法的基本思想:,设N=(V, E)是连通网,TE是N上最小生成树 中边的集合。初始U= u0, (u0V), TE= , 然后重复执行下述运算:,在所有uU,vV-U的边(u, v)E中,找一 条代价最小的边(u0,v0)并入集合TE,同时v0 并入U,直到U=V,则可生成一棵具有最小代 价的生成树 T=(V, TE)。,连通网用带权的邻接矩阵表示,并设置一个辅助数组closedge , 数组元素下标对应当前V-U集中的顶点序号,元素值则记录该顶点和 U集中相连接的代价最小(最近)边的顶点序号adjve
36、x和权值lowcost. 即对vV-U的每个顶点,closedgev记录所有与v邻接的、从U到V-U的那组边中的最小边的信息。,2.普里姆算法的基本思想:,辅助数组,A,1,A,5,A,0,6,A,A,B,C,D,E,F,4,F,2,C,5,C,6,C,C,F,3,B,B,D,E,A,E,A,F,B,D,C,5,3,4,1,2,0,0,0,0,0,对 称 矩 阵,2.普里姆算法的基本思想:,a,b,c,d,e,g,f,0,a,19,a,14,a,18,0,e,12,e,8,e,16,0,d,7,d,3,d,21,0,c,5,0,0,0,B,A,E,G,D,C,18,11,6,5,16,B,A,
37、E,G,D,C,18,11,5,6,16,图的生成树不唯一,从不同的顶点出发进行遍历,可以得到不同的生成树。 即使从相同的顶点出发,在选择最小边时,可能有多条同样的边可选,此时任选其一。,2.普里姆算法的基本思想:,具体做法: 先构造一个只含 n 个顶点的子图 SG,然后从权值最小的边开始,若它的添加不使SG 中产生回路,则在 SG 上加上这条边,如此重复,直至加上 n-1 条边为止。,考虑问题的出发点: 为使生成树上边的权值之和达到最小,则应使生成树中每一条边的权值尽可能地小。,3.克鲁斯卡尔算法的基本思想,合并法,3.克鲁斯卡尔算法的基本思想,1.所有的边按权值从小到大排序,5 (B,C)
38、,B,A,E,F,D,C,18,11,6,5,16,6 (B,D),6 (C,D),11 (B,E),14 (D,E),16 (A,B),18 (D,F),19 (A,F),21 (A,E),33 (E,F),2.顶点集合状态:,3.最小生成树边的集合:,所得生成树权值和 = 5+6+11+16+18 = 56,(B,C),(B,D),(B,E),(A,B),(D,F), A , B , C , D , E , F , B , C , B , C , D , B , C , D, E , B , C , D, E , A , B , C , D, E , A , F,B,A,E,F,D,C,1
39、8,11,6,5,16,B,A,E,F,D,C,18,11,5,6,16,图的生成树不唯一,从不同的顶点出发进行遍历,可以得到不同的生成树。 即使从相同的顶点出发,在选择最小边时,可能有多条同样的边可选,此时任选其一。,3.克鲁斯卡尔算法的基本思想,4. 最小生成树的方法比较,稠密图,稀疏图,7.4.2 拓扑排序,1. 拓扑排序问题引入,人们在实施一个复杂工程的时候,通常会将这个工程分为若干个简单的子工程(活动)分阶段进行,而这些子工程之间存在着一定的先后顺序。整个工程的实施的先后顺序可以用有向图来表示。在这种有向图中,用顶点表示活动,用有向边表示活动的先后顺序。Vi 必须先于活动Vj 进行。
40、用顶点表示活动,用弧表示活动间优先关系的有向图叫做顶点表示活动的网,简称AOV网 (Activity On Vertices)。,C1 高等数学C2 程序设计基础C3 离散数学 C1, C2 C4 数据结构 C2, C3C5 算法语言 C2C6 编译方法 C5, C4C7 操作系统 C4, C9C8 普通物理 C1C9 计算机原理 C8,课程代号,课程名称,先修课程,例如:计算机专业学生的学习就是一个工程,学生课程学习工程图,在AOV网络中不能出现有向回路,即有向环。在AOV网络中如果出现了有向环,则意味着某项活动应以自己作为先决条件,此AOV网络所代表的工程是不可行的。,检查有向图中是否存在
41、回路的方法之一,是对有向图进行拓扑排序。,2. 拓扑排序,例如:,可求得拓扑有序序列:,A B C D 或 A C B D,存在回路,活动互 为前驱。无法执行!,何谓“拓扑排序”?,对有向图进行如下操作:,按照有向图给出的次序关系,将图中顶点排成一个线性序列,对于有向图中没有限定次序关系的顶点,则可以人为加上任意的次序关系。由此所得顶点的线性序列称之为拓扑有序序列.,例如,对学生选课工程图进行拓扑排序,得到的拓扑有序序列为(不一定唯一)C1 , C2 , C3 , C4 , C5 , C6 , C8 , C9 , C7 或 C1 , C8 , C9 , C2 , C5 , C3 , C4 ,
42、C7 , C6,如何进行拓扑排序?,.从有向图中选取一个没有前驱的顶点,(入度为0 的顶点),并输出之;,.从有向图中删去此顶点以及所有以它为尾的弧;,重复上述两步,直至图中不存在没有前驱的顶点 所有顶点已输出,拓朴排序完成,说明图中不存在有向回路或 剩余的顶点入度都不为0(此时图中有环,拓朴排序不能进行下去)。,3. 拓扑排序,拓扑排序例如:,C,D,A,G,F,B,H,E,A,C,B,H,D,G,F,E,没有前驱的顶点 入度为零的顶点,删除顶点及它的出弧 弧头顶点的入度减1,在算法中需要用定量的描述替代定性的概念,三、拓朴排序算法描述,V1,V6,V4,V2,V5,V3,V6,V1,V4,
43、V5,V3,V2,拓扑序列:,三、拓朴排序算法描述,V6,V1,V4,V5,V3,V2,拓扑序列:,void TopSort_Stack(ALGraph G,int indegree) ArcNode *p; int i,count=0;SqStack S; InitStack(S);for(i=1;iadj=0)Push(S, p-adj);p=p-nextarc;if(countG.vernum) printf(“图中存在回路!n“); ,Pop(S,i);,indegreep-adj-;,1,1,1,1,三、拓朴排序算法描述,V1,V6,V4,V2,V5,V3,1,6,4,3,2,5,拓
44、扑序列:,0,0,0,0,1,1,1,1,4、拓朴排序算法描述,1,6,4,2,5,3,拓扑序列:,0,0,0,0,6,1,6,1,4,5,3,2,4,5,3,2,如何进行逆拓扑排序?,.从有向图中选取一个没有后继的顶点,(出度为0 的顶点),并输出之;,.从有向图中删去此顶点以及所有以它为头的弧;,重复上述两步,直至图中不存在没有后继的顶点 所有顶点已输出,拓朴排序完成,说明图中不存在有向回路或 剩余的顶点出度都不为0(此时图中有环,拓朴排序不能进行下去)。,5. 逆拓扑排序,C,D,A,G,F,B,H,E,E,F,H,G,B,D,C,A,没有后继的顶点 出度为零的顶点,删除顶点及它的入弧
45、弧尾顶点的出度减1,在算法中需要用定量的描述替代定性的概念,逆拓扑排序例如:,7.4.3 最短路径,从某顶点(源点)出发到另一顶点(目的点)的路径中,有一条各边(或弧)权值之和最小的路径称为最短路径。,.从单源点到其余各点的最短路径迪杰斯特拉算法(Dijkstra),.每一对顶点之间的最短路径弗洛伊德算法(floyd),带权有向图,最短路径 长度 (v0,v2) 10(v0,v4) 30(v0,v4,v3) 50(v0,v4,v3,v5) 60v0v1 无,求从源点到其余各点的最短路径的算法的基本思想:,依最短路径的长度递增的次序求得各条路径,v1,其中,从源点到顶点v的最短路径是所有最短路径
46、中长度最短者。,v2,源点,在这条路径上,必定只含一条弧,并且这条弧的权值最小。(设为v0v1),下一条路径长度次短的最短路径的特点:,路径长度最短的最短路径的特点:,它只可能有两种情况: 或者是直接从源点到该点(只含一条弧); 或者是从源点经过顶点v1,再到达该顶点(由两条弧组成)。,其余最短路径的特点:,再下一条路径长度次短的最短路径的特点:,它可能有三种情况: 或者是直接从源点到该点(只含一条弧); 或者是从源点经过顶点v1,再到达该顶点(由两条弧组成); 或者是从源点经过顶点v2,再到达该顶点。,它或者是直接从源点到该点(只含一条弧); 或者是从源点经过已求得最短路径的顶点, 再到达该顶点。,