Presentation is loading. Please wait.

Presentation is loading. Please wait.

第六章 图 本章的主要内容是: 图的逻辑结构 图的存储结构及实现 图的连通性 最小生成树 最短路径 AOV网与拓扑排序 AOE网与关键路径.

Similar presentations


Presentation on theme: "第六章 图 本章的主要内容是: 图的逻辑结构 图的存储结构及实现 图的连通性 最小生成树 最短路径 AOV网与拓扑排序 AOE网与关键路径."— Presentation transcript:

1 第六章 图 本章的主要内容是: 图的逻辑结构 图的存储结构及实现 图的连通性 最小生成树 最短路径 AOV网与拓扑排序 AOE网与关键路径

2 图论——欧拉 欧拉1707年出生在瑞士的巴塞尔城,19岁开始发表论文,直到76岁。几乎每一个数学领域都可以看到欧拉的名字,从初等几何的欧拉线,多面体的欧拉定理,立体解析几何的欧拉变换公式,四次方程的欧拉解法到数论中的欧拉函数,微分方程的欧拉方程,级数论的欧拉常数,变分学的欧拉方程,复变函数的欧拉公式等等。据统计他那不倦的一生,共写下了886本书籍和论文,其中分析、代数、数论占40%,几何占18%,物理和力学占28%,天文学占11%,弹道学、航海学、建筑学等占3%。 1733年,年仅26岁的欧拉担任了彼得堡科学院数学教授。1741年到柏林担任科学院物理数学所所长,直到1766年,重回彼得堡,没有多久,完全失明。欧拉在数学上的建树很多,对著名的哥尼斯堡七桥问题的解答开创了图论的研究。

3 哥尼斯堡七桥问题 能否从某个地方出发,穿过所有的桥仅一次后再回到出发点?

4 哥尼斯堡七桥问题 七桥问题的图模型 欧拉回路的判定规则: 1.如果通奇数桥的地方多于两个,则不存在欧拉回路;
2.如果只有两个地方通奇数桥,可以从这两个地方之一出发,找到欧拉回路; 3.如果没有一个地方是通奇数桥的,则无论从哪里出发,都能找到欧拉回路。 C A D B

5 6.1 图的逻辑结构 图的定义 图是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为: G=(V,E)
其中:G表示一个图,V是图G中顶点的集合,E是图G中顶点之间边的集合。 在线性表中,元素个数可以为零,称为空表; 在树中,结点个数可以为零,称为空树; 在图中,顶点个数不能为零,但可以没有边。

6 6.1 图的逻辑结构 V1 V2 若顶点vi和vj之间的边没有方向,则称这条边为无向边,表示为(vi,vj)。 V3 V4 V5
如果图的任意两个顶点之间的边都是无向边,则称该图为无向图。 V1 V2 若从顶点vi到vj的边有方向,则称这条边为有向边,表示为<vi,vj>。 V3 V4 如果图的任意两个顶点之间的边都是有向边,则称该图为有向图。

7 6.1 图的逻辑结构 图的基本术语 简单图:在图中,若不存在顶点到其自身的边,且同一条边不重复出现。 V1 V2 V3 V4 V5
非简单图 非简单图 简单图 数据结构中讨论的都是简单图。

8 6.1 图的逻辑结构 图的基本术语 邻接、依附 无向图中,对于任意两个顶点vi和顶点vj,若存在边(vi,vj),则称顶点vi和顶点vj互为邻接点,同时称边(vi,vj)依附于顶点vi和顶点vj。 V1 V2 V3 V4 V5 V1的邻接点: V2 、V4 V2的邻接点: V1 、V3 、V5

9 6.1 图的逻辑结构 图的基本术语 邻接、依附 有向图中,对于任意两个顶点vi和顶点vj,若存在弧<vi,vj>,则称顶点vi邻接到顶点vj,顶点vj邻接自顶点vi,同时称弧<vi,vj>依附于顶点vi和顶点vj 。 V1 V2 V3 V4 V1的邻接点: V2 、V3 V3的邻接点: V4

10 不同结构中逻辑关系的对比 F E C B A D 线性结构 A B C D E F 树结构 V1 V2 V3 V4 V5 图结构
在线性结构中,数据元素之间仅具有线性关系; 在树结构中,结点之间具有层次关系; 在图结构中,任意两个顶点之间都可能有关系。

11 不同结构中逻辑关系的对比 F E C B A D 线性结构 A B C D E F 树结构 V1 V2 V3 V4 V5 图结构
在线性结构中,元素之间的关系为前驱和后继; 在树结构中,结点之间的关系为双亲和孩子; 在图结构中,顶点之间的关系为邻接。

12 6.1 图的逻辑结构 图的基本术语 无向完全图:在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图。
有向完全图:在有向图中,如果任意两个顶点之间都存在方向相反的两条弧,则称该图为有向完全图。 V1 V2 V3 V4 V1 V2 V3

13 6.1 图的逻辑结构 含有n个顶点的无向完全图有多少条边? 含有n个顶点的有向完全图有多少条弧? V1 V2 V3 V4 V1 V2 V3
含有n个顶点的无向完全图有n×(n-1)/2条边。 含有n个顶点的有向完全图有n×(n-1)条边。

14 6.1 图的逻辑结构 图的基本术语 稀疏图:称边数很少的图为稀疏图; 稠密图:称边数很多的图为稠密图。
顶点的度:在无向图中,顶点v的度是指依附于该顶点的边数,通常记为TD (v)。 顶点的入度:在有向图中,顶点v的入度是指以该顶点为弧头的弧的数目,记为ID (v); 顶点的出度:在有向图中,顶点v的出度是指以该顶点为弧尾的弧的数目,记为OD (v)。

15 å e v TD 2 ) ( 6.1 图的逻辑结构 图的基本术语 V1 V2 V3 V4 V5 = n i 1
在具有n个顶点、e条边的无向图G中,各顶点的度之和与边数之和的关系?

16 å 6.1 图的逻辑结构 e v OD ID = ) ( 图的基本术语 V1 V2 V3 V4 i 1 n
在具有n个顶点、e条边的有向图G中,各顶点的入度之和与各顶点的出度之和的关系?与边数之和的关系?

17 6.1 图的逻辑结构 图的基本术语 权:是指对边赋予的有意义的数值量。 网:边上带权的图,也称网图。 V1 V2 V3 V4 2 7 8 5

18 6.1 图的逻辑结构 图的基本术语 路径:在无向图G=(V, E)中,从顶点vp到顶点vq之间的路径是一个顶点序列(vp=vi0,vi1,vi2, …, vim=vq),其中,(vij-1,vij)∈E(1≤j≤m)。若G是有向图,则路径也是有方向的,顶点序列满足<vij-1,vij>∈E。 V1 到V4的路径: V1 V4 V1 V2 V3 V4 V1 V2 V5V3 V4 V1 V2 V3 V4 V5 一般情况下,图中的路径不惟一。

19 6.1 图的逻辑结构 图的基本术语 非带权图——路径上边的个数 带权图——路径上各边的权之和 路径长度: V1 V2 V3 V4 V5

20 6.1 图的逻辑结构 图的基本术语 非带权图——路径上边的个数 带权图——路径上各边的权之和 路径长度: V1 V2 V3 V4 V5 2
8 V1 V4:长度为8 V1 V2 V3 V4 :长度为7 V1 V2 V5V3 V4 :长度为15

21 6.1 图的逻辑结构 图的基本术语 回路(环):第一个顶点和最后一个顶点相同的路径。 简单路径:序列中顶点不重复出现的路径。
简单回路(简单环):除了第一个顶点和最后一个顶点外,其余顶点不重复出现的回路。 V1 V2 V3 V4 V1 V2 V3 V4 V5

22 6.1 图的逻辑结构 图的基本术语 子图:若图G=(V,E),G'=(V',E'),如果V'V 且E'  E ,则称图G'是G的子图。

23 6.1 图的逻辑结构 图的基本术语 连通图:在无向图中,如果从一个顶点vi到另一个顶点vj(i≠j)有路径,则称顶点vi和vj是连通的。如果图中任意两个顶点都是连通的,则称该图是连通图。 连通分量:非连通图的极大连通子图称为连通分量。 1.含有极大顶点数; 2. 依附于这些顶点的所有边。 如何求得一个非连通图的连通分量?

24 6.1 图的逻辑结构 图的基本术语 V1 V2 V4 V5 V1 V2 V3 V6 V7 V4 V5 V3 V6 V7
连通分量1 V3 V6 V7 V4 V5 连通分量2 V3 V6 V7 连通分量是对无向图的一种划分。

25 6.1 图的逻辑结构 图的基本术语 强连通图:在有向图中,对图中任意一对顶点vi和vj (i≠j),若从顶点vi到顶点vj和从顶点vj到顶点vi均有路径,则称该有向图是强连通图。 强连通分量:非强连通图的极大强连通子图。 如何求得一个非连通图的连通分量?

26 6.1 图的逻辑结构 图的基本术语 V1 V3 V4 强连通分量1 V1 V2 V3 V4 强连通分量2 V2

27 6.1 图的逻辑结构 图的基本术语 生成树:n个顶点的连通图G的生成树是包含G中全部顶点的一个极小连通子图。 如何理解极小连通子图?
多——构成回路 少——不连通 如何理解极小连通子图? 生成森林:在非连通图中,由每个连通分量都可以得到一棵生成树,这些连通分量的生成树就组成了一个非连通图的生成森林。

28 6.1 图的逻辑结构 V1 V2 V3 V4 V5 V1 V2 V3 V4 V5 V1 V2 V3 V4 V5 V6 V7 V1 V2 V3
生成树 V1 V2 V3 V4 V5 V6 V7 V1 V2 V3 V4 V5 V6 V7 生成森林

29 6.1 图的逻辑结构 图的抽象数据类型定义 ADT Graph Data 顶点的有穷非空集合和边的集合 Operation
InitGraph 前置条件:图不存在 输入:无 功能:图的初始化 输出:无 后置条件:构造一个空的图

30 6.1 图的逻辑结构 DFSTraverse 前置条件:图已存在 输入:遍历的起始顶点v 功能:从顶点v出发深度优先遍历图
输出:图中顶点的一个线性排列 后置条件:图保持不变 BFSTraverse 功能:从顶点v出发广度优先遍历图

31 6.1 图的逻辑结构 DestroyGraph 前置条件:图已存在 输入:无 功能:销毁图 输出:无 后置条件:释放图所占用的存储空间
GetVex 输入:顶点v 功能:在图中查找顶点v的数据信息 输出:顶点v的数据信息 后置条件:图保持不变 endADT

32 6.1 图的逻辑结构 图的遍历操作 图的遍历是在从图中某一顶点出发,对图中所有顶点访问一次且仅访问一次。
抽象操作,可以是对结点进行的各种处理,这里简化为输出结点的数据。

33 6.1 图的逻辑结构 图的遍历操作要解决的关键问题 ① 在图中,如何选取遍历的起始顶点? 解决方案:从编号小的顶点开始 。
在线性表中,数据元素在表中的编号就是元素在序列中的位置,因而其编号是唯一的; 在树中,将结点按层序编号,由于树具有层次性,因而其层序编号也是唯一的; 在图中,任何两个顶点之间都可能存在边,顶点是没有确定的先后次序的,所以,顶点的编号不唯一。 为了定义操作的方便,将图中的顶点按任意顺序排列起来,比如,按顶点的存储顺序。

34 6.1 图的逻辑结构 图的遍历操作要解决的关键问题 ② 从某个起点始可能到达不了所有其它顶点,怎么办?
解决方案:多次调用从某顶点出发遍历图的算法。 下面仅讨论从某顶点出发遍历图的算法。

35 6.1 图的逻辑结构 图的遍历操作要解决的关键问题
③ 因图中可能存在回路,某些顶点可能会被重复访问,那么如何避免遍历不会因回路而陷入死循环。 ④ 在图中,一个顶点可以和其它多个顶点相连,当这样的顶点访问过后,如何选取下一个要访问的顶点? 解决方案:附设访问标志数组visited[n] 。 解决方案:深度优先遍历和广度优先遍历。

36 6.1 图的逻辑结构 1986年图灵奖获得者 约翰·霍普克洛夫特1939年生于西雅图。1961年进入斯坦福大学研究生院深造,1962年获硕士学位,1964年获博士学位。毕业后先后在普林斯顿大学、斯坦福大学等著名学府工作,也曾任职于一些科学研究机构如 NSF(美国科学基金会)和 NRC(美国国家研究院)。 罗伯特·陶尔扬1948年4月30日生于加利福尼亚州 。1969年本科毕业,进入斯坦福大学研究生院,1972年获得博士学位。

37 6.1 图的逻辑结构 1. 深度优先遍历 基本思想 : ⑴ 访问顶点v;
⑵ 从v的未被访问的邻接点中选取一个顶点w,从w出发进行深度优先遍历; ⑶ 重复上述两步,直至图中所有和v有路径相通的顶点都被访问到。

38 6.1 图的逻辑结构 深度优先遍历序列?入栈序列?出栈序列? V1 V5 V2 V3 V4 V2 V4 V5 V6 V7 V1 V8
深一层递归 V5 V2 V3 V4 递归返回 V2 V4 V5 V6 V7 V1 V8 遍历序列: V1 V2 V4 V5

39 6.1 图的逻辑结构 深度优先遍历序列?入栈序列?出栈序列? V1 V8 V2 V3 V4 V2 V4 V5 V6 V7 V1 V8
深一层递归 V8 V2 V3 V4 递归返回 V2 V4 V5 V6 V7 V1 V8 遍历序列: V1 V2 V4 V5 V8

40 6.1 图的逻辑结构 深度优先遍历序列?入栈序列?出栈序列? V1 V2 V3 V4 V2 V4 V5 V6 V7 V1 V8 遍历序列:
深一层递归 V2 V3 V4 递归返回 V2 V4 V5 V6 V7 V1 V8 遍历序列: V1 V2 V4 V5 V8

41 6.1 图的逻辑结构 深度优先遍历序列?入栈序列?出栈序列? V1 V7 V2 V3 V6 V3 V4 V5 V6 V7 V1 V8
深一层递归 V7 V2 V3 V6 递归返回 V3 V4 V5 V6 V7 V1 V8 遍历序列: V1 V2 V4 V5 V8 V3 V6 V7

42 6.1 图的逻辑结构 2. 广度优先遍历 基本思想: ⑴ 访问顶点v; ⑵ 依次访问v的各个未被访问的邻接点v1, v2, …, vk;
⑶ 分别从v1,v2,…,vk出发依次访问它们未被访问的邻接点,并使“先被访问顶点的邻接点”先于“后被访问顶点的邻接点”被访问。直至图中所有与顶点v有路径相通的顶点都被访问到。

43 6.1 图的逻辑结构 广度优先遍历序列?入队序列?出队序列? V1 V1 V2 V3 V4 V5 V6 V7 V8 遍历序列: V1

44 6.1 图的逻辑结构 广度优先遍历序列?入队序列?出队序列? V1 V2 V3 V2 V3 V4 V5 V6 V7 V8 遍历序列: V1

45 6.1 图的逻辑结构 广度优先遍历序列?入队序列?出队序列? V1 V3 V4 V5 V2 V3 V4 V5 V6 V7 V8 遍历序列:

46 6.1 图的逻辑结构 广度优先遍历序列?入队序列?出队序列? V1 V4 V5 V6 V7 V2 V3 V4 V5 V6 V7 V8
遍历序列: V1 V2 V3 V4 V5 V6 V7

47 6.1 图的逻辑结构 广度优先遍历序列?入队序列?出队序列? V1 V5 V6 V7 V8 V2 V3 V4 V5 V6 V7 V8
遍历序列: V1 V2 V3 V4 V5 V6 V7 V8

48 6.2 图的存储结构及实现 是否可以采用顺序存储结构存储图? 如何存储图?
图的特点:顶点之间的关系是m:n,即任何两个顶点之间都可能存在关系(边),无法通过存储位置表示这种任意的逻辑关系,所以,图无法采用顺序存储结构。 如何存储图? 考虑图的定义,图是由顶点和边组成的,分别考虑如何存储顶点、如何存储边。

49 6.2 图的存储结构及实现 邻接矩阵(数组表示法) 1 若(vi, vj)∈E(或<vi, vj>∈E) 0 其它
基本思想:用一个一维数组存储图中顶点的信息,用一个二维数组(称为邻接矩阵)存储图中各顶点之间的邻接关系。 假设图G=(V,E)有n个顶点,则邻接矩阵是一个n×n的方阵,定义为: arc[i][j]= 若(vi, vj)∈E(或<vi, vj>∈E) 其它

50 6.2 图的存储结构及实现 无向图的邻接矩阵 0 1 0 1 1 0 1 1 0 1 0 0 1 1 0 0 V1 V2 V3 V4
vertex= V1 V3 V4 V2 V1 V2 V3 V4 V1 V2 V3 V4 arc= 无向图的邻接矩阵的特点? 主对角线为 0 且一定是对称矩阵。

51 6.2 图的存储结构及实现 无向图的邻接矩阵 0 1 0 1 1 0 1 1 0 1 0 0 1 1 0 0 V1 V2 V3 V4
vertex= V1 V4 V1 V2 V3 V4 V1 V2 V3 V4 arc= V2 V3 如何求顶点i的度? 邻接矩阵的第i行(或第i列)非零元素的个数。

52 6.2 图的存储结构及实现 无向图的邻接矩阵 0 1 0 1 1 0 1 1 0 1 0 0 1 1 0 0 V1 V2 V3 V4
vertex= V1 V4 V1 V2 V3 V4 V1 V2 V3 V4 arc= V2 V3 如何判断顶点 i 和 j 之间是否存在边? 测试邻接矩阵中相应位置的元素arc[i][j]是否为1。

53 6.2 图的存储结构及实现 无向图的邻接矩阵 0 1 0 1 1 0 1 1 0 1 0 0 1 1 0 0 V1 V2 V3 V4
vertex= V1 V4 V1 V2 V3 V4 V1 V2 V3 V4 arc= V2 V3 如何求顶点 i 的所有邻接点? 将数组中第 i 行元素扫描一遍,若arc[i][j]为1,则顶点 j 为顶点 i 的邻接点。

54 6.2 图的存储结构及实现 有向图的邻接矩阵 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 V1 V2 V3 V4
vertex= V1 V2 V3 V4 V1 V2 V3 V4 V1 V2 V3 V4 arc= 有向图的邻接矩阵一定不对称吗? 不一定,例如有向完全图。

55 6.2 图的存储结构及实现 有向图的邻接矩阵 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 V1 V2 V3 V4
vertex= V1 V2 V3 V4 V1 V2 V3 V4 V1 V2 V3 V4 arc= 如何求顶点 i 的出度? 邻接矩阵的第 i 行元素之和。

56 6.2 图的存储结构及实现 有向图的邻接矩阵 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 V1 V2 V3 V4
vertex= V1 V2 V3 V4 V1 V2 V3 V4 V1 V2 V3 V4 arc= 如何求顶点 i 的入度? 邻接矩阵的第 i 列元素之和。

57 6.2 图的存储结构及实现 有向图的邻接矩阵 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 V1 V2 V3 V4
vertex= V1 V2 V3 V4 V1 V2 V3 V4 V1 V2 V3 V4 arc= 如何判断从顶点 i 到顶点 j 是否存在边? 测试邻接矩阵中相应位置的元素arc[i][j]是否为1。

58 6.2 图的存储结构及实现 网图的邻接矩阵 0 2 5 ∞ ∞ 0 ∞ ∞ ∞ ∞ 0 8 7 ∞ ∞ 0 网图的邻接矩阵可定义为:
arc[i][j]= wij 若(vi, vj)∈E(或<vi, vj>∈E) 若i=j ∞ 其他 V1 V2 V3 V4 2 7 8 5 ∞ ∞ ∞ ∞ ∞ 7 ∞ ∞ 0 arc=

59 6.2 图的存储结构及实现 邻接矩阵存储无向图的类 const int MaxSize=10;
template <class T> class Mgraph { public: MGraph(T a[ ], int n, int e ); ~MGraph( ) void DFSTraverse(int v); void BFSTraverse(int v); private: T vertex[MaxSize]; int arc[MaxSize][MaxSize]; int vertexNum, arcNum; }; 邻接矩阵存储无向图的类

60 6.2 图的存储结构及实现 邻接矩阵中图的基本操作——构造函数 确定图的顶点个数和边的个数;
2. 输入顶点信息存储在一维数组vertex中; 3. 初始化邻接矩阵; 4. 依次输入每条边存储在邻接矩阵arc中; 4.1 输入边依附的两个顶点的序号i, j; 4.2 将邻接矩阵的第i行第j列的元素值置为1; 4.3 将邻接矩阵的第j行第i列的元素值置为1;

61 6.2 图的存储结构及实现 邻接矩阵中图的基本操作——构造函数 template <class T>
MGraph::MGraph(T a[ ], int n, int e) { vertexNum=n; arcNum=e; for (i=0; i<vertexNum; i++) vertex[i]=a[i]; for (i=0; i<vertexNum; i++) //初始化邻接矩阵 for (j=0; j<vertexNum; j++) arc[i][j]=0; for (k=0; k<arcNum; k++) //依次输入每一条边 cin>>i>>j; //边依附的两个顶点的序号 arc[i][j]=1; arc[j][i]=1; //置有边标志 }

62 6.2 图的存储结构及实现 邻接矩阵中图的基本操作——深度优先遍历 template <class T>
void MGraph::DFSTraverse(int v) { cout<<vertex[v]; visited [v]=1; for (j=0; j<vertexNum; j++) if (arc[v][j]==1 && visited[j]==0) DFSTraverse( j ); }

63 6.2 图的存储结构及实现 邻接矩阵中图的基本操作——广度优先遍历 template <class T>
void MGraph::BFSTraverse(int v) { front=rear=-1; //假设采用顺序队列且不会发生溢出 cout<<vertex[v]; visited[v]=1; Q[++rear]=v; while (front!=rear) v=Q[++front]; for (j=0; j<vertexNum; j++) if (arc[v][j]==1 && visited[j]==0 ) { cout<<vertex[j]; visited[j]=1; Q[++rear]=j; }

64 6.2 图的存储结构及实现 邻接表 图的邻接矩阵存储结构的空间复杂度? 如果为稀疏图则会出现什么现象?
假设图G有n个顶点e条边,则存储该图需要O(n2) 。 邻接表存储的基本思想:对于图的每个顶点vi,将所有邻接于vi的顶点链成一个单链表,称为顶点vi的边表(对于有向图则称为出边表),所有边表的头指针和存储顶点信息的一维数组构成了顶点表。

65 6.2 图的存储结构及实现 vertex firstedge adjvex next 邻接表有两种结点结构:顶点表结点和边表结点。
顶点表 边 表 vertex:数据域,存放顶点信息。 firstedge:指针域,指向边表中第一个结点。 adjvex:邻接点域,边的终点在顶点表中的下标。 next:指针域,指向边表中的下一个结点。

66 6.2 图的存储结构及实现 adjvex next vertex firstedge 定义邻接表的结点 struct ArcNode
{ int adjvex; ArcNode *next; }; template <class T> struct VertexNode { T vertex; ArcNode *firstedge; adjvex next vertex firstedge

67 6.2 图的存储结构及实现 无向图的邻接表 V1 V4 边表中的结点表示什么? 每个结点对应图中的一条边,
邻接表的空间复杂度为O(n+e)。 1 3 2 V1 V2 V3 V4 vertex firstedge

68 6.2 图的存储结构及实现 无向图的邻接表 V1 V4 如何求顶点 i 的度? 顶点i的边表中结点的个数。 V2 V3 V1 V2 V3
3 2 V1 V2 V3 V4 vertex firstedge

69 6.2 图的存储结构及实现 无向图的邻接表 V4 V1 如何判断顶点 i 和顶点 j 之间是否存在边?
3 2 V1 V2 V3 V4 vertex firstedge

70 6.2 图的存储结构及实现 有向图的邻接表 V1 V2 如何求顶点 i 的出度? 顶点 i 的出边表中结点的个数。 V3 V4 V1 V2
V1 V2 V3 V4 3 vertex firstedge

71 6.2 图的存储结构及实现 有向图的邻接表 V1 V2 如何求顶点 i 的入度? 各顶点的出边表中以顶点 i 为 终点的结点个数。 V3
V1 V2 V3 V4 3 vertex firstedge

72 6.2 图的存储结构及实现 有向图的邻接表 V1 V2 如何求顶点 i 的所有邻接点?
遍历顶点 i 的边表,该边表中的所有终点都是顶点 i 的邻接点。 1 2 3 V1 V2 V3 V4 vertex firstedge

73 6.2 图的存储结构及实现 网图的邻接表 V1 V2 2 V3 V1 V2 V4 7 5 8 V3 V4 vertex firstedge
2 1 V1 V2 V3 V4 1 2 3 vertex firstedge 5 2 8 3 7 0 V1 V2 V3 V4 2 7 8 5

74 6.2 图的存储结构及实现 邻接表存储有向图的类 const int MaxSize=10; //图的最大顶点数
template <class T> class ALGraph { public: ALGraph(T a[ ], int n, int e); ~ALGraph; void DFSTraverse(int v); void BFSTraverse(int v); private: VertexNode adjlist[MaxSize]; int vertexNum, arcNum; }; 邻接表存储有向图的类

75 6.2 图的存储结构及实现 邻接表中图的基本操作——构造函数 1. 确定图的顶点个数和边的个数; 2. 输入顶点信息,初始化该顶点的边表;
3. 依次输入边的信息并存储在边表中; 3.1 输入边所依附的两个顶点的序号i和j; 3.2 生成邻接点序号为j的边表结点s; 3.3 将结点s插入到第i个边表的头部;

76 6.2 图的存储结构及实现 邻接表中图的基本操作——构造函数 template <class T>
ALGraph::ALGraph(T a[ ], int n, int e) { vertexNum=n; arcNum=e; for (i=0; i<vertexNum; i++) //输入顶点信息,初始化边表 adjlist[i].vertex=a[i]; adjlist[i].firstedge=NULL; }

77 6.2 图的存储结构及实现 for (k=0; k<arcNum; k++) //输入边的信息存储在边表中 {
cin>>i>>j; s=new ArcNode; s->adjvex=j; s->next=adjlist[i].firstedge; adjlist[i].firstedge=s; } s 1 2 V1 V2 V3 V4 3

78 6.2 图的存储结构及实现 邻接表中图的基本操作——深度优先遍历 template <class T>
void ALGraph::DFSTraverse(int v) { cout<<adjlist[v].vertex; visited[v]=1; p=adjlist[v].firstedge; while (p!=NULL) j=p->adjvex; if (visited[j]==0) DFSTraverse(j); p=p->next; }

79 6.2 图的存储结构及实现 邻接表中图的基本操作——广度优先遍历 template <class T>
void ALGraph::BFSTraverse(int v) { front=rear=-1; cout<<adjlist[v].vertex; visited[v]=1; Q[++rear]=v; while (front!=rear) v=Q[++front]; p=adjlist[v].firstedge; while (p!=NULL) j= p->adjvex; if (visited[j]==0) { cout<<adjlist[j].vertex; visited[j]=1; Q[++rear]=j; } p=p->next;

80 6.2 图的存储结构及实现 十字链表 1 2 ∧ 3 ∧ v1 v2 v3 v4 1 ∧ 邻接表 V1 V2 V3 V4 3 ∧ 0 ∧
2 ∧ 3 ∧ v1 v2 v3 v4 2 3 1 ∧ 邻接表 V1 V2 V3 V4 3 ∧ 0 ∧ 2 ∧ v1 v2 v3 v4 1 2 3 逆邻接表 将邻接表与逆邻接表合二为一?为什么要合并?

81 6.2 图的存储结构及实现 十字链表的结点结构 vertex firstin firstout 顶点表结点 tailvex headvex
headlink taillink 边表结点 vertex:数据域,存放顶点信息; firstin:入边表头指针; firstout:出边表头指针; tailvex:弧的起点在顶点表中的下标; headvex:弧的终点在顶点表中的下标; headlink:入边表指针域; taillink:出边表指针域。

82 6.2 图的存储结构及实现 十字链表存储有向图 V1 V2 V3 V4 v3v4 v4v1 v1v2 v1v3 v4v2 3 2 1 V1
V1 V2 V3 V4 0 1 3 0

83 6.2 图的存储结构及实现 图的存储结构的比较——邻接矩阵和邻接表 空间性能 时间性能 适用范围 唯一性 邻 接 矩 阵 表 O(n2)
O(n+e) 稠密图 稀疏图 唯一 不唯一 O(n+e)

84 6.3 图的连通性 无向图的连通性 要想判定一个无向图是否为连通图,或有几个连通分量,通过对无向图遍历即可得到结果。
6.3 图的连通性 无向图的连通性 要想判定一个无向图是否为连通图,或有几个连通分量,通过对无向图遍历即可得到结果。 连通图:仅需从图中任一顶点出发,进行深度优先搜索(或广度优先搜索),便可访问到图中所有顶点。 非连通图:需从多个顶点出发进行搜索,而每一次从一个新的起始点出发进行搜索过程中得到的顶点访问序列恰为其各个连通分量中的顶点集。

85 6.3 图的连通性 求无向图的连通分量 count=0; 2. for (图中每个顶点v) 2.1 if (v尚未被访问过)
6.3 图的连通性 求无向图的连通分量 count=0; 2. for (图中每个顶点v) 2.1 if (v尚未被访问过) 2.1.1 count++; 2.1.2 从v出发遍历该图; 3. if (count==1) cout<<"图是连通的"; else cout<<"图中有"<<count<<"个连通分量";

86 6.3 图的连通性 有向图的连通性 ⑴ 从某顶点出发进行深度优先遍历,并按其所有邻接点都访问(即出栈)的顺序将顶点排列起来。
6.3 图的连通性 有向图的连通性 ⑴ 从某顶点出发进行深度优先遍历,并按其所有邻接点都访问(即出栈)的顺序将顶点排列起来。 ⑵ 从最后完成访问的顶点出发,沿着以该顶点为头的弧作逆向的深度优先遍历。若不能访问到所有顶点,则从余下的顶点中最后访问的那个顶点出发,继续作逆向的深度优先遍历,直至有向图中所有顶点都被访问到为止。 ⑶ 每一次逆向深度优先遍历所访问到的顶点集便是该有向图的一个强连通分量的顶点集。

87 6.3 图的连通性 生成树 V1 V1 V2 V3 V2 V3 V4 V5 V6 V7 V4 V5 V6 V7 V8 V8
6.3 图的连通性 生成树 V1 V1 V2 V3 V2 V3 V4 V5 V6 V7 V4 V5 V6 V7 V8 V8 (a)深度优先生成树 (b) 广度优先生成树

88 6.3 图的连通性 生成树 结论: 由深度优先遍历得到的为深度优先生成树, 由广度优先遍历得到的为广度优先生成树。
6.3 图的连通性 生成树 结论: 由深度优先遍历得到的为深度优先生成树, 由广度优先遍历得到的为广度优先生成树。 一个连通图的生成树可能不唯一,由不同的遍历次序、从不同顶点出发进行遍历都会得到不同的生成树。 对于非连通图,通过图的遍历,将得到的是生成森林。

89 应用举例——最小生成树 最小生成树 生成树的代价:设G=(V,E)是一个无向连通网,生成树上各边的权值之和称为该生成树的代价。
最小生成树的概念可以应用到许多实际问题中。 例:在n个城市之间建造通信网络,至少要架设n-1条通信线路,而每两个城市之间架设通信线路的造价是不一样的,那么如何设计才能使得总造价最小?

90 应用举例——最小生成树 MST性质 假设G=(V, E)是一个无向连通网,U是顶点集V的一个非空子集。若(u, v)是一条具有最小权值的边,其中u∈U,v∈V-U,则必存在一棵包含边(u, v)的最小生成树。 顶点集U V-U u' v v' u 顶点集 T1 T2

91 应用举例——最小生成树 普里姆(Prim)算法
基本思想:设G=(V, E)是具有n个顶点的连通网,T=(U, TE)是G的最小生成树, T的初始状态为U={u0}(u0∈V),TE={ },重复执行下述操作:在所有u∈U,v∈V-U的边中找一条代价最小的边(u, v)并入集合TE,同时v并入U,直至U=V。 关键:是如何找到连接U和V-U的最短边。 利用MST性质,可以用下述方法构造候选最短边集:对应V-U中的每个顶点,保留从该顶点到U中的各顶点的最短边。

92 应用举例——最小生成树 Prim算法 B 34 12 U={A} V-U={B, C, D, E, F}
cost={(A, B)34, (A, C)46, (A, D)∞,(A, E)∞,(A, F)19} A E 19 26 F 46 25 25 38 C D 17

93 应用举例——最小生成树 Prim算法 B 34 12 U={A, F} V-U={B, C, D, E}
cost={(A, B)34,(F, C)25, (F, D)25,(F, E)26} A E 19 26 F 46 25 25 38 C D 17

94 应用举例——最小生成树 Prim算法 B 34 12 U={A, F, C} V-U={B, D, E}
cost={(A, B)34, (C, D)17, (F, E)26} A E 19 26 F 46 25 25 38 C D 17

95 应用举例——最小生成树 Prim算法 B 34 12 U={A, F, C, D} V-U={B, E}
cost={(A, B)34, (F, E)26} A E 19 26 F 46 25 25 38 C D 17

96 应用举例——最小生成树 Prim算法 B 34 12 U={A, F, C, D, E} V-U={B} cost={(E, B)12} A
19 26 F 46 25 25 38 C D 17

97 应用举例——最小生成树 Prim算法 B 34 12 U={A, F, C, D, E, B} V-U={ } A E 19 26 F 46
25 25 38 C D 17

98 应用举例——最小生成树 数据结构设计 数组lowcost[n]:用来保存集合V-U中各顶点与集合U中顶点最短边的权值,lowcost[v]=0表示顶点v已加入最小生成树中; 数组adjvex[n]:用来保存依附于该边(集合V-U中各顶点与集合U中顶点的最短边)在集合U中的顶点。 如何用数组lowcost和adjvex表示候选最短边集? 表示顶点vi和顶点vk之间的权值为w,其中:vi∈ V-U 且vk ∈U lowcost[i]=w adjvex[i]=k

99 应用举例——最小生成树 adjvex lowcost {A} adjvex lowcost {A, F} {B, C, D, E}
i 数组 B(i=1) C(i=2) D(i=3) E(i=4) F(i=5) U V-U 输出 adjvex lowcost A 34 A 46 A A A 19 {A} {B, C, D, E, F} (A F)19 adjvex lowcost A 34 F 25 F 25 F 26 {A, F} {B, C, D, E} (F C)25 adjvex lowcost A 34 C 17 F 26 {A, F, C} {B, D, E} (C D)17 adjvex lowcost A 34 F 26 {A, F, C, D} {B, E} (F E)26 adjvex lowcost E 12 {A, F, C, D, E} {B} (E B)12 adjvex lowcost {A,F,C,D,E,B} { }

100 应用举例——最小生成树 Prim算法——伪代码 1. 初始化两个辅助数组lowcost和adjvex;
2. 输出顶点u0,将顶点u0加入集合U中; 3. 重复执行下列操作n-1次 3.1 在lowcost中选取最短边,取adjvex中对应的顶点序号k; 3.2 输出顶点k和对应的权值; 3.3 将顶点k加入集合U中; 3.4 调整数组lowcost和adjvex;

101 应用举例——最小生成树 克鲁斯卡尔(Kruskal)算法
基本思想:设无向连通网为G=(V, E),令G的最小生成树为T=(U, TE),其初态为U=V,TE={ },然后,按照边的权值由小到大的顺序,考察G的边集E中的各条边。若被考察的边的两个顶点属于T的两个不同的连通分量,则将此边作为最小生成树的边加入到T中,同时把两个连通分量连接为一个连通分量;若被考察边的两个顶点属于同一个连通分量,则舍去此边,以免造成回路,如此下去,当T中的连通分量个数为1时,此连通分量便为G的一棵最小生成树。

102 应用举例——最小生成树 B B 34 12 A E 19 26 A E F F 46 25 25 38 C D C D 17
连通分量={A}, {B}, {C}, {D}, {E}, {F}

103 应用举例——最小生成树 B B 34 12 12 A E 19 26 A E F F 46 25 25 38 C D C D 17
连通分量={A}, {B}, {C}, {D}, {E}, {F} 连通分量={A}, {B, E}, {C}, {D}, {F}

104 应用举例——最小生成树 B B 34 12 12 A E 19 26 A 19 E F F 46 25 25 38 C D C D 17
连通分量={A}, {B, E}, {C}, {D}, {F} 连通分量={A, F}, {B, E}, {C}, {D}

105 应用举例——最小生成树 B B 34 12 12 A E 19 26 A 19 E F F 46 25 25 38 C D C D 17
连通分量={A, F}, {B, E}, {C}, {D} 连通分量={A, F}, {B, E}, {C, D}

106 应用举例——最小生成树 B B 34 12 12 A E 19 26 A 19 E F F 46 25 25 25 38 C D C D
17 17 连通分量={A, F}, {B, E}, {C, D} 连通分量={A, F, C, D}, {B, E}

107 应用举例——最小生成树 B B 34 12 12 A E 19 26 A 19 E 26 F F 46 25 25 25 38 C D C
17 17 连通分量={A, F, C, D}, {B, E} 连通分量={A, F, C, D, B, E}

108 应用举例——最小生成树 Kruskal算法——伪代码 1. 初始化:U=V; TE={ }; 2. 循环直到T中的连通分量个数为1
2.1 在E中寻找最短边(u,v); 2.2 如果顶点u、v位于T的两个不同连通分量,则 2.2.1 将边(u,v)并入TE; 2.2.2 将这两个连通分量合为一个; 2.3 在E中标记边(u,v),使得(u,v)不参加后续最短边的选取;

109 应用举例——最短路径 最短路径 在非网图中,最短路径是指两顶点之间经历的边数最少的路径。 B AE:1 ADE:2 A C ADCE:3
ABCE:3

110 应用举例——最短路径 最短路径 在网图中,最短路径是指两顶点之间经历的边上权值之和最短的路径。 B AE:100 A C ADE:90
50 30 100 20 60 AE:100 ADE:90 ADCE:60 ABCE:70

111 应用举例——最短路径 单源点最短路径问题 问题描述:给定带权有向图G=(V, E)和源点v∈V,求从v到G中其余各顶点的最短路径。
应用实例——计算机网络传输的问题:怎样找到一种最经济的方式,从一台计算机向网上所有其它计算机发送一条消息。 迪杰斯特拉(Dijkstra)提出了一个按路径长度递增的次序产生最短路径的算法——Dijkstra算法。

112 应用举例——最短路径 Dijkstra算法
基本思想:设置一个集合S存放已经找到最短路径的顶点,S的初始状态只包含源点v,对vi∈V-S,假设从源点v到vi的有向边为最短路径。以后每求得一条最短路径v, …, vk,就将vk加入集合S中,并将路径v, …, vk , vi与原来的假设相比较,取路径长度较小者为最短路径。重复上述过程,直到集合V中全部顶点加入到集合S中。

113 应用举例——最短路径 Dijkstra算法的基本思想 V-S S vk v vi

114 应用举例——最短路径 Dijkstra算法 B S={A} A→B:(A, B)10 A→C:(A, C)∞ A→D: (A, D)30
A→E: (A, E)100 10 50 A A C 30 10 100 20 E D 60

115 应用举例——最短路径 Dijkstra算法 B B S={A, B} A→B:(A, B)10 A→C:(A, B, C)60
A→D: (A, D)30 A→E: (A, E)100 10 50 A A C 30 10 100 20 E D 60

116 应用举例——最短路径 Dijkstra算法 B B S={A, B, D} A→B:(A, B)10 A→C:(A, D, C)50
A→D: (A, D)30 A→E: (A, D, E)90 10 50 A A C 30 10 100 20 E D D 60

117 应用举例——最短路径 Dijkstra算法 B B S={A, B, D, C} A→B:(A, B)10 A→C:(A, D, C)50
A→D: (A, D)30 A→E: (A, D, C, E)60 10 50 A A C C 30 10 100 20 E D D 60

118 应用举例——最短路径 Dijkstra算法 B B S={A, B, D, C, E} A→B:(A, B)10
A→C:(A, D, C)50 A→D: (A, D)30 A→E: (A, D, C, E)60 10 50 A A C C 30 10 100 20 E E D D 60

119 应用举例——最短路径 设计数据结构 : 图的存储结构:带权的邻接矩阵存储结构
数组dist[n]:每个分量dist[i]表示当前所找到的从始点v到终点vi的最短路径的长度。初态为:若从v到vi有弧,则dist[i]为弧上权值;否则置dist[i]为∞。 数组path[n]:path[i]是一个字符串,表示当前所找到的从始点v到终点vi的最短路径。初态为:若从v到vi有弧,则path[i]为vvi;否则置path[i]空串。 数组s[n]:存放源点和已经生成的终点,其初态为只有一个源点v。

120 应用举例——最短路径 Dijkstra算法——伪代码 1. 初始化数组dist、path和s;
2. while (s中的元素个数<n) 2.1 在dist[n]中求最小值,其下标为k; 2.2 输出dist[j]和path[j]; 2.3 修改数组dist和path; 2.4 将顶点vk添加到数组s中;

121 应用举例——最短路径 每一对顶点之间的最短路径
问题描述:给定带权有向图G=(V, E),对任意顶点vi,vj∈V(i≠j),求顶点vi到顶点vj的最短路径。 解决办法1:每次以一个顶点为源点,调用Dijkstra算法n次。显然,时间复杂度为O(n3)。 解决办法2:弗洛伊德提出的求每一对顶点之间的最短路径算法——Floyd算法,其时间复杂度也是O(n3),但形式上要简单些。

122 应用举例——最短路径 Floyd算法 基本思想:对于从vi到vj的弧,进行n次试探:首先考虑路径vi,v0,vj是否存在,如果存在,则比较vi,vj和vi,v0,vj的路径长度,取较短者为从vi到vj的中间顶点的序号不大于0的最短路径。在路径上再增加一个顶点v1,依此类推,在经过n次比较后,最后求得的必是从顶点vi到顶点vj的最短路径。

123 应用举例——最短路径 Floyd算法 a 3 ∞ 0 3 4 11 6 c b 2 有向网图 邻接矩阵

124 应用举例——最短路径 Floyd算法 0 4 11 6 0 2 3 ∞ 0 dist-1 = a ab ac c b ba bc ca
3 ∞ 0 dist-1 = a c b 3 4 6 11 2 ab ac ba bc ca path-1 = 初始化

125 应用举例——最短路径 Floyd算法 0 4 11 6 0 2 3 ∞ 0 0 4 11 6 0 2 3 7 0 a c b
3 ∞ 0 a c b 3 4 6 11 2 dist-1 = dist0 = ab ac ba bc ca ab ac ba bc ca cab path-1 = path0 = 第1次迭代

126 应用举例——最短路径 Floyd算法 0 4 11 0 4 6 6 0 2 6 0 2 3 7 0 3 7 0 dist0 =
a c b 3 4 6 11 2 dist0 = dist1 = ab ac ba bc ca cab ab abc ba bc ca cab path0 = path1 = 第2次迭代

127 应用举例——最短路径 Floyd算法 0 4 6 0 4 6 6 0 2 5 0 2 3 7 0 3 7 0 dist1 = dist2 =
dist1 = dist2 = a 3 4 11 6 ab abc ba bc ca cab ab abc bca bc ca cab c b 2 path1 = path2 = 第3次迭代

128 应用举例——最短路径 设计数据结构 图的存储结构:带权的邻接矩阵存储结构
数组dist[n][n]:存放在迭代过程中求得的最短路径长度。迭代公式: 数组path[n][n]:存放从vi到vj的最短路径,初始为path[i][j]="vivj"。 dist-1[i][j]=arc[i][j] dist k[i][j]=min{distk-1[i][j], distk-1[i][k]+distk-1[k][j]} 0≤k ≤n-1

129 应用举例——最短路径 Floyd算法——C++描述 void Floyd(MGraph G) {
for (i=0; i<G.vertexNum; i++)      for (j=0; j<G.vertexNum; j++)      { dist[i][j]=G.arc[i][j];        if (dist[i][j]!=∞) path[i][j]=G.vertex[i]+G.vertex[j];         else path[i][j]=""; }

130 应用举例——最短路径 Floyd算法——C++描述 for (k=0; k<G.vertexNum; k++)
        for (i=0; i<G.vertexNum; i++)          for (j=0; j<G.vertexNum; j++)          if (dist[i][k]+dist[k][j]<dist[i][j]) {          dist[i][j]=dist[i][k]+dist[k][j];          path[i][j]=path[i][k]+path[k][j]; }

131 应用举例——拓扑排序 AOV网 什么是工程?工程有什么共性?
AOV网:在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,称这样的有向图为顶点表示活动的网,简称AOV网。 AOV网中出现回路意味着什么?

132 应用举例——拓扑排序 AOV网 什么是工程?工程有什么共性?
AOV网:在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,称这样的有向图为顶点表示活动的网,简称AOV网。 2.AOV网中不能出现回路 。 AOV网特点: 1.AOV网中的弧表示活动之间存在的某种制约关系。

133 应用举例——拓扑排序 AOV网 C3 C5 C1 C4 C7 C2 C6 编号 课程名称 先修课 C1 高等数学 无 C2 计算机导论 C3
离散数学 C4 程序设计 C1, C2 C5 数据结构 C3,C4 C6 计算机原理 C2,C4 C7 数据库原理 C4,C5,C6 C1 C2 C3 C4 C6 C5 C7

134 应用举例——拓扑排序 拓扑排序 拓扑序列:设G=(V,E)是一个具有n个顶点的有向图,V中的顶点序列v1, v2, …, vn称为一个拓扑序列,当且仅当满足下列条件:若从顶点vi到vj有一条路径,则在顶点序列中顶点vi必在顶点vj之前。 拓扑排序:对一个有向图构造拓扑序列的过程称为拓扑排序 。 拓扑序列使得AOV网中所有应存在的前驱和后继关系都能得到满足。

135 应用举例——拓扑排序 拓扑排序 基本思想: ⑴ 从AOV网中选择一个没有前驱的顶点并且输出;
拓扑排序的结果?

136 应用举例——拓扑排序 拓扑排序 C3 C5 C1 C4 C7 C2 C6 拓扑序列: C1, C2, C3, C4, C5, C6, C7

137 应用举例——拓扑排序 拓扑排序 C3 C4 C1 说明AOV网中存在回路。 C4 C2 C6 拓扑序列: C1, C2, C3,

138 应用举例——拓扑排序 设计数据结构 1. 图的存储结构:采用邻接表存储 ,在顶点表中增加一个入度域。 顶点表结点 in vertex
1. 图的存储结构:采用邻接表存储 ,在顶点表中增加一个入度域。 顶点表结点 in vertex firstedge 2. 栈S:存储所有无前驱的顶点。

139 应用举例——拓扑排序 拓扑排序 A B C D E F 1 2 3 4 5 3 A ∧ 0 B 1 C 3 D 0 E 2 F ∧ 3 ∧
in vertex firstedge A B 1 2 3 4 5 3 A ∧ 0 B 1 C 3 D 0 E 2 F ∧ 3 ∧ C D 3 ∧ 5 ∧ E F 2 3 5 ∧ (a) 一个AOV网 (b) AOV网的邻接表存储

140 应用举例——拓扑排序 拓扑排序 A B C D E E F B 1 2 3 4 5 3 A ∧ 0 B 1 C 3 D 0 E 2 F ∧
in vertex firstedge A B 1 2 3 4 5 3 A ∧ 0 B 1 C 3 D 0 E 2 F ∧ 3 ∧ C D 3 ∧ 5 ∧ E E F 2 3 5 ∧ B

141 应用举例——拓扑排序 拓扑排序 A B C D E E C F B 1 2 3 4 5 3 A ∧ 0 B 1 C 3 D 0 E
in vertex firstedge A B 1 2 3 4 5 3 A ∧ 0 B 1 C 3 D 0 E 2 F ∧ 3 ∧ C D 3 ∧ E 2 5 ∧ E C F 2 3 5 ∧ B 1

142 应用举例——拓扑排序 拓扑排序 A B C D C F B 1 2 3 4 5 3 A ∧ 0 B 0 C 2 D 0 E 1 F ∧ 2
in vertex firstedge A B 1 2 3 4 5 3 A ∧ 0 B 0 C 2 D 0 E 1 F ∧ 2 C 3 ∧ D 3 ∧ 1 5 ∧ C F 2 3 5 ∧ B

143 应用举例——拓扑排序 拓扑排序 A B D F B D 1 2 3 4 5 2 A ∧ 0 B 0 C 1 D 0 E 1 F ∧ 1
in vertex firstedge A B 1 2 3 4 5 2 A ∧ 0 B 0 C 1 D 0 E 1 F ∧ 1 3 ∧ D 3 ∧ 5 ∧ F 2 3 5 ∧ B D

144 应用举例——拓扑排序 拓扑排序 A D F F A 1 2 3 4 5 1 A ∧ 0 B 0 C 0 D 0 E 1 F ∧ 3 ∧
in vertex firstedge A 1 2 3 4 5 1 A ∧ 0 B 0 C 0 D 0 E 1 F ∧ D 3 ∧ 3 ∧ 5 ∧ F F 2 3 5 ∧ A

145 应用举例——拓扑排序 拓扑排序 A F F A 1 2 3 4 5 0 A ∧ 0 B 0 C 0 D 0 E 0 F ∧ 3 ∧ 3 ∧
in vertex firstedge A 1 2 3 4 5 0 A ∧ 0 B 0 C 0 D 0 E 0 F ∧ 3 ∧ 3 ∧ 5 ∧ F F 2 3 5 ∧ A

146 应用举例——拓扑排序 拓扑排序算法——伪代码 1. 栈S初始化;累加器count初始化; 2. 扫描顶点表,将没有前驱的顶点压栈;
3.1 vj=退出栈顶元素;输出vj;累加器加1; 3.2 将顶点vj的各个邻接点的入度减1; 3.3 将新的入度为0的顶点入栈; 4. if (count<vertexNum) 输出有回路信息;

147 应用举例——关键路径 AOE网 AOE网:在一个表示工程的带权有向图中,用顶点表示事件,用有向边表示活动,边上的权值表示活动的持续时间,称这样的有向图叫做边表示活动的网,简称AOE网。AOE网中没有入边的顶点称为始点(或源点),没有出边的顶点称为终点(或汇点)。 AOE网的性质: ⑴ 只有在某顶点所代表的事件发生后,从该顶点出发的各活动才能开始; ⑵ 只有在进入某顶点的各活动都结束,该顶点所代表的事件才能发生。

148 应用举例——关键路径 AOE网 v2 a4=1 v7 a7=9 a10=2 a1=6 v5 v1 a5=1 v3 v8 a11=4 a3=5
事件 事件含义 v 开工 v 活动a1完成,活动a4可以开始 v 活动a2完成,活动a5可以开始 … ……… v 活动a10 和a11完成,整个工程完成

149 应用举例——关键路径 AOE网 AOE网可以回答下列问题: 1. 完成整个工程至少需要多少时间?
2. 为缩短完成工程所需的时间, 应当加快哪些活动? 从始点到终点的路径可能不止一条,只有各条路径上所有活动都完成了,整个工程才算完成。因此,完成整个工程所需的最短时间取决于从始点到终点的最长路径长度,即这条路径上所有活动的持续时间之和。这条路径长度最长的路径就叫做关键路径。

150 应用举例——关键路径 关键路径 关键路径:在AOE网中,从始点到终点具有最大路径长度(该路径上的各个活动所持续的时间之和)的路径称为关键路径。 关键活动:关键路径上的活动称为关键活动。 由于AOE网中的某些活动能够同时进行,故完成整个工程所必须花费的时间应该为始点到终点的最大路径长度。关键路径长度是整个工程所需的最短工期。

151 应用举例——关键路径 关键路径 要找出关键路径,必须找出关键活动, 即不按期完成就会影响整个工程完成的活动。
首先计算以下与关键活动有关的量: ⑴ 事件的最早发生时间ve[k] ⑵ 事件的最迟发生时间vl[k] ⑶ 活动的最早开始时间e[i] ⑷ 活动的最晚开始时间l[i] 最后计算各个活动的时间余量 l[k] - e[k],时间余量为0者即为关键活动。

152 应用举例——关键路径 ⑴ 事件的最早发生时间ve[k]
ve[k]是指从始点开始到顶点vk的最大路径长度。这个长度决定了所有从顶点vk发出的活动能够开工的最早时间。 vj vk ve[1]=0 ve[k]=max{ve[j]+len<vj, vk>} (<vj, vk>∈p[k]) p[k]表示所有到达vk的有向边的集合

153 应用举例——关键路径 v2 v1 v3 v4 v5 v8 v6 v7 a1=6 a4=1 a7=9 a10=2 a11=4 a9=4
ve[k]=max{ve[j]+len<vj, vk>} v2 v7 v6 v5 v4 v1 v3 v9 v8 ve[k] 6 4 5 7 7 16 14 18

154 应用举例——关键路径 ⑵ 事件的最迟发生时间vl[k] vl[k]是指在不推迟整个工期的前提下,事件vk允许的最晚发生时间。 vk
vj vk vl[n]=ve[n] vl[k]=min{vl[j]-len<vk , vj>}(<vk, vj>∈s[k]) s[k]为所有从vk发出的有向边的集合

155 应用举例——关键路径 v2 v1 v3 v4 v5 v8 v6 v7 a1=6 a4=1 a7=9 a10=2 a11=4 a9=4
vl[k]=min{vl[j]-len<vk , vj>} v2 v7 v6 v5 v4 v1 v3 v9 v8 ve[k] 6 4 5 7 7 16 14 18 vl[k] 6 6 8 7 10 16 14 18

156 应用举例——关键路径 ⑶ 活动的最早开始时间e[i]
若活动ai是由弧<vk , vj>表示,则活动ai的最早开始时间应等于事件vk的最早发生时间。因此,有: e[i]=ve[k]

157 应用举例——关键路径 v2 v1 v3 v4 v5 v8 v6 v7 a1=6 a4=1 a7=9 a10=2 a11=4 a9=4
e[i]=ve[k] v2 v7 v6 v5 v4 v1 v3 v9 v8 ve[k] 6 4 5 7 7 16 14 18 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 e[i] 6 4 5 7 7 7 16 14

158 应用举例——关键路径 ⑷ 活动的最晚开始时间l[i] 活动ai的最晚开始时间是指,在不推迟整个工期的前提下, ai必须开始的最晚时间。
若ai由弧<vk,vj>表示,则ai的最晚开始时间要保证事件vj的最迟发生时间不拖后。因此,有: l[i]=vl[j]-len<vk, vj> v2 v7 v6 v5 v4 v1 v3 v9 v8 vl[k] 6 6 8 7 10 16 14 18

159 应用举例——关键路径 v2 v1 v3 v4 v5 v8 v6 v7 a1=6 a4=1 a7=9 a10=2 a11=4 a9=4
l[i]=vl[j]-len<vk, vj> v2 v7 v6 v5 v4 v1 v3 v9 v8 vl[k] 6 6 8 7 10 16 14 18 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 l[i] 2 3 6 6 8 7 7 10 16 14

160 应用举例——关键路径 v2 a4=1 v7 a7=9 a1=6 a10=2 v5 v1 a5=1 v3 v8 a11=4 a3=5 a6=2
关键活动:l[i]=e[i]的活动 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 e[i] 6 4 5 7 7 7 16 14 l[i] 2 3 6 6 8 7 7 10 16 14

161 应用举例——关键路径 课堂练习:求u0到其他各顶点的最短路径。 b a c d 7 6 2 f e 8 1 4 3 5 u0 g

162 应用举例——关键路径 T S 7 1 2 ∞ 4 8 abcdefg u0 7 2 4 ∞ 8 abcdeg u0 f 7 3 ∞ 4 8
l(g) l(f) l(e) l(d) l(c) l(b) l(a) T S 7 1 2 4 8 abcdefg u0 7 2 4 8 abcdeg u0 f 7 3 4 8 abcdg u0 fe 6 9 4 8 abcg u0 fed 6 9 acg u0 fedb 5 6 9 cg u0 fedba 9 c u0 fedbag 7 u0 fedbagc 8


Download ppt "第六章 图 本章的主要内容是: 图的逻辑结构 图的存储结构及实现 图的连通性 最小生成树 最短路径 AOV网与拓扑排序 AOE网与关键路径."

Similar presentations


Ads by Google