收藏 分享(赏)

第7讲 图.ppt

上传人:jinchen 文档编号:9863129 上传时间:2019-09-12 格式:PPT 页数:91 大小:967KB
下载 相关 举报
第7讲 图.ppt_第1页
第1页 / 共91页
第7讲 图.ppt_第2页
第2页 / 共91页
第7讲 图.ppt_第3页
第3页 / 共91页
第7讲 图.ppt_第4页
第4页 / 共91页
第7讲 图.ppt_第5页
第5页 / 共91页
点击查看更多>>
资源描述

1、第7章 图,基 本 术 语,图是由一个顶点集V和一个边集VR构 成的数据结构 Graph = (V , VR ) 其中:VR| v,wV 且 P(v,w) 表示从 v 到 w 的一条边,并称 v 为起点,w 为终点P(v,w) 定义了弧 的意义或信息,由于“边”是有方向的,因此称由 顶点集和边集构成的图为有向图,例如:,G1 = (V1, VR1 ),其中: V1=A, B, C, D, E VR1=, , ,若有VR,必 有VR,则称 (v,w) 为顶点v和顶 点w之间存在一条 无向边,由顶点集和边集构成的图称作无向图,例如: G2=(V2,VR2 ) V2=A, B, C, D, E, F

2、 VR2=(A,B), (A,E),(B,E), (C,D), (D,F), (B,F), (C,F) ,A,E,F,设图G=( V,VR )和 图G=( V, VR ),且VV, VRVR, 则 称 G 为 G 的子图,边带权的图分别称作有向网或无向网,假设图中有 n 个顶点,e 条边,则,含有 e=n(n-1)/2 条边的无向图称作无向完全图,含有 e=n(n-1) 条边的有向图称作有向完全图,若边或弧的个数较少,则称作稀疏图,否则称作稠密图,假若顶点v 和顶点w 之间存在一条边,则称顶点v和w互为邻接点,边(v,w),ID(B) = 3,ID(A) = 2,和顶点v和w相关联和顶点v 关

3、联的边的数目定义为顶点的度,顶点的出度: 以顶点v为起点的边的数目,A,B,E,C,F,有向图,顶点的入度: 以顶点v为终点的边的数目,顶点的度(TD)= 出度(OD)+入度(ID),ID(B) = 2,OD(B) = 1,TD(B) = 3,设图G=(V,VR)中的一个顶点序列 u=vi,0,vi,1, , vi,m=w中, (vi,j-1,vi,j)VR 1jm, 则称从顶点u 到顶点w 之 间存在一条路径。路径上 边的数目称作路径长度,长度为3的路径A,B,C,F,简单路径:序列中顶点不重复出现的路径,简单回路:序列中只有第一个顶点和最后一个顶点相同,其它顶点不重复出现的路径,若图G中任

4、意两个顶点之间都有路径相通,则称此图为连通图,若无向图为非连通图,则图中各个极大连通子图称作此图的连通分量,若任意两个顶点之间都存在一条有向路径,则称此有向图为强连通图,对有向图,,否则,其各个强连通子 图称作它的强连通分量,假设一个连通图有n个顶点和e条边,其中n-1 条边和n个顶点构成一个极小连通子图,称该极小连通子图为此连通图的生成树,对非连通图,则称由各个连通分量的生成树的集合为此非连通图的生成森林,1StatusCode GetElem(int v, ElemType &e) const 初始条件:图已存在。 操作结果:求顶点的元素。 2StatusCode SetElem(int

5、v, const ElemType &e) 初始条件:图已存在。 操作结果:设置顶点的元素值。 3ElemType GetVexData(int v) const 初始条件:图已存在。 操作结果:返回顶点数据。,图基本操作,4int GetVexNum() const 初始条件:图已存在。 操作结果:返回顶点个数。 5int GetEdgeNum() const 初始条件:图已存在。 操作结果:返回边个数。 6int FirstAdjVex(int v) const 初始条件:图已存在,v是图顶点。 操作结果:返回顶点v的第一个邻接点。 7int NextAdjVex(int v1, int

6、v2) const; 初始条件:图已存在,v1和v2是图顶点,v2是v1的一个邻接点。 操作结果:返回顶点v1的相对于v2的下1个邻接点。,8void InsertEdge(int v1, int v2); 初始条件:图已存在,v1和v2是图顶点。 操作结果:插入顶点为v1和v2的边。 9void DeleteEdge(int v1, int v2); 初始条件:图已存在,v1和v2是图顶点。 操作结果:删除顶点为v1和v2的边。 10StatusCode GetTag(int v) const; 初始条件:图已存在,v是图顶点。 操作结果:返回顶点v的标志。 11StatusCode Set

7、Tag(int v, StatusCode val); 初始条件:图已存在,v是图顶点。 操作结果:设置顶点v的标志为val。,图的存储表示,一、图的数组(邻接矩阵)存储表示,二、图的邻接表存储表示,Aij=,0 VR,1 VR,图的数组(邻接矩阵)存储表示,定义:矩阵的元素为,无向图的邻接矩阵是对称矩阵,有向图的邻接矩阵为非对称矩阵,在有向图中, 统计第 i 行 1 的个 数可得顶点 i 的出度,统计第 j 列 1 的个数可得顶点 j 的入度在无向图中, 统计第 i 行 (列) 1 的个数可得顶点i 的度,网(边或弧带权值的图)的数组 (邻接矩阵)存储表示如下,0 A 1 4 1 B 0 4

8、 5 2 C 3 5 3 D 2 5 4 E 0 1 5 F 1 2 3,B,A,C,D,F,E,图的邻接表存储表示,图的遍历 深度优先遍历 DFS (Depth First Search) 广度优先遍历 BFS (Breadth First Search),从图中某个顶点V0 出发,访问此顶点,然后依次从V0的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和V0有路径相通的顶点都被访问到。,一、深度优先搜索遍历图,连通图的深度优先搜索遍历,V,w1,SG1,SG2,SG3,W1、W2和W3 均为 V 的邻接点,SG1、SG2 和 SG3 分别为含顶点W1、W2和W3 的子图。,访问

9、顶点 V : for (W1、W2、W3 )若该邻接点W未被访问,则从它出发进行深度优先搜索遍历。,w2,w3,w2,从上页的图解可见:,1. 从深度优先搜索遍历连通图的过程类似于树的先根遍历;,解决的办法是:图的遍历算法一般为图的每个顶点保留一个标志域(tag),值为UNVISITED表示没有被访问,值为VISITED表示已被访问,2. 如何判别V的邻接点是否被访问?,template void DFSTraverse(const AdjMatrixDirGraph ,template void DFS(const AdjMatrixDirGraph ,二、广度优先搜索遍历图,v,w1,w8

10、,w3,w7,w6,w2,w5,w4,对连通图,从起始点V到其余各顶点必定存在路径。,其中,v-w1, v-w2, v-w8 的路径长度为1;,v-w7, v-w3, v-w5的路径长度为2;,v-w6, v-w4 的路径长度为3。,w1,v,w2,w7,w6,w3,w8,w5,w4,从图中的某个顶点V0出发,并在访问此顶点之后依次访问V0的所有未被访问过的邻接点,之后按这些顶点被访问的先后次序依次访问它们的邻接点,直至图中所有和V0有路径相通的顶点都被访问到。,若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。,template

11、 void BFS(const AdjListDirGraph / v入队,while (!q.Empty() / 队列q非空, 进行循环int u, w; / 临时顶点q.OutQueue(u); / 出队for (w = g.FirstAdjVex(v); w = 0; w = g.NextAdjVex(v, w) / 对u尚未访问过的邻接顶点w进行访问if (g.GetTag(w) = UNVISITED) / 对w进行访问g.SetTag(w, VISITED);/访问标志 g.GetElem(w, e); / w的数据元素Visit(e); / 记问w的数据元素q.InQueue(w

12、); / w入队 ,最小代价生成树 (minimum cost spanning tree),假设要在 n 个城市之间建立通讯联络网,则连通 n 个城市只需要修建 n-1 条线路,如何在最节省经费的前提下建立这个通讯网?,问题,构造网的一棵最小生成树,即: 在 e 条带权的边中选取n-1条边(不 构成回路),使“权值之和”为最小,该问题等价于,构造最小生成树的准则 必须使用且仅使用该网络中的n-1 条边来联结网络中的 n 个顶点 不能使用产生回路的边 各边上的权值的总和达到最小,算法二:克鲁斯卡尔算法 (Kruskal),算法一:普里姆算法(Prim),普里姆算法的 基本思想,1.取图中任意一

13、个顶点 v 作为生成树的根,之后往生成树上添加新的顶点 w,2.在生成树的构造过程中,图中 n 个顶点分属两个集合:已落在生成树上的顶点集 U 和尚未落在生成树上的顶点集V-U ,则应在所有连通U中顶点和V-U中顶点的边中选取权值最小的边(v,w)这里v属于V,w属于U,U,V-U,3.之后继续往生成树上添加顶点,直至生成树上含有 n-1 个顶点为止,a,b,c,d,e,g,f,19,5,14,18,27,16,8,21,3,a,e,12,d,c,b,g,f,7,14,8,5,3,16,21,所得生成树权值和,= 14+8+3+5+16+21 = 67,克鲁斯卡尔算法的 基本思想,具体做法:

14、先构造一个只含 n 个顶点的子图 SG,然后从权值最小的边开始,若它的添加不使SG 中产生回路,则在 SG 上加上这条边,如此重复,直至加上 n-1 条边为止,考虑问题的出发点: 为使生成树上边的权值之和达到最小,则应使生成树中每一条边的权值尽可能地小,a,b,c,d,e,g,f,19,5,14,18,27,16,8,21,3,a,e,12,d,c,b,g,f,7,14,8,5,3,16,21,7,12,18,19,活动网络 ( Activity Network ),用顶点表示活动的网络( AOV网络 ) ( Activity On Vertices ) 用边表示活动的网络( AOE网络 )

15、( Activity On Edges )有向无环图,C1 高等数学C2 程序设计基础C3 离散数学 C1, C2 C4 数据结构 C3, C2C5 高级语言程序设计 C2C6 编译方法 C5, C4C7 操作系统 C4, C9C8 普通物理 C1C9 计算机原理 C8,课程代号,课程名称,先修课程,学生课程学习工程图,C8,C3,C5,C4,C9,C6,C7,C1,C2,拓扑排序(TopologicalSort),按照有向图给出的次序关系,将图中顶点排成一个线性序列,对于有向图中没有限定次序关系的顶点,则可以人为加上任意的次序关系,由此所得顶点的线性序列 称之为拓扑有序序列,例如:对于下列有

16、向图,可求得拓扑有序序列:A B C D 或 A C B D,B,D,A,C,反之,对于下列有向图,不能求得它的拓扑有序序列。,因为图中存在一个回路 B, C, D,进行拓扑排序的步骤,一、从有向图中选取一个没有前驱的顶点,并输出之,重复上述两步,直至图空,或者图不空但找不到无前驱的顶点为止,二、从有向图中删去此顶点以及所有以它为起点的边,a,b,c,g,h,d,f,e,a,b,h,c,d,g,f,e,在算法中需要用定量的描述替代定性的概念,没有前驱的顶点 入度为零的顶点,删除顶点及以它为起点的边 终点的入度减1,对学生选课工程图进行拓扑排序, 得到的拓扑有序序列为C1 , C2 , C3 ,

17、 C4 , C5 , C6 , C8 , C9 , C7 或 C1 , C8 , C9 , C2 , C5 , C3 , C4 , C7 , C6,C4 , C0 , C3 , C2 , C1 , C5,在算法中, 使用一 个堆栈或队列存放入度 为零的顶点, 供选择和 输出无前驱的顶点,拓扑排序算法描述,建立入度为零的顶点栈 当入度为零的栈不空时, 重复执行 从栈中退出一个顶点, 并输出之从AOV网中删去这个顶点和它发出的边, 边的终点入度减一如果边的终点入度减至0, 则该顶点进入入度为零的顶点栈如果输出顶点个数少于AOV网的顶点个数, 则报告网络中存在有向环,template StatusC

18、ode TopSort(const AdjMatrixDirGraph / 建立入度为0的顶点队列,while (!q.Empty() / 队列非空int v1;q.OutQueue(v1); / 取出一个入度为0的顶点cout v1 “ “;count+; / 对输出顶点进行记数for (int v2 = g.FirstAdjVex(v1); v2 != -1; v2 = g.NextAdjVex(v1, v2) / v2为v1的一个邻接点if (-indegreev2 = 0)/邻接点入度减1q.InQueue(v2);/入度为0,v2入队;delete indegree; / 释放ind

19、egree所占用的存储空间if (count g.GetVexNum() return FAIL; / g有回路else return SUCCESS; / 拓扑排序成功 ,关键路径(Critical Path),问题:,假设以有向网表示一个施工流程 图,弧上的权值表示完成该项子 工程所需时间。问:哪些子工程项是“关键工程”?即:哪些子工程项将影响整个工程的 完成期限,a,b,c,d,e,f,g,h,k,6,4,5,2,1,1,8,7,2,4,4,例如:,整个工程完成的时间为:从有向图的源点到汇点的最长路径,源点,汇点,6,1,7,4,用有向边表示一个工程中的活动 (Activity), 用边

20、上权值表示活动持续 时间 (Duration), 用顶点表示事件 (Event)“关键活动”指的是: 该弧上的 权值增加 将使有向图上的最长路径的 长度增加,完成整个工程所需的时间取决于从源点到汇点的最长路径长度, 即在这条路径上所有活动的持续时间之和。这条路径长度最长的路径就叫做关键路径,如何求关键活动?,假设第 i 条边为 对第 j 个顶点而言 “事件(顶点)”的最早发生时间 ve(j) “事件(顶点)”的最迟发生时间 vl(j) 对第 i 项活动而言“活动(弧)”的最早开始时间 ee(i)“活动(弧)”的最迟开始时间 el(i),ve(源点) = 0; ve(k) = Maxve(j)

21、+ dut() (2属于所有以k为终点的边的集合)vl(汇点) = ve(汇点); vl(j) = Minvl(k) dut() (1属于所有以j为起点的边的集合),附注,“事件(顶点)” 的 最早发生时间 ve(j) ve(j) = 从源点到顶点j的最长路径长度;,“事件(顶点)” 的 最迟发生时间 vl(k) vl(k) =从源点到汇点的最长路径长度-从顶点k到汇点的最长路径长度。,ee(i) = ve(j) el(i) = vl(k) dut()ve(源点) = vl(源点) = 0 vl(汇点) = ve(汇点)关键活动:el(i) = ee(i),这两个递推公式的计 算必须分别在拓扑

22、有序及 逆拓扑有序的前提下进行,a,b,c,d,e,f,g,h,k,6,4,5,2,1,1,8,7,2,4,4,0,0,0,0,0,0,0,0,0,6,4,5,7,11,5,7,15,14,18,18,18,18,18,18,18,18,18,18,16,14,8,6,6,10,8,0,7,拓扑有序序列: a - d - f - c - b - e - h - g - k,0,6,4,5,7,7,15,14,18,18,14,16,10,7,8,6,6,0,0,0,0,6,4,5,7,7,7,15,14,14,16,0,2,3,6,6,8,8,7,10,显然 求ve的顺序应该是按拓扑有序的 次

23、序,而 求vl的顺序应该是按拓扑逆序的次序,因为 拓扑逆序序列即为拓扑有序序列的逆序列,因此 应该在拓扑排序的过程中,另设一个“栈”记下拓扑有序序列,要找出关键路径,必须找出关键活 动, 即不按期完成就会影响整个工程完 成的活动, 关键路径上的所有活动都是关键活动因此, 只要找到了关键活动, 就可以 找到关键路径,最短路径 (Shortest Path),最短路径问题如果从图中某一顶点(称为源点)到达另一顶点(称为终点)的路径可能不止一条,如何找到一条路径使得沿此路径上各边上的权值总和达到最小,问题解法边上权值非负情形的单源最短路径 问题 Dijkstra算法所有顶点之间的最短路径 Floyd

24、算法,为求得这些最短路径, Dijkstra提出按路径长度的递增次序, 逐步产生最短路径的算法。首先求出长度最短的一条最短路径,再参照它求出长度次短的一条最短路径,依次类推,直到从顶点v到其它各顶点的最短路径全部求出为止,依最短路径的长度递增的次序求得各条路径,源点,v1,其中,从源点到顶点v1的最短路径是所有最短路径中长度最短者,v2,在这条路径上,必定只含一条弧,并且这条弧的权值最小。,下一条路径长度次短(第1次)的最短路径的特点:,路径长度最短(第0次)的最短路径的特点:,它只可能有两种情况:或者是直接从源点到该点(只含一条弧); 或者是从源点经过顶点v1,再到达该顶点(由两条弧组成)。

25、,其余最短路径(第k次)的特点:,再下一条路径长度次短(第2次)的最短路径的特点:,它可能有两种情况:或者是从源点不经过v2到该点; 或者是从源点到顶点v2,再到达该顶点。,它或者是从源点不经过vk到该点; 或者是从源点到vk,再到达该顶点。,求每一对顶点之间的最短路径,弗洛伊德算法的基本思想是:,从 vi 到 vj 的所有可能存在的路径中,选出一条长度最短的路径,顶点集为V=v1, v2,. vn 第0步:若存在,则存在路径vi,vj ,路径中不含其它顶点,相当于中间点集U=A0ij=G.arcsij (编程序时不写上标,即为Aij=G.arcsij) 第1步:若,存在,则存在路径vi,v1

26、,vj ,路径中所含顶点序号不大于1, 相当于中间点集U=v1A1ij=MINA0ij, A0i1+A01j 第2步:若vi,v2, v2,vj存在,则存在一条路径vi, , v2, vj, 路径所含顶点序号不大于2号,相当于中间点集U=v1,v2A2ij=MINA1ij, A1i2+A12j 第n步:若vi,vn, vn,vj存在,则存在一条路径vi, , vn, vj, 路径顶点序号不大于n号, 相当于中间点集U=V,为最短路径Anij=MINAn-1ij, An-1in+An-1nj,template void ShortestPathFloyd(const AdjListDirNetw

27、ork &net, int *path, WeightType *dist) / 操作结果: 用Floyd算法求有向网net中各对顶点u和v之 / 间的最短路径pathuv和路径长度 / distuv,pathuv存储从u到v的最短路径上至此 / 顶点的前一顶点的顶点号,distuv存储从u到v的最 / 短路径的长度 ,for (int u = 0; u else pathuv = -1; / 不存在边 for (int k = 0; k net.GetVexNum(); k+)for (int i = 0; i net.GetVexNum(); i+)for (int j = 0; j net.GetVexNum(); j+)if (distik + distkj distij) / 从i到k再到j的路径长度更短distij = distik + distkj; pathij = pathkj;,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报