【算法证明 六】深入理解广度优先搜索

这篇具有很好参考价值的文章主要介绍了【算法证明 六】深入理解广度优先搜索。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

看了算法导论,才知道自己理解的深搜、广搜有多肤浅。

搜索算法非常直观,容易理解。只要简单学过其思想,都能在做算法题时自己写出来,或者模板背出来。但是这些是图论算法的基础,如果不把搜索算法的方方面面研究透彻,很难再学习更难得图论算法。接下来两篇文章将探索图搜索算法的方方面面。本问将证明广度优先搜索求最短路的正确性,证明过程中会导出广搜算法中得一些重要性质。而下一篇文章将使用深度优先搜索实现强连通分量算法的正确性。

算法描述

为了全面的考察广度优先搜索算法,我们将给节点加入一些状态。

  • v . c o l o r :初始状态为白色,被发现时改为灰色,其所有的邻接节点都被发现时,变为黑色。所以灰色代表被发现节点和未被发现的节点的边界。 v.color:初始状态为白色,被发现时改为灰色,其所有的邻接节点都被发现时,变为黑色。所以灰色代表被发现节点和未被发现的节点的边界。 v.color:初始状态为白色,被发现时改为灰色,其所有的邻接节点都被发现时,变为黑色。所以灰色代表被发现节点和未被发现的节点的边界。
  • v . d :初始 s 节点到 v 节点的距离 ( 算法发现 v 时得到得 s 到 v 的简单路径的边的数量 ) v.d:初始s节点到v节点的距离(算法发现v时得到得s到v的简单路径的边的数量) v.d:初始s节点到v节点的距离(算法发现v时得到得sv的简单路径的边的数量)
  • v . π : v 的前驱节点,也就是说是从哪个节点发现 v 的,初始化为 n i l v.\pi: v的前驱节点,也就是说是从哪个节点发现v的,初始化为 nil v.π:v的前驱节点,也就是说是从哪个节点发现v的,初始化为nil
BFS(G, s)
	for v in G.V:
		v.color = white
		v.d = Inf
		v.Π = nil
	s.color = gray
	s.d = 0
	s.Π = nil
	que = empty
	que.push(s)
	while !que.empty()
		u = que.pop()
		for v in G.adj[v]:
			if v.color == white:
				v.color = gray
				v.d = u.d + 1
				v.Π = u
				que.push(v)
		u.color = black

复杂度分析

算法使用聚合分析的思想。队列中存放的是节点v。根据代码,每个节点只会入队、出队一次,所以队列操作的复杂度为 O ( V ) O(V) O(V)。此外,算法 13 行对每个节点遍历了其临接边,但所有的边只会遍历一次。因此对边的遍历的总操作的复杂度为 O ( E ) O(E) O(E),因此广度优先搜索的复杂度 O ( V + E ) O(V+E) O(V+E)

最短路径证明

为了证明方便,先定义s到v的最短距离为 δ ( s , v ) \delta(s,v) δ(s,v)时s到v的所有路径中最少的边数,相应的路径称为最短路径。对于最短路径 δ ( s , v ) \delta(s,v) δ(s,v)有一个重要的性质:给定 G = ( V , E ) G=(V,E) G=(V,E),对于任意的边 ( u , v ) ∈ E (u,v)\in E (u,v)E,有 δ ( s , v ) ≤ δ ( s , u ) + 1 \delta(s,v) \le \delta(s,u)+1 δ(s,v)δ(s,u)+1。该性质还是比较直观的:如果 δ ( s , v ) > δ ( s , u ) + 1 \delta(s,v) \gt \delta(s,u)+1 δ(s,v)>δ(s,u)+1,那么s到v的路径完全可以选择先到 u u u,再到 v v v得到一个更小值,这与 δ ( s , v ) \delta(s,v) δ(s,v)的定义矛盾。

我们将通过夹逼的方式,证明算法运行结束后, v . d = δ ( s , v ) v.d = \delta(s,v) v.d=δ(s,v),即先证明 v . d ≥ δ ( s , v ) v.d \ge \delta(s,v) v.dδ(s,v),再证明 v . d ≤ δ ( s , v ) v.d\le\delta(s,v) v.dδ(s,v)。此外,还将证明 s s s v v v的一条最短路径为 s s s v . π v.\pi v.π的最短路径加上边 ( v . p i , v ) (v.pi, v) (v.pi,v),这个结论对恢复 s s s v v v最短路径很重要。

  • 定理1:算法结束后, v . d ≥ δ ( s , v ) v.d\ge \delta(s,v) v.dδ(s,v)
    证明:使用数学归纳法证明。先证明基本状态成立:算法开始时, s . d = 0 = v . d = δ ( s , s ) s.d=0=v.d = \delta(s,s) s.d=0=v.d=δ(s,s),而对于其他节点, v . d = I n f v.d=Inf v.d=Inf,所以基本状态成立。考虑算法的14~18行
				v.color = gray
				v.d = u.d + 1
				v.Π = u
				que.push(v)

假设,此时 u . d u.d u.d此时满足 u . d ≥ δ ( s , u ) u.d\ge \delta(s,u) u.dδ(s,u),再根据最短路径的性质, δ ( s , v ) ≤ δ ( s , u ) + 1 \delta(s,v) \le \delta(s,u)+1 δ(s,v)δ(s,u)+1,可以得到,
v . d = u . d + 1 ≥ δ ( s , u ) + 1 ≥ δ ( s , v ) v.d = u.d+1 \ge \delta(s,u) + 1 \ge\delta(s,v) v.d=u.d+1δ(s,u)+1δ(s,v)
此时v被图上了灰色,不会被再次入队,因此 v . d v.d v.d不会再次改变,因此基本状态与归纳均证毕,原命题成立。

  • 定理2:对于算法运行中的队列中的节点 < v 1 , . . . , v r > <v_1, ...,v_r> <v1,...,vr>,有 v r . d ≤ v 1 . d + 1 v_r.d\le v_1.d+1 vr.dv1.d+1,且队列中的 v i . d v_i.d vi.d单调递增

    仍然使用数学归纳法。开始时,队列中只有 s s s,命题成立。
    v 1 v_1 v1从队列中删除时,对原命题没有影响,原命题依然成立。
    v r + 1 v_{r+1} vr+1入队时, v 0 v_0 v0刚从队列中移除。此时 v r + 1 . d v_{r+1}.d vr+1.d 被设置为 v 0 . d + 1 v_{0}.d+1 v0.d+1

    • 由于 v r . d ≤ v 0 . d + 1 v_r.d\le v_0.d + 1 vr.dv0.d+1(上一轮的假设),所以 v r . d ≤ v r + 1 . d v_{r}.d\le v_{r+1}.d vr.dvr+1.d,单调性成立。
    • 因为 v 0 . d + 1 ≤ v 1 . d + 1 v_0.d +1 \le v_1.d +1 v0.d+1v1.d+1 (上一轮的单调性假设),因此 v r + 1 . d ≤ v 1 . d + 1 v_{r+1}.d \le v_1.d +1 vr+1.dv1.d+1。因此基本状态和归纳均成立,命题得证。
  • 推论2.1:算法运行中,当 v i v_i vi v j v_j vj之前入队时,必有 v i . d ≤ v r . d v_i.d\le v_r.d vi.dvr.d,d 随着算法的运行单调递增的。

    定理2已保证了这一点

  • 定理3: v . d = δ ( s , v ) v.d = \delta(s,v) v.d=δ(s,v),并且v的最短路径为 v . π v.\pi v.π的最短路径加边 < v . π , v > <v.\pi, v> <v.π,v>

    使用反证法:假设算法结束后,有一些 v . d v.d v.d 不满足 v . d ≠ δ ( s , v ) v.d \neq \delta(s,v) v.d=δ(s,v)。我们精心挑选一个 v v v,他是所有 v . d ≠ δ ( s , v ) v.d \neq \delta(s,v) v.d=δ(s,v)的节点中, δ ( s , v ) \delta(s,v) δ(s,v)最小的一个。根据定理1,可知 v . d > δ ( s , v ) v.d > \delta(s,v) v.d>δ(s,v)。假设节点 u u u s s s v v v的最短路径上, v v v的直接前驱节点。因此 δ ( s , v ) = δ ( s , u ) + 1 \delta(s,v)= \delta(s,u) + 1 δ(s,v)=δ(s,u)+1,即 δ ( s , u ) < δ ( s , v ) \delta(s,u) \lt \delta(s,v) δ(s,u)<δ(s,v)。 因为 v v v v . d ≠ δ ( s , u ) v.d\neq \delta(s,u) v.d=δ(s,u)的最小节点,因此 u . d = δ ( s , u ) u.d = \delta(s,u) u.d=δ(s,u)。于是有不等式
    v . d > δ ( s , v ) = δ ( s , u ) + 1 = u . d + 1 v.d\gt \delta(s,v) = \delta(s,u) + 1 = u.d + 1 v.d>δ(s,v)=δ(s,u)+1=u.d+1
    考虑 u u u 从队列 Q Q Q中取出的时间。此时 v v v 可以是任何颜色。

    • 如果 v v v是白色,那么本轮循环会将v.d设置为u.d + 1,与 v . d > δ ( s , v ) = δ ( s , u ) + 1 v.d\gt \delta(s,v) = \delta(s,u) + 1 v.d>δ(s,v)=δ(s,u)+1矛盾。
    • 如果 v v v是灰色,那么 v v v此时在队列中,根据定理2, v . d ≤ u . d + 1 v.d \le u.d +1 v.du.d+1,依然与上式矛盾
    • 如果 v v v是黑色,那么 v v v此时已经不在队列中,根据推论2.1, v . d ≤ u . d v.d \le u.d v.du.d,仍然矛盾。

    因此算法结束后 v . d = δ ( s , v ) v.d= \delta(s,v) v.d=δ(s,v)。根据算法伪代码,如果 v . π = u v.\pi=u v.π=u,则必有 v . d = u . d + 1 v.d = u.d + 1 v.d=u.d+1,即 δ ( s , v ) = δ ( s , u ) + 1 \delta(s,v)= \delta(s,u) + 1 δ(s,v)=δ(s,u)+1,因此, v v v的最短路径为 u u u的最短路径加边 < v . π , v > <v.\pi, v> <v.π,v>,证毕。

广度优先树

根据广度优先搜索算法的性质,算法结束后,可以通过每个节点的 v . π v.\pi v.π属性来恢复最短路径。事实上使用 v . π v.\pi v.π属性为边,加上其关联的节点,可以形成一个树形结构。称之为:广度优先树 G . π G.\pi G.π文章来源地址https://www.toymoban.com/news/detail-510478.html

到了这里,关于【算法证明 六】深入理解广度优先搜索的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python 算法基础篇:深度优先搜索( DFS )和广度优先搜索( BFS )

    深度优先搜索( DFS )和广度优先搜索( BFS )是两种常用的图遍历算法,用于在图中搜索目标节点或遍历图的所有节点。本篇博客将介绍 DFS 和 BFS 算法的基本概念,并通过实例代码演示它们的应用。 😃😄 ❤️ ❤️ ❤️ 深度优先搜索( DFS )是一种用于遍历或搜索图或树

    2024年02月07日
    浏览(52)
  • 深度优先搜索(DFS)和广度优先搜索(BFS)两种算法c++

    深度优先搜索(DFS)和广度优先搜索(BFS)是一种用于遍历或搜索树图的一种算法,在这个过程中保证图或数的每个结点被访问且仅被访问一次,再按照每个结点访问的顺序不同分为深搜和广搜。 本文只讨论这两种算法在搜索方面的应用! 深度优先搜索 ( Depth-First-Search,DFS )它 沿

    2024年02月13日
    浏览(33)
  • 数据结构学习笔记——图的遍历算法(深度优先搜索和广度优先搜索)

    图的遍历指从图中某一顶点出发(任意一个顶点都可以作为访问的起始顶点),按照某种遍历方法,对图中所有的顶点访问一次且只访问一次。图与树不一样,其中一个顶点可能与多个顶点相连,所以需记录已访问过的顶点,当访问一个顶点后,考虑如何选取下一个要访问的

    2024年02月05日
    浏览(39)
  • 图的遍历(搜索)算法(深度优先算法DFS和广度优先算法BFS)

    从图的某个顶点出发访问遍图中所有顶点,且每个顶点仅被访问一次。(连通图与非连通图) 1、访问指定的起始顶点; 2、若当前访问的顶点的邻接顶点有未被访问的,则任选一个访问之;反之,退回到最近访问过的顶点;直到与起始顶点相通的全部顶点都访问完毕; 3、若

    2024年01月17日
    浏览(36)
  • Python 图算法,图最短路径,图广度优先搜索,图深度优先搜索,图排序

    一、图数据库相关算法 图数据库是一种专门用来存储和处理图数据的数据库系统。它使用图结构来表示数据之间的关联关系,以及节点和边之间的属性信息。以下是一些常用的图数据库算法: 1. 最短路径算法:最短路径算法用于计算图中两个节点之间的最短路径,例如Dijk

    2024年02月15日
    浏览(21)
  • 【Python搜索算法】广度优先搜索(BFS)算法原理详解与应用,示例+代码

    目录 1 广度优先搜索     2 应用示例 2.1 迷宫路径搜索 2.2 社交网络中的关系度排序 2.3 查找连通区域         广度优先搜索(Breadth-First Search,BFS)是一种图遍历算法,用于系统地遍历或搜索图(或树)中的所有节点。BFS的核心思想是从起始节点开始,首先访问其所有相

    2024年02月08日
    浏览(37)
  • 图论算法|深度优先搜索理论基础|797.所有可能的路径|广度优先搜索BFS理论基础|200. 岛屿数量

    dfs是可一个方向去搜,不到黄河不回头,直到遇到绝境了,搜不下去了,在换方向(换方向的过程就涉及到了回溯)。 递归和回溯是相辅相成的 https://leetcode.cn/problems/all-paths-from-source-to-target/ 有向无环图(DAG): 有环无向图是指在图中存在至少一个环(Cycle)的无向图。环是

    2024年02月15日
    浏览(45)
  • 数据结构与算法基础-学习-24-图的遍历之DFS(深度优先搜索)和BFS(广度优先搜索)

    目录 一、遍历定义 二、遍历实质 三、DFS 四、BFS 五、宏定义 六、自定义类型 七、函数实现 1、DFS(邻接矩阵实现) 2、DFS(邻接表实现) 3、BFS(邻接矩阵实现) 4、BFS(邻接表实现) 5、打印邻接矩阵遍历顺序  6、打印邻接表遍历顺序 八、遍历算法效率分析 1、DFS 2、BFS 九

    2024年02月03日
    浏览(59)
  • 广度优先搜索(BFS)算法求解单源最短路径问题

      单源最短路径问题是图论中一类重要且常见的应用问题。在这个问题中,我们需要找到从一个给定源节点到其他节点的最短路径。广度优先搜索(BFS)算法是一种常用且有效的求解这一问题的算法。   本篇博客将重点讨论单源最短路径问题及其实际应用,同时简要介绍

    2024年02月13日
    浏览(33)
  • 【数据结构与算法】图的搜索——广度优先遍历、最小生成树

    邻接链表: 用字典实现.有向图的邻接链表的总长度等于图的边个数;无向图的邻接链表的总长度等于图的边个数的2倍. 邻接矩阵:用于最短路径算法. 该数据结构维护一个不相交动态集的集合,每个集合有一个代表,不关心谁做代表。 支持三种操作: MAKE_SET(x) FIND_SET(x) UNION(x,y

    2024年02月19日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包