算法复习——图算法篇之拓扑排序

算法复习——图算法篇之拓扑排序

以下内容主要参考中国大学MOOC《算法设计与分析》,墙裂推荐希望入门算法的童鞋学习!

1. 问题背景

​ 举一个生活中的实例,穿衣服是有顺序,比如肯定是先穿袜子,再穿鞋,不可能是先穿鞋,再穿袜子。

在这里插入图片描述

​ 如上图所示,对于这类问题,我们可以用有向无环图里来表示事件发生的先后顺序,其中,有向规定了先后顺序,无环则避免了相互依赖。那么,问题就是比如在穿衣的这个生活场景中,如何确定一个可行的穿衣顺序呢?

​ 我们可以给出以下的方案:

在这里插入图片描述

​ 它要求有向图任意边的起点排在终点前面。

2. 问题定义

拓扑排序(Topological Sort)

输入:

  • 有向无环图 G = < V , E > G=<V, E> G=<V,E>

输出:

  • 图顶点 V V V的拓扑序 S S S,满足:对任意有向边 ( u , v ) (u, v) (u,v),排序后 u u u v v v之前

​ 显然,拓扑序是不唯一的,满足条件即可。

3. 广度优先策略

3.1 算法思想

  • 有向图顶点的度分为入度和出度
    • 顶点 u u u的入度:终点为 u u u的边数
    • 顶点 v v v的出度:起点为 u u u的边数
  • 若顶点入度为0,所对应事件无制约,可直接完成
  • 完成入度为0对应的事件
  • 删除完成事件,产生新的入度为0点,继续完成

3.2 伪代码

输入:图G

输出:顶点拓扑序

初始化空队列q
for v ∈ V do
	if v.in_degree = 0 then
		Q.Enqueue(v)
	end
end
while not Q.is_empty() do
	u ← Q.Dequeue()
	print u
	for v ∈ G.Adj(u) do
		v.in_degree ← v.in_degree - 1
		if v.in_degree = 0 then
			Q.Enqueue(v)
		end
	end
end

​ 该算法的时间复杂度是 O ( ∣ V ∣ + ∣ E ∣ ) O(|V|+|E|) O(V+E)

4. 深度优先策略

4.1 算法思想

  • 从DFS的视角观察

    • 穿衣顺序和搜索深度有关:深度越深,顺序越靠后

    • 深度越深

      • 发现时刻越晚
      • 完成时刻越早
    • 那么,我们是按照发现时刻顺序还是按照完成时刻逆序来生成拓扑序呢?

    • 我们可以看下方的实例。假设从袜子出发,下一个点是鞋子,然后就走完了一棵深度优先树。袜子的发现时刻和完成时刻是1和4,鞋的发现时刻和完成时刻是2和3。接着,如果下一个访问的是短裤,则短裤的发现时刻是5,这时,就出问题了。若按发现时刻顺序执行,会先穿鞋后穿短裤,拓扑序错误。

    在这里插入图片描述

    • 继续走完该实例,会发现按照完成时刻逆序执行,没有出问题,那我们需要证明算法的正确性。

4.2 正确性证明

  • 已知深度优先搜索确定的顺序:顶点完成时刻的逆序
  • 已知拓扑序:对任意边 ( u , v ) (u, v) (u,v) u u u v v v前面
  • 需证明对任意边 ( u , v ) (u, v) (u,v),完成时刻满足: f ( u ) > f ( v ) f(u)>f(v) f(u)>f(v)
    • 证明:设当前顶点为 u u u,搜索顶点 v v v
      • v v v为白色, v v v u u u的后代, f ( u ) > f ( v ) f(u)>f(v) f(u)>f(v)(括号化定理)
      • v v v为黑色, v v v已经完成, u u u尚未完成, f ( u ) > f ( v ) f(u)>f(v) f(u)>f(v)
      • v v v不可能是灰色,因为给定的图是有向无环图,不存在后向边,若当前顶点为 u u u,但搜索到了灰色的 v v v,那只能说明 v v v发现得比 u u u发现得还早,也就存在 v v v u u u的反向边,成环了。

4.3 伪代码

Topological-Sort-DFS(G)

输入:图G​

输出:顶点拓扑序

L ← DFS(G)
return L.reverse()

DFS(G)

输入:图G

新建数组color[1..V],L[1..V]
for v ∈ V do
	color[v] ← WHITE
end
for v ∈ V do
	if color[v] = WHITE then
		L' ← DFS-Visit(G, v)
		向L结尾追加L'
	end
end
return L

DFS-Visit(G, v)

输入:图G,顶点v

输出:按完成时刻从早到晚排列的顶点L

color[v] ← GRAY
for w ∈ G.Adj[v] do
	if color[w] = WHITE then
		L ← DFS-Visit(G, w)
	end
end
color[v] ← BLACK
向L结尾追加顶点v
return L

​ 该算法的时间复杂度是 O ( ∣ V ∣ + ∣ E ∣ ) O(|V|+|E|) O(V+E)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值