zoukankan      html  css  js  c++  java
  • 算法与数据结构基础

    拓扑排序基础

    拓扑排序用于解决有向无环图(DAG,Directed Acyclic Graph)按依赖关系排线性序列问题,直白地说解决这样的问题:有一组数据,其中一些数据依赖其他,问能否按依赖关系排序(被依赖的排在前面),或给出排序结果。

    最常用解决拓扑排序问题的方法是Kahn算法,步骤可以概括为:

    1. 根据依赖关系,构建邻接矩阵或邻接表、入度数组
    2. 取入度为0的数据(即不依赖其他数据的数据),根据邻接矩阵/邻接表依次减小依赖其的数据的入度
    3. 判断减小后是否有新的入度为0的数据,继续进行第2步
    4. 直到所有数据入度为0、得到拓扑排序序列,或返回失败(存在环形依赖)

    其中2、3两个步骤取入度为0数据、减小依赖其的数据的入度,过程像树的宽度优先搜索,用到类似BFS方法;以上过程用伪代码表示如下:

    L ← Empty list that will contain the sorted elements
    S ← Set of all nodes with no incoming edge
    while S is non-empty do
        remove a node n from S
        add n to tail of L
        for each node m with an edge e from n to m do
            remove edge e from the graph
            if m has no other incoming edges then
                insert m into S
    if graph has edges then
        return error   (graph has at least one cycle)
    else 
        return L   (a topologically sorted order)

    下面看具体例子 207. Course Schedule (有n个课程,课程间有依赖关系,问能否完成所有课程):

        //207. Course Schedule
        bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
    //构建邻接矩阵、入度数组 vector
    <vector<int>> adj(numCourses); vector<int> indegree(numCourses,0); for(auto x:prerequisites){ adj[x.second].push_back(x.first); indegree[x.first]++; }
    //类似BFS queue
    <int> q; for(int i=0;i<numCourses;i++) if(indegree[i]==0) q.push(i); while(!q.empty()){ int cur=q.front(); q.pop(); numCourses--; for(auto next:adj[cur]) if(--indegree[next]==0) q.push(next);//新入度为0的先处理,这与正统BFS有区别 }
    //判断最后所有数据入度为0
    return numCourses==0; }

    以上用到邻接矩阵(adjacency matrix)表示依赖关系,时间复杂度为O(V^2),其中V为数据个数。可视化过程:这里

    相关LeetCode题:

    207. Course Schedule  题解

    210. Course Schedule II  题解

    444. Sequence Reconstruction  题解

    269. Alien Dictionary  题解

     
     
     
  • 相关阅读:
    数据库悲观锁与乐观锁
    windows消息大全
    Ubuntu 16.04 LTS GNOME版本下载
    Spring MVC-表单(Form)处理示例(转载实践)
    Spring MVC-Hello World示例(转载实践)
    Spring MVC-环境设置(转载实践)
    MyBatis在注解上使用动态SQL(@select使用if)
    Ubuntu 16.04安装Ubuntu After Install工具实现常用软件批量安装
    Ubuntu 16.04开机自动挂载硬盘分区(转)
    Spring MVC-概述(转载实践)
  • 原文地址:https://www.cnblogs.com/bangerlee/p/10715342.html
Copyright © 2011-2022 走看看