首页 > 其他分享 >不读概念,用过程轻松理解并实现拓扑排序

不读概念,用过程轻松理解并实现拓扑排序

时间:2024-03-30 20:59:11浏览次数:16  
标签:int 拓扑 入度 轻松 ints 顶点 排序

目录

1. 有向无环图

2. AOV网:顶点活动图

3. 拓扑排序

4. 实现拓扑排序

5. 力扣OJ


1. 有向无环图

顾名思义,边有向,图中没有回路。这里只需要知道各顶点的入度和出度怎么计算即可。

2. AOV网:顶点活动图

在有向无环图中,用顶点来表示一个活动,用边来表示活动的先后顺序的图结构。

拓扑排序与 AOV 网络之间存在密切的关系,因为 AOV 网络通常用于描述项目中的活动之间的依赖关系,而拓扑排序则可以用来确定这些活动的执行顺序。

3. 拓扑排序

概念:抽象,略。

找到做事情的先后顺序,拓扑排序的结果可能不是唯一的.

模拟一遍拓扑排序就明白了:

在这个有向无环图中,统计了各个顶点的入度和出度。

拓扑排序是找到做事情的先后顺序,也就是说,在做1这件事之前,我必须先把0这件事做完了才行。而入度为0的顶点就是拓朴排序的起点,如果有多个入度为0的顶点,拓扑排序的结果就不一样了。

因此,拓扑排序分为以下几个步骤:

  1. 找出入度为0的点,然后输出。
  2. 删除与该点连接的边,即这些边指向的顶点的入度-1。
  3. 重复1,2操作,直到图中没有点或者没有入度为0的点为止。

重要应用,判断有向图中是否有环。

例如:

该图中右侧三个顶点(3,4,5)构成了环。根据上面步骤进行拓扑排序,发现当1,2顶点依次处理完后,剩下顶点之间的关系是这样的:

此时,图中没有入度为1的顶点了,而已处理的顶点数未达到图中顶点的个数,因此就可以判断出该图是有环的。

4. 实现拓扑排序

借助队列,来一次BFS即可。

1.初始化:把所有入度为0的顶点加入到队列中。

2.当队列不为空时:

        (1)拿出队头元素,加入到最终结果中。

        (2)删除与该元素相连的边。

        (3)判断:删除边指向的顶点,此时入度是否为0,如果为0,加入到队列中。

5. 力扣OJ

207. 课程表

不看题目的示例,直接看前面那个图:

根据题目要求,它让我们判断是否可能完成所有课程的学习,其实就是看我们在拓扑排序的过程中能否处理完所有顶点,也就是判断这个有向图中是否有环。对此,我们首要任务其实是建图。

二维数组中每个元素 prerequisites[i]就表示prerequisites[1]指向prerequisites[0],即通过给出的prerequisites数组要转换成图示中的图,实现图有两种方式,这里我们使用邻接表实现(稀疏图)。对于建图,我们要灵活使用语言提供的容器。

模拟一个邻接表也有两种方式:

  1. List<List<Integer>>:本题中,课程映射成了数字(整型)的形式,因此我们可以用一个大的List表示图中的顶点数,小的List存储这个顶点的邻接顶点。
  2. Map<Integer, List<Integer>>:这种方式同样可以创建邻接表,但它的通用性更强。原因就是当课程是以字符串的形式表示的,如数学,语文,英语等,此时我们如果用第一种方式建表就需要先把课程和数字(整型)的对应关系确定下来。而第二种方式直接将泛型更改为String类型,即Map<String, List<String>>即可直接建表。

除建表外,还需要一个入度表,用于后续BFS的过程中将入度变为0的顶点入队。结合上述拓扑排序的实现步骤,代码实现如下(具体步骤看注释):

class Solution {
    public boolean canFinish(int n, int[][] p) {
        //1.准备工作,建图
        Map<Integer, List<Integer>> edges = new HashMap<>();
        int[] in = new int[n]; //入度表
        //遍历二维数组
        for (int[] ints : p) {
            //以p[1]为键,p[0]为值的元素建表
            if (!edges.containsKey(ints[1])) {
                edges.put(ints[1], new ArrayList<>());
            }
            edges.get(ints[1]).add(ints[0]);
            in[ints[0]]++; //p[0]的入度加1
        }
        //2.进行拓扑排序
        //2.1 遍历入度表,将所有入度为0的顶点入队
        Queue<Integer> queue = new LinkedList<>();
        for(int i = 0; i < n; i++) {
            if(in[i] == 0) {
                queue.offer(i);
            }
        }
        //2.2 bfs
        int count = 0;//记录能够完成几门课程
        while(!queue.isEmpty()) {
            int edge = queue.poll();
            count++;
            //遍历该顶点的邻接顶点(先要保证该顶点有邻接顶点),将它们的入度-1
            if (edges.containsKey(edge)) {
                for (int inIdx : edges.get(edge)) {
                    in[inIdx]--;
                    if (in[inIdx] == 0) {
                        queue.offer(inIdx);
                    }
                }
            }
        }
        //或者判断入度表是否有不为0的顶点,有则返回false,否则为true
        return count == n;
    }
}

接下来可尝试解决另外两道题:

210. 课程表 II

LCR 114. 火星词典

标签:int,拓扑,入度,轻松,ints,顶点,排序
From: https://blog.csdn.net/sjsjzhx/article/details/137158461

相关文章

  • sort函数对vector一维或者二维数组排序
    目录sort对一维数组排序1、sort对一位数组升序排序2、sort对一维数组降序排序sort对二维数组排序1、sort默认对横坐标进行升序排序,如下:2、使用自定义排序对纵坐标进行升序排序:额外知识:对横坐标进行降序排列,当横坐标相同时,对纵坐标进行升序排序sort对一维数组排序......
  • 动画图解:九大经典排序算法详解-算法宝App
    重新整理了一遍排序算法,结合自己开发的算法宝App的录屏,转成webp动画一起分享给大家,适合新手。概述时间复杂度(timecomplexity)用来描述算法的运行时间。常用大O符号表述。比如:O(n),O(1),O(logn),O(n2)等。举例:O(n)表示线性级复杂度,表示时间复杂度和元素element数量n成正比。......
  • AI写作智能免费一键生成:让写作变简单,输入标题,轻松装作
    首先,这篇文章是基于笔尖AI写作进行文章创作的,喜欢的宝子,也可以去体验下,解放双手,上班直接摸鱼~按照惯例,先介绍下这款笔尖AI写作,宝子也可以直接下滑跳过看正文~笔尖Ai写作面向写作领域的全能型Ai写作工具笔尖Ai写作助手包括:Ai论文、Ai开题报告、Ai公文写作、Ai商业计划书、文......
  • 数据结构:归并排序
    归并排序时间复杂度O(N*logN)如果两个序列有序,通过归并,可以让两个序列合并后也有序,变成一个有序的新数组对于一个数组,如果他的左右区间都有序,就可以进行归并了归并的方法将数组的左右两个有序区间比较,每次都取出一个最小的,然后放入临时数组(不能在原数组上修改,因......
  • 虾皮订单怎么采购商品?几步教你轻松搞定!
    在跨境电商领域,虾皮平台以其广泛的商品种类和庞大的用户群体,成为了许多卖家的首选。然而,面对大量的订单和多样的商品需求,如何高效地进行商品采购成为了卖家们必须面对的问题。虎观采购将详细介绍虾皮订单商品采购的步骤,并重点介绍虎观采购插件如何助力卖家实现高效采购。一、......
  • 排序算法 - 堆排序
    文章目录目录文章目录前言1.堆排序原理2.堆排序实现 总结前言大家好,今天给大家介绍一下常见排序算法中的堆排序(填坑)1.堆排序原理堆排序是一种基于二叉堆数据结构的排序算法,它利用堆的性质进行排序。堆是一种完全二叉树,分为最大堆和最小堆两种类型。在......
  • 文件名按数字排序,可以排序多组数字,尤其是99-333~~_222这种复杂数字组合的文件名或字符
    这是我本人编写的一个排序算法,主要就是解决复杂多组数字组合的这种文件名或者字符串的排序,排序主要规则就是从前往后对每一组数据进行排序,效果及截图如下:以下是使用方法:第一步搜索和安装我的Nuget包搜索和安装zmjtool这个包,我写的,如下图:第二步使用HMSorter的Sort方法进行......
  • 选择排序(java)
    选择排序,从头至尾扫描序列,找出最小的一个元素,和第一个元素交换,接着从剩下的元素中继续这种选择和交换方式,最终得到一个有序序列解题思路:选择排序的基本思路是遍历整个数组,每次找到剩余部分中的最小值,然后将其与当前位置进行交换。这样每一次遍历都能确定一个元素的最终位置,......
  • 带流量主功能的外卖菜谱小程序源码:助你轻松领取优惠券,个人使用也可通过审查
    外卖菜谱小程序源码-带流量主功能-外卖领劵个人也可过审这套小程序优点就带很多菜谱,各种你爱吃菜的做法与各类食材介绍营养搭配,相信很多小姐姐会感兴趣。宝妈宝爸这个小程序肯定能留的住这个群体的人脉流量,这是小程序最大的亮点;其它功能也没有什么对接外卖劵加个流量主。源......
  • pipeline拓扑裁剪规则
    1.1概述在一些usecase中,会有多个使用场景。根据不同的场景,需要构建不同的pipeline拓扑。例如,高通SATusecase有多个场景:EIS-Disable,EISv3等等对于这种情况有两种解决方案:1、第一个是为这类用例设计不同的pipeline,以适应其不同的usecase。然后,在场景变化时切换到相应的pipel......