数据结构图

整本书的知识点,点击右方链接整本书笔记知识点

 

 

六、图

因为课时原因,笔记中只写一些基本定义概念,遍历和应用等代码我也没学…

6.1、图的定义和基本术语

6.1.1、图的定义

图G由顶点集V和边集E组成,记为G=(V,E),其中V(G)表示图G中顶点的有限非空集;E(G)表示图G中顶点之间的关系(边)的集合。

注意:线性表可以是空表,树可以是空树,图不可以是空图,图可以没有边,但是至少要有一个顶点

有向图

若E是有向边(简称弧)的有限集合时,则G为有向图。弧是顶点的有序对,记为<v,w>,其中 v,w 是顶点。当v 是弧尾,w 是弧头时,称为从顶点v到顶点w的弧。

有向图

在这里插入图片描述

如上图所示G可表示为:

G=(V,E)

V={1,2,3}

E={<1,2>, <2,1>, <2,3>}

无向图

若E是无向边(简称边)的有限集合时,则G为无向图。边是顶点的无序对,记为 (v,w) 或(w,v) ,且有 (v,w) =(w,v) 。其中 v,w 是顶点。

无向图

在这里插入图片描述

如上图所示,无向图G可表示为:

G=(V, E)

V={1,2,3,4}

E={(1,2), (1,3), (1,4), (2,3), (2,4), (3,4)}

6.1.2、图的基本术语

①、子图

若有两个图G=(V,E),G1=(V1,E2),若V1是V的子集且E2是E的子集,称G1是G的子图。

如下面的有向完全图是有向图的一个子图。

在这里插入图片描述

②、完全图

1.无向图中任意两点之间都存在边,称为无向完全图;如无向图中的示例就是完全图。无向完全图具有 n(n-1)/2 条边

2.有向图中任意两点之间都存在方向向反的两条弧,称为有向完全图;有向完全图具有 n(n-1)条弧

如示例中的有向图就不是完全图,但如果没有顶点3和指向顶点3 的边,就是一个完全图。即下图是一个完全图。

在这里插入图片描述
有向完全图

③、稀疏图和稠密图

边树小于 nlogn 的图称为稀疏图,反之称为稠密图

④、权和网
  1. 在实际应用中,每条边可以标上具有某种含义的数值,该数值称为该边上的权,这些权可以表示从一个顶点到另一个顶点的距离或耗费
  2. 带权的图称为网
⑤、邻接点

E是边的有限集合

对于下面的无向图G,边 (1,2) ∈ E ,则称顶点 1 和 2 互为邻接点,即 1 和 2 相邻接

边 (1,2) 依附于顶点 1 和 2,或者说边 (1,2) 与顶点 1 和 2 相关联

在这里插入图片描述

⑥、顶点的度、入度和出度

顶点的度为以该顶点为一个端点的边的数目

对于无向图,顶点的边数为度,度数之和是顶点边数的两倍

对于有向图,入度是以顶点为终点(即箭头所指方向),出度是以顶点为起点 (即箭尾巴所指方向)

有向图的全部顶点入度之和等于出度之和且等于边数。顶点的度等于入度与出度之和

注意:入度与出度是针对有向图来说的

⑦、路径和路径长度

路径:在图中,两点间边构成的序列

在无向图中,比如图中0到6中一条路径0 -> 1 -> 3 -> 2 -> 6。一般图中两点之间的路径不止一条。这里的路径只要找到一条就返回。

在这里插入图片描述

对于有向图,则路径也是有向的

⑧、回路或环

第一个顶点和最后一个顶点相同的路径称为回路或环

⑨、简单路径、简单回路或简单环

顶点不重复出现的路径称为简单路径。

除第一个顶点和最后一个顶点外,其余顶点不重复出现的回路称为简单回路或简单环

在这里插入图片描述

⑩、连通、连通图、连通分量

在无向图中,两顶点有路径存在,就称为连通的。

若图中任意两顶点都连通,同此图为连通图。无向图中的极大连通子图称为连通分量。

以下面两个图为例,下面的图是上面的图的连通分量,并且下面的图是连通图。上面图中 I与J 也是连通的。

在这里插入图片描述

上图的两个连通分量

在这里插入图片描述

⑪、强连通图、强连通分量

在有向图中,两顶点两个方向都有路径,两顶点称为强连通。若任一顶点都是强连通的,称为强连通图

有向图中极大强连通子图为有向图的强连通分量

在这里插入图片描述

⑫、连通图的生成树(无向树)

连通图的生成树是包含图中全部顶点的一个极小连通子图,若图中有n个顶点,则生成树有n-1条边,仅有足以构成一颗树的 n-1 条边

所以对于生成树而言,若砍去一条边,就会变成非连通图,若加上一条边,则构成一个环,因为这条边使得他依附的那两个顶点之间有了第二条路径

在这里插入图片描述

在这里插入图片描述

⑬、有向树和生成森林

有一个顶点的入度为0,其余顶点的入度均为1的有向图称作有向树。如下图:

在这里插入图片描述
有向树

一个有向图的生成森林是由若干棵有向树组成,含有图中全部顶点,但只有足以构成若干棵不相交的有向树的弧

在这里插入图片描述

6.2、案例引入

6.3、图的类型定义

6.4、图的存储结构

6.4.1、邻接矩阵法(数组表示法)

图的邻接矩阵的存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或弧的信息(可分别称他们为顶点数组和边数组)。

在无向图中,求某个顶点的度,即计算此顶点vi在邻接矩阵中第i行(或第i列)的元素之和。若vi到vj之间有通路,则记为1,反之为0。在有向图中,求某个顶点vi的出度,即求此顶点所在行的元素之和,若求某个顶点的度,即求顶点所在列的元素之和。

设图G有n个顶点,则邻接矩阵是一个n×n的方阵

在这里插入图片描述

 

在这里插入图片描述

 

在这里插入图片描述

邻接矩阵表示法的优缺点:

  1. 优点:
    • 便于判断两个顶点之间是否有边, 即根据A[i] [j] = 0或1来判断
    • 便于计算各个顶点的度。对于无向图,邻接矩阵第 i 行元素之和就是顶点 i 的度;对于有向图,第 i 行元素之和就是顶点 i 的出度,第 i 列元素之和就是顶点 i 的入度
  2. 缺点:
    • 不便于增加和删除顶点
    • 不便于统计边的数目,需要扫描邻接矩阵所有元素才能统计完毕,时间复杂度为 O(n2)
    • 空间复杂度高

伪码等因为课时缩短不学,可以看下方超链接

图的存储结构伪码

6.4.2、邻接表

对图中的每个顶点建立一个单链表,存储该顶点所有邻接顶点及其相关信息。每一个单链表设有一个表头结点

把从一个顶点出发的所有边链接在一个单链表(又名边链表)中

把所有边链表的表头结点放在一个顺序表(又名顶点表)中

在这里插入图片描述

对于有向图,邻接表又称正邻接表或出度表

在这里插入图片描述

在这里插入图片描述

有向图的逆邻接表又称入度表

在这里插入图片描述

邻接表表示法的优缺点:

  1. 优点

    • 便于增加和删除结点
    • 便于统计边的数目
    • 空间效率高
  2. 缺点

    • 不便于判断顶点之间是否有边
    • 不便于计算有向图各个顶点的度

创建邻接表等伪码、图的数据结构伪码

6.4.3、十字链表

6.4.3、邻接多重表

十字链表和邻接多重表跳转链接

图解图的四种存储结构

6.5、图的遍历

6.5.1、深度优先搜索

算法思想

**深度优先搜索思想:**假设初始状态是图中所有顶点均未被访问,则从某个顶点v出发,首先访问该顶点,然后依次从它的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和v有路径相通的顶点都被访问到。若此时尚有其他顶点未被访问到,则另选一个未被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。

算法特点

深度优先搜索是一个递归的过程。首先,选定一个出发点后进行遍历,如果有邻接的未被访问过的节点则继续前进。若不能继续前进,则回退一步再前进,若回退一步仍然不能前进,则连续回退至可以前进的位置为止。重复此过程,直到所有与选定点相通的所有顶点都被遍历。

深度优先遍历类似于二叉树的先序遍历

深度优先遍历通常借助栈来实现算法

图解过程

无向图深度优先搜索

以下图中所示无向图说明深度优先搜索遍历过程。

在这里插入图片描述

  1. 首先选取顶点A为起始点,输出A顶点信息,并标记A为已访问顶点
  2. A的邻接顶点有C、D、F,从中任意选取一个顶点前进。这里我们选取C顶点为前进位置顶点。输出C顶点信息,并标记C为已访问顶点。当前位置指向顶点C
  3. 顶点C的邻接顶点有A、D和B,此时A已经标记为已访问顶点,因此不能继续访问。从B或者D中选取一个顶点前进,这里我们选取B顶点为前进位置顶点。输出B顶点信息,标记B顶点为已访问顶点。当前位置指向顶点B
  4. 顶点B的邻接顶点只有C、E,C已被标记,不能继续访问,因此选取E为前进位置顶点,输出E顶点信息,标记E顶点,当前位置指向E
  5. 顶点E的邻接顶点均已被标记,此时无法继续前进,则需要进行回退。将当前位置回退至顶点B
  6. 顶点B的邻接顶点也均被标记,需要继续回退,当前位置回退至C
  7. 顶点C可以前进的顶点位置为D,则输出D顶点信息,并标记D顶点。当前位置指向顶点D
  8. 顶点D没有前进的顶点位置,因此需要回退操作。将当前位置回退至顶点C
  9. 顶点C没有前进的顶点位置,继续回退,将当前位置回退至顶点A
  10. 顶点A前进的顶点位置为F,输出F顶点信息,并标记F。将当前位置指向顶点F
  11. 顶点F的前进顶点位置为G,输出G顶点信息,并标记G。将当前位置指向顶点G
  12. 顶点G没有前进顶点位置,回退至F。当前位置指向F
  13. 顶点F没有前进顶点位置,回退至A,当前位置指向A
  14. 顶点A没有前进顶点位置,继续回退,发现没有可用回退的顶点,则以A为起始的遍历结束。若图中仍有未被访问的顶点,则选取未访问的顶点为起始点,继续执行此过程。直至所有顶点均被访问
  15. 采用深度优先搜索遍历顺序为A->C->B->E->D->F->G

有向图深度优先搜索

以图中所示有向图说明深度优先搜索遍历过程

在这里插入图片描述

  1. 以顶点A为起始点,输出A,并标记A。当前位置指向A
  2. 以A为尾的边只有1条,且边的头为顶点B,则前进位置为顶点B,输出B,标记B。当前位置指向B
  3. 顶点B可以前进的位置有C与F,选取F为前进位置,将F入栈,并标记F。当前位置指向F
  4. 顶点F的前进位置为G,输出G,并标记G。当前位置指向G
  5. 顶点G没有可以前进的位置,则回退至F,当前位置指向F
  6. 顶点F没有可以前进的位置,继续回退至B,当前位置指向B
  7. 顶点B可以前进位置为C和E,选取E,输出E,并标记E。当前位置指向E
  8. 顶点E的前进位置为D和B,而B已经被标记为输出过,则输出D,并标记D。当前位置指向D
  9. 顶点D的前进位置为C,输出C,并标记C。当前位置指向C
  10. 顶点C没有前进位置,进行回退至D
  11. 继续执行此过程,发现没有可以回退的顶点,以A为起始点的遍历过程结束。若图中仍有未被访问的顶点,则选取未访问的顶点为起始点,继续执行此过程。直至所有顶点均被访问。
  12. 输出次序:A、B、F、G、E、D、C

6.5.2、广度优先搜索

算法思想

**广度优先搜索思想:**从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使得“先被访问的顶点的邻接点先于后被访问的顶点的邻接点被访问,直至图中所有已被访问的顶点的邻接点都被访问到。如果此时图中尚有顶点未被访问,则需要另选一个未曾被访问过的顶点作为新的起始点,重复上述过程,直至图中所有顶点都被访问到为止。

算法特点

广度优先搜索类似于树的层次遍历,是按照一种由近及远的方式访问图的顶点。在进行广度优先搜索时需要使用队列存储顶点信息。

广度优先遍历通常借助队列来实现算法

图解过程

无向图的广度优先搜索

图所示的无向图,采用广度优先搜索过程。

在这里插入图片描述

(1)选取A为起始点,输出A,A入队列,标记A,当前位置指向A。

在这里插入图片描述

(2)队列头为A,A出队列。A的邻接顶点有B、E,输出B和E,将B和E入队,并标记B、E。当前位置指向A。

在这里插入图片描述

(3)队列头为B,B出队列。B的邻接顶点有C、D,输出C、D,将C、D入队列,并标记C、D。当前位置指向B。

在这里插入图片描述

(4)队列头为E,E出队列。E的邻接顶点有D、F,但是D已经被标记,因此输出F,将F入队列,并标记F。当前位置指向E。

在这里插入图片描述

(5)队列头为C,C出队列。C的邻接顶点有B、D,但B、D均被标记。无元素入队列。当前位置指向C。

在这里插入图片描述

(6)队列头为D,D出队列。D的邻接顶点有B、C、E,但是B、C、E均被标记,无元素入队列。当前位置指向D。

在这里插入图片描述

(7)队列头为F,F出队列。F的邻接顶点有G、H,输出G、H,将G、H入队列,并标记G、H。当前位置指向F。

在这里插入图片描述

(8)队列头为G,G出队列。G的邻接顶点有F,但F已被标记,无元素入队列。当前位置指向G。

在这里插入图片描述

(9)队列头为H,H出队列。H的邻接顶点有F,但F已被标记,无元素入队列。当前位置指向H。

在这里插入图片描述

(10)队列空,则以A为起始点的遍历结束。若图中仍有未被访问的顶点,则选取未访问的顶点为起始点,继续执行此过程。直至所有顶点均被访问。

则访问次序为:A、B、E、C、D、F、G、H

有向图的广度优先搜索

以图所示的有向图为例进行广度优先搜索。

在这里插入图片描述

(1)选取A为起始点,输出A,将A入队列,标记A。

在这里插入图片描述

(2)队列头为A,A出队列。以A为尾的边有两条,对应的头分别为B、C,则A的邻接顶点有B、C。输出B、C,将B、C入队列,并标记B、C。

在这里插入图片描述

(3)队列头为B,B出队列。B的邻接顶点为C,C已经被标记,因此无新元素入队列。

在这里插入图片描述

(4)队列头为C,C出队列。C的邻接顶点有E、F。输出E、F,将E、F入队列,并标记E、F。

在这里插入图片描述

(5)队列头为E,E出队列。E的邻接顶点有G、H。输出G、H,将G、H入队列,并标记G、H。

在这里插入图片描述

(6)队列头为F,F出队列。F无邻接顶点。

在这里插入图片描述

(7)队列头为G,G出队列。G无邻接顶点。

在这里插入图片描述

(8)队列头为H,H出队列。H邻接顶点为E,但是E已被标记,无新元素入队列。

在这里插入图片描述

(9)队列为空,以A为起始点的遍历过程结束,此时图中仍有D未被访问,则以D为起始点继续遍历。选取D为起始点,输出D,将D入队列,标记D。

在这里插入图片描述

(10)队列头为D,D出队列,D的邻接顶点为B,B已被标记,无新元素入队列。

在这里插入图片描述

(11)队列为空,且所有元素均被访问,广度优先搜索遍历过程结束。广度优先搜索的输出序列为:A->B->E->C->D->F->G->H。

转载于:图的两种遍历方式

案例:
在这里插入图片描述

 

DFS:首先从 1 链表开始找,找到 2 ,再根据链表2 找到 4(1已经被找到,所以跳过),然后根据链表4 找到 3,再根据链表3 找到 5 ,然后根据链表5找到6。 即:1,2,4,3,5,6

BFS:1为起始点,输出1,1入队列

队列头为1,1出队列,与1的邻接顶点为2,3.输出2,3。将2,3入队

队列头为2,2出队列,与2的邻接顶点为1,4,但是1已经输出,输出4,将4入队

队列头为3,3出队列,与3的邻接顶点为 1,4,5,但是1,4已经输出,输出5,将5入队

队列头为4,4出队列,与4的邻接顶点为2,3,6,但是2,3已经输出,输出6,将6入队

队列头为5,5出队列,与5的邻接顶点都已经输出

队列头为6,6出队列,与6的邻接顶点都已经输出

队列为空,BFS遍历结束

6.6、图的应用

6.6.1、最小生成树

首先关于树的生成树:

在这里插入图片描述

广度:1邻接2,3,然后2邻接4,5,然后3邻接6,7,最后4邻接8

深度:1后2, 2后4, 4后8, 8后5, 5后面没有,然后返回8, 8后6, 6后3, 3后7

一、普里姆算法(Prim)

普利姆算法从始至终始终是一整棵树

算法的时间复杂度为O(n2),与图中边数无关,该算法适合于稠密图

首先随意找一个顶点,一般都是v1,然后找到与v1相连的权值最小的边(若有多条,则随机选取一条),然后找与这两个点相连的有最小权值的边,然后与找这三个点相连权值最小的边,一直重复,直到有n-1条边,并且连接完所有的顶点,注意,不能形成环。

在这里插入图片描述

二、克鲁斯卡尔算法(Kruskal)

基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路。
具体做法:首先构造一个只含n个顶点的森林,然后依权值从小到大从连通网中选择边加入到森林中,并使森林中不产生回路,直至森林变成一棵树为止。

时间复杂度为:O(eloge) 边数e越大,所耗费时间越长,则适合稀疏图

在这里插入图片描述

因为课时原因,伪码略,具体可以看超链接

最小生成树伪码

6.6.2、最短路径

最短路径问题:如果从有向图中某一顶点(称为源点)到达另一顶点(称为终点)的路径可能不止一条,如何找到一条路径使得沿此路径上各边上的权值总和达到最小

一、迪杰斯拉(Dijkstra)算法

以D为开头,求D到各个点的最短距离。

在这里插入图片描述

第1步:初始化距离,其实指与D直接连接的点的距离。dis[c]代表D到C点的最短距离,因而初始dis[C]=3,dis[E]=4,dis[D]=0,其余为无穷大。设置集合S用来表示已经找到的最短路径。此时,S={D}。现在得到D到各点距离**{D(0),C(3),E(4),F(*),G(*),B(*),A(*)}**,其中*代表未知数也可以说是无穷大,括号里面的数值代表D点到该点的最短距离。

第2步:不考虑集合S中的值,因为dis[C]=3,是当中距离最短的,所以此时更新S,S={D,C}。接着我们看与C连接的点,分别有B,E,F,已经在集合S中的不看,dis[C-B]=10,因而dis[B]=dis[C]+10=13,dis[F]=dis[C]+dis[C-F]=9,dis[E]=dis[C]+dis[C-E]=3+5=8>4**(初始化时的dis[E]=4)不更新。此时{D(0),C(3),E(4),F(9),G(*),B(13),A(*)}。**

第3步:在第2步中,E点的值4最小,更新S={D,C,E},此时看与E点直接连接的点,分别有F,G。dis[F]=dis[E]+dis[E-F]=4+2=6(比原来的值小,得到更新),dis[G]=dis[E]+dis[E-G]=4+8=12(更新)。此时**{D(0),C(3),E(4),F(6),G(12),B(13),A(*)}**。

第4步:在第3步中,F点的值6最小,更新S={D,C,E,F},此时看与F点直接连接的点,分别有B,A,G。dis[B]=dis[F]+dis[F-B]=6+7=13,dis[A]=dis[F]+dis[F-A]=6+16=22,dis[G]=dis[F]+dis[F-G]=6+9=15>12(不更新)。此时**{D(0),C(3),E(4),F(6),G(12),B(13),A(22)}.**

第5步:在第4步中,G点的值12最小,更新S={D,C,E,F,G},此时看与G点直接连接的点,只有A。dis[A]=dis[G]+dis[G-A]=12+14=26>22(不更新)。{D(0),C(3),E(4),F(6),G(12),B(13),A(22)}.

第6步:在第5步中,B点的值13最小,更新S={D,C,E,F,G,B},此时看与B点直接连接的点,只有A。dis[A]=dis[B]+dis[B-A]=13+12=25>22(不更新)。{D(0),C(3),E(4),F(6),G(12),B(13),A(22)}.

第6步:最后只剩下A值,直接进入集合S={D,C,E,F,G,B,A},此时所有的点都已经遍历结束,得到最终结果**{D(0),C(3),E(4),F(6),G(12),B(13),A(22)}.**

在这里插入图片描述

文字转载于:https://zhuanlan.zhihu.com/p/40338107

图转载于:https://blog.csdn.net/heroacool/article/details/51014824

伪码等也在其中

二、弗洛伊德算法

因为课时原因:跳转链接自学

弗洛伊德算法

6.6.3、拓扑排序

一个无环的有向图称作为有向无环图,简称DAG图。

AOV网:用顶点表示活动,用弧表示活动间的优先关系的有向图称为顶点表示活动的网,简称AOV网

在AOV网中,不应该出现有向环,因为存在环意味着某项活动应以自己为先决条件

所谓拓扑排序就是将AOV网中所有顶点排成一个线性序列

举个例子,学习java系列的教程
在这里插入图片描述

就比如学习java系类(部分)从java基础,到jsp/servlet,到ssm,到springboot,springcloud等是个循序渐进且有依赖的过程。在jsp学习要首先掌握java基础和html基础。学习框架要掌握jsp/servlet和jdbc之类才行。那么,这个学习过程即构成一个拓扑序列。当然这个序列也不唯一,你可以对不关联的学科随意选择顺序(比如html和java可以随便先开始哪一个。)

那上述序列可以简单表示为:
在这里插入图片描述

其中五种均为可以选择的学习方案,对课程安排可以有参考作用,当然,五个都是拓扑序列。只是选择的策略不同!

规则:

图中每个顶点只出现一次。
A在B前面,则不存在B在A前面的路径。(不能成环!!!!)
顶点的顺序是保证所有指向它的下个节点在被指节点前面!(例如A—>B—>C那么A一定在B前面,B一定在C前面)。所以,这个核心规则下只要满足即可,所以拓扑排序序列不一定唯一!

拓扑排序算法分析

在这里插入图片描述

正常步骤为(方法不一定唯一):

从DGA图中找到一个没有前驱的顶点输出。(可以遍历,也可以用优先队列维护)
删除以这个点为起点的边。(它的指向的边删除,为了找到下个没有前驱的顶点)
重复上述,直到最后一个顶点被输出。如果还有顶点未被输出,则说明有环!
对于上图的简单序列,可以简单描述步骤为:

1:删除1或2,并输出
在这里插入图片描述

2:删除2或3以及对应边
在这里插入图片描述

3:删除3或者4以及对应边
在这里插入图片描述

4:重复以上规则步骤
在这里插入图片描述

这样就完成一次拓扑排序,得到一个拓扑序列,但是这个序列并不唯一!从过程中也看到有很多选择方案,具体得到结果看你算法的设计了。但只要满足即是拓扑排序序列。

另外观察 1 2 4 3 6 5 7 9这个序列满足我们所说的有关系的节点指向的在前面,被指向的在后面。如果完全没关系那不一定前后(例如1,2)

转载于:拓扑排序

6.6.4、关键路径

AOE网:在一个表示工程的带权有向图中,用顶点表示事件(如V0),用有向边表示**活动(如<v0,v1> = a1),**边上的权值表示活动的持续时间,称这样的有向图为边表示的活动的网,简称AOE网(activity on edge network)

AOE网是一个带权的有向无环图

源点:

在AOE网中,没有入边的顶点称为源点;如顶点V0

终点:

在AOE网中,没有出边的顶点称为终点;如顶点V3

AOE网的性质:

【1】只有在进入某顶点的活动都已经结束,该顶点所代表的事件才发生;

​ 例如:a1和a2活动都结束了,顶点V2所代表的事件才会发生。

【2】只有在某顶点所代表的事件发生后,从该顶点出发的各活动才开始;

​ 例如:只有顶点V1所代表的事件结束之后,活动a2和a4才会开始。

在AOE网中,所有活动都完成才能到达终点,因此完成整个工程所必须花费的时间(即最短工期)应该为源点到终点的最大路径长度。具有最大路径长度的路径称为关键路径。关键路径上的活动称为关键活动

在这里插入图片描述

在这里插入图片描述

事件的最早发生时间:ve[k]

从源点向终点方向计算
 
ve[0] = 0
 
ve[1] = ve[0] + a0 = 0 + 4 = 4
 
ve[2] = max( ve[0] + a1, ve[1] + a2 ) = max(0 + 3, 4 + 2 )= 6
 
ve[3] = max(ve[1] + a4, ve[2] + a3) = max(4 + 6, 6+4) = 10

事件的最迟发生时间:vl[k]

从终点向源点方向计算
 
vl[3] = ve[3] = 10
 
vl[2] = vl[3] - a3 = 10 - 4 = 6
 
vl[1] = min(vl[3] - a4, vl[2] - a2) = min(10-6, 6-2) = 4

vl[0] = min(vl[2] - a1, vl[1] - a0) = min(4-4, 4-2) = 0

活动的最早发生时间:e[i]

共有五个活动:
 
e[0] = ve[0] = 0
 
e[1] = ve[0] = 0
 
e[2] = ve[1] = 4
 
e[3] = ve[2] = 6
 
e[4] = ve[1] = 4

活动的最迟发生时间:el[i]

l[0] = v[1] - a0 = 4 - 4 = 0
 
l[1] = vl[2] - a1 = 6 - 3 = 3
 
l[2] = vl[2] - a2 = 6 - 2 = 4
 
l[3] = vl[3] - a3 = 10 - 4 = 6
 
l[4] = vl[3] - a4 = 10 - 6 = 4

活动的最早开始时间和最晚开始时间相等,则说明该活动时属于关键路径上的活动,即关键活动。

经过比较,得出关键活动有:a0, a2, a3, a4,因为不能有环,画出示意图如下:

在这里插入图片描述

该AOE网有两条关键路径。

所以,通过此案例也可以发现,一个AOE网的关键路径可能有多条。

转载于:关键路径

原博客有一点点错误,这里更改了一点:ve[3] = max(ve[1] + a4, ve[2] + a3) = max(4 + 6, 3 + 4) = 10 应改为:ve[3] = max(ve[1] + a4, ve[2] + a3) = max(4 + 6, 6 + 4) = 10

案例:在这里插入图片描述

第六章小结

在这里插入图片描述

在这里插入图片描述

第六章习题

(1)在一个图中,所有顶点的度数之和等于图的边数的( )倍。

A.1/2 B.1 C.2 D.4

答案:C

(2)在一个有向图中,所有顶点的入度之和等于所有顶点的出度之和的( )倍。

A.1/2 B.1 C.2 D.4

答案:B

解释:有向图所有顶点入度之和等于所有顶点出度之和。

(3)具有n个顶点的有向图最多有( )条边。

A.n B.n(n-1) C.n(n+1) D.n2

答案:B

解释:有向图的边有方向之分,即为从n个顶点中重复选取2个顶点有序排列,结果为n(n-1)。

(4)n个顶点的连通图用邻接距阵表示时,该距阵至少有( )个非零元素。

A.n B.2(n-1) C.n/2 D.n2

答案:B

所谓连通图一定是无向图,有向图叫强连通图

连通n个顶点,至少只需要n-1条边就可以了,由于无向图的每条边同时关联两个顶点,因此邻接矩阵中每条边被存储了两次(也就是说是对称矩阵),因此至少有2(n-1)个非零元素

(5)G是一个非连通无向图,共有28条边,则该图至少有( )个顶点。

A.7 B.8 C.9 D.10

答案:C

解释:8个顶点的无向图最多有8*7/2=28条边,再添加一个点即构成非连通无向图,故至少有9个顶点。

(6)若从无向图的任意一个顶点出发进行一次深度优先搜索可以访问图中所有的顶点,则该图一定是( )图。

A.非连通 B.连通 C.强连通 D.有向

答案:B

解释:即从该无向图任意一个顶点出发有到各个顶点的路径,所以该无向图是连通图。

(7)下面( )算法适合构造一个稠密图G的最小生成树。

A. Prim算法 B.Kruskal算法 C.Floyd算法 D.Dijkstra算法

答案:A

解释:Prim算法适合构造一个稠密图G的最小生成树,Kruskal算法适合构造一个稀疏图G的最小生成树。

(8)用邻接表表示图进行广度优先遍历时,通常借助( )来实现算法。

A.栈 B. 队列 C. 树 D.图

答案:B

解释:广度优先遍历通常借助队列来实现算法,深度优先遍历通常借助栈来实现算法。

(9)用邻接表表示图进行深度优先遍历时,通常借助( )来实现算法。

A.栈 B. 队列 C. 树 D.图

答案:A

解释:广度优先遍历通常借助队列来实现算法,深度优先遍历通常借助栈来实现算法。

(10)深度优先遍历类似于二叉树的( )。

A.先序遍历 B.中序遍历 C.后序遍历 D.层次遍历

答案:A

(11)广度优先遍历类似于二叉树的( )。

A.先序遍历 B.中序遍历 C.后序遍历 D.层次遍历

答案:D

(12)图的BFS生成树的树高比DFS生成树的树高( )。

A.小 B.相等 C.小或相等 D.大或相等

答案:C

解释:对于一些特殊的图,比如只有一个顶点的图,其BFS生成树的树高和DFS生成树的树高相等。一般的图,根据图的BFS生成树和DFS树的算法思想,BFS生成树的树高比DFS生成树的树高小。

(13)已知图的邻接矩阵如图6.30所示,则从顶点v0出发按深度优先遍历的结果是( )。

在这里插入图片描述

​ 图6.30 邻接矩阵

答案:C

因为是深度优先,找到与顶点0直接相连的结点,由邻接矩阵知道是顶点1(多个相邻节点取第一个找到的未遍历到的结点),然后再在邻接矩阵中找与顶点1直接相连的结点,得到顶点3.相同方法找到后续结点为:顶点4,顶点2.因为顶点2的相连结点都已被遍历,所以退回到顶点4继续遍历,遍历到顶点5,然后是顶点6

(14)已知图的邻接表如图6.31所示,则从顶点v0出发按广度优先遍历的结果是( ),按深度优先遍历的结果是( )。

在这里插入图片描述

图6.31 邻接表

A.0 1 3 2 B.0 2 3 1 C.0 3 2 1 D.0 1 2 3

答案:D、D

广度:访问V0,依次访问其未访问的邻接顶点(顺着链表)

深度:首先邻的结点 1,然后找到 2,然后找到 3

(15)下面( )方法可以判断出一个有向图是否有环

A.深度优先遍历 B.拓扑排序 C.求最短路径 D.求关键路径

答案:B

在这里插入图片描述

  • 80
    点赞
  • 209
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值