第八章 图

引言

  1. 文章大纲:本文由知识点思维导图,注意事项与易错点,题型总结,方法心得四部分组成。
  2. 思维导图中,标红的是重点内容,标黄的是次重点。
  3. 码字不易,如果这篇文章对您有帮助的话,希望您能点赞、收藏、加关注!您的鼓励就是我前进的动力!

知识点思维导图

在这里插入图片描述
点此查看原图

补充:

  1. 邻接表
    1)优点:空间效率高,容易寻找顶点的邻接点;
    2)缺点:判断两顶点间是否有边或弧,需搜索两结点对应的单链表,没有邻接矩阵方便。
    3)邻接矩阵的空间复杂度为O(n2),而邻接表的空间复杂度O(n+e)。
    4)邻接矩阵多用于稠密图的存储,邻接表多用于稀疏图的存储。
  2. 图的遍历
    1)为避免访问多次,常设置一个访问数组,访问前的元素标志为0,访问后设置为1。
    2)深度优先搜索是一种递归的过程。
    3)深度和广度优先遍历得到的序列不唯一。
    4)若图是连通的或强连通的,则从图中某一个顶点出发可以访问到图中所有顶点,否则只能访问到一部分顶点,再从未被访问的顶点中选一个顶点出发访问未被访问的顶点。
    5)广度优先生成树高度 ≤ 深度优先生成树高度

注意事项与易错点

  1. 用Prim算法构建最小生成树时,注意每一轮选边时,要将已选顶点一起作为一组,找出这一组中,到剩余结点中权最小的边,而不是只看新加入结点的最小边。

题型总结

一、求关键路径

  1. 五个描述量:
    1)ve( vj ) 表示事件(即图中的顶点) vj 的最早发生时间。计算方法: v e ( 1 ) = 0 ve(1)=0 ve(1)=0 开始向前递推, v e ( j ) = M a x [ v e ( i ) + W i , j ] ve(j)=Max[ve(i)+W_{i,j}] ve(j)=Max[ve(i)+Wi,j]
    即事件的最早发生时间,等于该事件的前一个事件的最早发生时间加上两个事件之间的弧上的权值,该事件的前一个事件若有多个,则取结果最大的。
    2)vl( vj ) 表示事件 vj 的最晚发生时间。计算方法: v l ( n − 1 ) = v e ( n − 1 ) vl(n-1)=ve(n-1) vl(n1)=ve(n1) 开始向后递推, v l [ i ] = M i n [ v l [ j ] − W i , j ] vl[i]=Min[vl[j]-W_{i,j}] vl[i]=Min[vl[j]Wi,j]
    即事件的最晚发生时间,等于该事件的后一个事件的最晚发生时间减去两个事件之间的弧上的权值,该事件的后一个事件若有多个,则取结果最小的。
    3)e( i ) 表示活动(即图中的弧) ai 的最早开始时间。计算方法: e ( i ) = v e ( j ) e(i) = ve(j) e(i)=ve(j)
    即活动的最早开始时间等于(弧尾)事件的最早开始时间。
    4)l( i ) 表示活动 ai 的最晚开始时间。计算方法: l ( i ) = v l ( k ) − W i , j l(i)=vl(k)-W_{i,j} l(i)=vl(k)Wi,j
    即活动的最晚开始时间等于(弧头)事件的最晚发生时间减去活动所需时间(弧上的权值)。
    5)时间余量 l ( i ) − e ( i ) l(i) - e(i) l(i)e(i)
  2. 求关键路径的步骤:
    1)列表求 v e ( i ) ve(i) ve(i) v e ( j ) ve(j) ve(j)(见下表)
    2)列表求 e ( i ) e(i) e(i) e ( j ) e(j) e(j) e ( i ) − e ( j ) e(i) - e(j) e(i)e(j)(见下表)
    3)表中所有 e ( i ) − e ( j ) e(i) - e(j) e(i)e(j) 等于0的弧组成的路径就是关键路径。
顶点 v ( e ) v(e) v(e) v ( l ) v(l) v(l)
V 1 V1 V1
V 2 V2 V2
……
V n Vn Vn
活动 e ( i ) e(i) e(i) l ( i ) l(i) l(i) e ( i ) − l ( i ) e(i)-l(i) e(i)l(i)
a 1 a1 a1
a 2 a2 a2
……
a n an an

(详解见青岛大学-王卓老师数据结构与算法-关键路径

二、Dijkstra算法(求单源最短路径)

  1. 步骤:
    1)初始化:先找出从源点到各个终点的直达路径 ( v 0 , v k ) (v_0,v_k) (v0,vk),即通过一条弧到达的路径。
    2)选择:从这些路径中找出一条长度最短的路径 ( v 0 , u ) (v_0,u) (v0,u)
    3)更新:然后对其余各条路径进行适当调整,若图中存在弧 ( u , v k ) (u,v_k) (u,vk),且 ( v 0 , u ) + ( u , v k ) < ( v 0 , v k ) (v_0,u)+(u,v_k)<(v_0,v_k) (v0,u)+(u,vk)<(v0,vk),则以路径 ( v 0 , u , v k ) (v_0,u,v_k) (v0,u,vk) 代替 ( v 0 , v k ) (v_0,v_k) (v0,vk),在调整后的各条路径中,再找长度最短的路径,以此类推。
  2. 注意:
    1)把V集合分为 S 和 T 两组,其中S是已求出最短路径的顶点集合;T是尚未确定最短路径的顶点集合(即T=V - S)。
    2)将T中顶点按照最短路径递增的次序加入到S中。
  3. 例题:求下图的最短路径:
    在这里插入图片描述解析:
    1)初始化:从 v 0 v_0 v0能直达 v 1 v_1 v1 v 2 v_2 v2 v 4 v_4 v4 v 6 v_6 v6,故在下表中第一列对应格填入距离和路径,无法直达的填∞。
    2)选择:其中路径长度最小的是 < v 0 , v 2 > <v_0,v_2> <v0,v2>(为8)故写在 v j v_j vj处。
    3)更新:在S集合加入顶点 v 2 v_2 v2后,后面就不用在考虑 v 2 v_2 v2了( v 0 v_0 v0 v 2 v_2 v2的最短路径已经确定了),故在表格中将后续的 v 2 v_2 v2划掉。再看加入 v 2 v_2 v2后,可直达的路径有没有变得更短,有则更新,没有保持不变,数据填入第二列中,其中 v 0 v_0 v0 v 1 v_1 v1的路径最短,故将其填入第二列的 v j v_j vj中。
    4)以此类推,填好该表格,表格的最后一行和最后一列所表示的路径即为从 v 0 v_0 v0到各顶点的最短路径。
    在这里插入图片描述

(详解见青岛大学-王卓老师数据结构与算法-Dijkstra算法

三、Floyd算法(求所有顶点间的最短路径)

  1. 算法思想:逐个顶点试探,从 v i v_i vi v j v_j vj的所有可能存在的路径中选出一条长度最短的路径。
  2. 解题步骤:
    1)初始时设置一个n阶方阵,令其对角线元素为0,若存在弧 < V i , V j > <V_i,V_j> <Vi,Vj>,则对应元素为权值;否则为∞。
    2)逐步试着在原直接路径中增加中间顶点,若加入中间点后路径变短,则修改之;否则,维持原值。
    3)所有顶点试探完毕,算法结束。
  3. 补充:
    1)也可以用 Dijkstra算法 来计算所有顶点间的最短路径,但较为复杂。
    2)该算法的时间复杂度和 Dijkstra算法 的时间复杂度均为 O ( n 3 ) O(n^3) O(n3),但该方法较为简单。

(详解见青岛大学-王卓老师数据结构与算法-Floyd算法

方法心得

NULL

参考资料:
[1] 程杰. 大话数据结构. 北京:清华大学出版社, 2020.
[2]严蔚敏,吴伟民. 数据结构 (C语言版). 北京:清华大学出版社, 1997.
[3]青岛大学-王卓老师数据结构与算法课:关键路径Dijkstra算法Floyd算法

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沉远

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值