算法: 拓扑排序与后序遍历

作者: 写代码的海怪 | 来源:发表于2019-02-14 08:24 被阅读3次

简介

拓扑排序在我们生活中有很多的应用,最简单的就是任务的安排表,使用拓扑排序可以帮助你更容易分清哪个任务应该先做,哪个后做,以及它们之间的依赖关系。如下图有 5 个任务

凭我们肉眼很容易知道第 5 个任务先做,再后再做 3 ,以此类推下去,这就是拓扑排序。

定理

在图论里有这样一个定理,在有向图里只有两种情况出现:

  1. 要么有环的结构
  2. 要么存在拓扑排序

好像很废话是不是,定理其实都挺废话的,像什么两点间直线最短之类的,但是这些定理将是算法的基础,例如推理,证明的基础。

根据上面的这个定理我们可以知道,如果要求一个有向图的拓扑排序,返回结果就只有两种:有环抛出错误,或者返回拓扑排序结果。

DFS 求拓扑排序

我知道你们肯定都听说过先找入度为 0 的 BFS 方法,这里我就说一下用 DFS 来求拓扑排序的方法。

首先我们对这个算法的期望应该是如果有环就说有环抛出错误,如果可以拓扑排序那么就把排序打印出来,同时要说明每个节点的父节点是谁。

考虑如下图

对于这个图是可以拓扑排序的,顺序为 [s, a, x, b, z, c],节点的的父节点是:

当前节点 父节点
a a
b a
c b
z b
x a

这里再给出图的后序遍历的顺序 [c, z, b, x, a, s]。哎,这反转一下不就是拓扑排序的结果了么?没错,DFS 方法就是使用这个来得到拓扑排序的。下面给出思路。

  1. 首先因为我们处理的不是树,所以对每个节点都要做 DFS 搜索
  2. 在搜索每个节点时,先当前节点推到 Stack 中
    1. 如果发现要搜索的下一个节点在 Stack 里,那么说明有一条向上的路,这就有环了,抛出错误
    2. 否则就继续搜索下一个节点,同时设置当前节点为下一个节点的父节点
  3. 完成当前节点的搜索后就从 Stack 中弹出,将当前节点加入到 PostOrder 结果里
  4. 最后将 PostOrder 结果反转一下就是拓扑排序结果了

伪代码如下

const parents = {}
const postOrder = []
const stack = new Stack()

function dfs(vertex) {
    // 将当前节点推到 stack 中
    stack.push(vertex)
    // 找下一个节点
    for (let child in vertex.children) {
        if (stack.includes(child)) {
            // 有环,抛出错误
            throw new Error('有环')
        }
        if (!parents.includes(child)) {
            parents[child] = vertex
            dfs(child)
        }
    }

    postOrder.push(vertex)
    stack.remove(vertex)
}

function topOrder(graph) {
    // 每个节点都 DFS 一次
    for (let vertex in graph.vertices) {
        parents[vertex] = vertex
        dfs(vertex)
    }
}

相关文章

  • 算法: 拓扑排序与后序遍历

    简介 拓扑排序在我们生活中有很多的应用,最简单的就是任务的安排表,使用拓扑排序可以帮助你更容易分清哪个任务应该先做...

  • 强连通分量和Kosaraju算法

    内容概要: 基于深度优先后序遍历的DAG图拓扑排序 强连通分量 求解强连通分量Kosaraju算法 拓扑排序的另一...

  • 面试题

    面试题 二叉树 非递归实现二叉树遍历 节点: 前序遍历 中序遍历 后序遍历 排序 快速排序 其他问题 算法题 给一...

  • 阿里面试经历JAVA总结

    一面主要问题如下: 1)首先自我介绍 2)数据结构算法的基本问题,如排序算法,二叉树遍历,后序遍历非递归,图的最短...

  • 7.6图的应用:拓扑排序

    拓扑排序Topological Sort ❖从工作流程图得到工作次序排列的算法,称为“拓扑排序”❖拓扑排序处理一个...

  • 模板

    并查集 拓扑排序 Floyd算法 Dijkstra算法

  • LeetCode 第207题:课程表

    1、前言 2、思路 使用拓扑排序的方法,拓扑排序其实是使用的 BFS 算法,简而言之使用 BFS 算法解题。算法流...

  • 图算法(一)遍历,拓扑排序

    本文介绍图的几种基本操作:BFS,DFS,求有向图连通分量的Tarjan算法以及拓扑排序。 图的表示 一张图是由若...

  • 数据结构课程 第八周 遍历二叉树

    存储结构为二叉链表 遍历 先序遍历递归算法 中序遍历递归算法 后序遍历递归算法 总结 时间O(n) 空间(O(n)...

  • ALI 算法

    二叉树遍历算法: 按层遍历, 中序前序后序:

网友评论

    本文标题:算法: 拓扑排序与后序遍历

    本文链接:https://www.haomeiwen.com/subject/undwsqtx.html