返回顶部
首页 > 资讯 > 后端开发 > Python >Java实现拓扑排序的示例代码
  • 925
分享到

Java实现拓扑排序的示例代码

2024-04-02 19:04:59 925人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录铺垫简介工作过程数据结构拓扑排序测试样例1测试样例2总结铺垫 有向图:我们这节要讲的算法涉及到有向图,所以我先把有向图的一些概念说一下,文章后面就不做解释啦。首先有向图节点与节点

铺垫

有向图:我们这节要讲的算法涉及到有向图,所以我先把有向图的一些概念说一下,文章后面就不做解释啦。首先有向图节点与节点之间是用带箭头的线连接起来的。节点有出度和入度的概念,连线尾部指向的节点出度加1,连线头部,也就是箭头指向的节点入度加1。看下面这个例子,A的入度为0,出度为2,B的入度为1,出度为1,C的入度为1,出度为1,D的入度为2,出度为0。

图片

邻接表:邻接表是存储图结构的一种有效方式,如下图所示,左边节点数组存储图中所有节点,右侧邻接表存储节点的相邻节点。

图片

简介

这篇文章我们要讲的是拓扑排序,这是一个针对有向无环图的算法,主要是为了解决前驱后继的关系,即我们在完成当前事项的时候需要先完成什么事项,其实这在我们流程控制里面用的挺多的。看下面这个图,我们需要先完成A事项,然后才能去完成B,C事项,B,C事项的属于并列的,没有先后顺序,但是对于D事项需要在B,C事项完成之后才能进行。而拓扑排序能够帮助我们找到这个完成事项的合理顺序,同时我们看上面这个例子,A事项完成之后,B,C事项是没有先后顺序的,不管是先完成B还是C都符合条件,所以拓扑排序的顺序序列不是完全一定的。

工作过程

首先拓扑排序对应操作的是一个有向无环图。无环图,则肯定存在至少一个结点入度为0。在当前情况下,我们需要查找入度为0的节点进行操作,入度为0,表示当前节点没有前驱节点,或者前驱节点已经处理,可以直接操作。操作完毕之后,将当前节点的后继节点入度全部减1,再次查找入度节点为0的节点进行操作,此后就是一个递归过程,不断处理当前情况下入度为0的节点,直至所有节点处理完毕。

图片

数据结构

有向图结构如下,其中node存储当前图中包含的所有节点,adj存储对应下标节点的邻接点。初始化图时候,我们需要初始化图中节点个数,存储节点的数组以及节点对应邻接数组。同时提供一个addEdge方法,用于在两个节点直接加边,其实就是将后继节点放入前驱节点的邻接表中。

public static class Graph{
       
       private Integer nodeSize;
       
       private char[] node;
       
       private LinkedList[] adj;

       public Graph(char[] node) {
           this.nodeSize = node.length;
           this.node = node;
           this.adj = new LinkedList[nodeSize];
           for (int i = 0 ; i < adj.length ; i++) {
               adj[i] = new LinkedList();
          }
      }
       
       public void addEdge(int front, int end) {
           adj[front].add(end);
      }
  }

拓扑排序

拓扑排序首先初始化了两个临时数组,一个队列,一个inDegree数组存储对应下标节点的入度,因为每次访问的节点需要前驱节点已经完成,即入度为0,有了这个数组我们就可以比较快速的找到这些节点;另一个是visited数组,标志当前节点是否已经访问过,防止多次访问;一个nodes队列则保存在目前情况下所有入度为0的节点。(注意,为了存取方便,我们都是存储的节点下标 step1:初始化inDegree数组,visited数组; step2:遍历inDegree数组,将所有入度为0的节点入nodes队列; step3:依次将节点node出队; 根据visited判断当前node是否已经被访问,是,返回step3,否,进行下一步; 将当前节点的邻接节点入度-1,判断邻接节点入度是否为0,为0直接放入nodes队列,不为0返回step3;


   public List<Character> toPoLogicalSort(Graph graph) {
       //用一个数组标志所有节点入度
       int[] inDegree = new int[graph.nodeSize];
       for (LinkedList list : graph.adj) {
           for (Object index : list) {
               ++ inDegree[(int)index];
          }
      }
       //用一个数组标志所有节点是否已经被访问
       boolean[] visited = new boolean[graph.nodeSize];
       //开始进行遍历
       Deque<Integer> nodes = new LinkedList<>();
       //将入度为0节点入队
       for (int i = 0 ; i < graph.nodeSize; i++) {
           if (inDegree[i] == 0) {
               nodes.offer(i);
          }
      }
       List<Character> result = new ArrayList<>();
       //将入度为0节点一次出队处理
       while (!nodes.isEmpty()) {
           int node = nodes.poll();
           if (visited[node]) {
               continue;
          }
           visited[node] = true;
           result.add(graph.node[node]);
           //将当前node的邻接节点入度-1;
           for (Object list : graph.adj[node]) {
               -- inDegree[(int)list];
               if (inDegree[(int)list] == 0) {
                   //前驱节点全部访问完毕,入度为0
                   nodes.offer((int) list);
              }
          }
      }
       return result;
  }

测试样例1

public static void main(String[] args) {
       ToPoLogicalSort toPoLogicalSort = new ToPoLogicalSort();
       //初始化一个图
       Graph graph = new Graph(new char[]{'A', 'B', 'C', 'D'});
       graph.addEdge(0, 1);
       graph.addEdge(0,2);
       graph.addEdge(1,3);
       graph.addEdge(2,3);
       List<Character> result = toPoLogicalSort.toPoLogicalSort(graph);
  }

执行结果

图片

测试样例2

public static void main(String[] args) {
       ToPoLogicalSort toPoLogicalSort = new ToPoLogicalSort();
       //初始化一个图
       Graph graph = new Graph(new char[]{'A', 'B', 'C', 'D','E','F','G','H'});
       graph.addEdge(0, 1);
       graph.addEdge(0,2);
       graph.addEdge(0,3);
       graph.addEdge(1,4);
       graph.addEdge(2,4);
       graph.addEdge(3,4);
       graph.addEdge(4,7);
       graph.addEdge(4,6);
       graph.addEdge(7,5);
       graph.addEdge(6,7);
       List<Character> result = toPoLogicalSort.toPoLogicalSort(graph);
  }

执行结果

图片

总结

我在上面有说到,拓扑排序可以用来判断图是否存在环,其实判断方式很简单,实现步骤与上面一致,只是我们最后判断一下出队的元素个数是否等于图的节点个数,如果等于,证明图无环,如果不等于则证明存在环。

到此这篇关于Java实现拓扑排序的示例代码的文章就介绍到这了,更多相关Java拓扑排序内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Java实现拓扑排序的示例代码

本文链接: https://lsjlt.com/news/148898.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java实现拓扑排序的示例代码
    目录铺垫简介工作过程数据结构拓扑排序测试样例1测试样例2总结铺垫 有向图:我们这节要讲的算法涉及到有向图,所以我先把有向图的一些概念说一下,文章后面就不做解释啦。首先有向图节点与节点...
    99+
    2024-04-02
  • Java实现拓扑排序算法的示例代码
    目录拓扑排序原理1.点睛2.拓扑排序3.算法步骤4.图解拓扑排序算法实现1.拓扑图2.实现代码3.测试拓扑排序原理 1.点睛 一个无环的有向图被称为有向无环图。有向无环图是描述一个工...
    99+
    2024-04-02
  • Java如何实现拓扑排序
    今天小编给大家分享一下Java如何实现拓扑排序的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。铺垫有向图:我们这节要讲的算法涉...
    99+
    2023-06-30
  • 详解Java实现拓扑排序算法
    目录一、介绍二、拓扑排序算法分析三、拓扑排序代码实现一、介绍 百科上这么定义的: 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中...
    99+
    2024-04-02
  • 拓扑排序Python实现的过程
    目录有向无环图拓扑排序算法步骤代码实现总结有向无环图 拓扑排序是针对有向无环图(DAG, Directed Acyclic Graph)的 具有以下性质: 如果这个图不是 DAG,那...
    99+
    2023-01-31
    拓扑排序Python 拓扑排序 Python拓扑排序
  • 详解C++实现拓扑排序算法
    目录一、拓扑排序的介绍二、拓扑排序的实现步骤三、拓扑排序示例手动实现四、拓扑排序的代码实现五、完整的代码和输出展示一、拓扑排序的介绍 拓扑排序对应施工的流程图具有特别重要的作用,它可...
    99+
    2024-04-02
  • Java实现归并排序的示例代码
    目录1.算法理解2.实现代码3.实现效果1.算法理解 参考:图解Java中归并排序算法的原理与实现 2.实现代码 import java.lang.reflect.Array; im...
    99+
    2024-04-02
  • Java实现快速排序和堆排序的示例代码
    目录快速排序算法步骤动图演示JavaScript代码实现python代码实现Go代码实现C++代码实现Java代码实现堆排序算法步骤动图演示JavaScript代码实现Python代...
    99+
    2022-12-22
    Java快速排序 Java 堆排序 Java排序
  • Java实现扑克牌游戏的示例代码
    目录一、三人扑克二、具体实现Card类生成52张牌打乱顺序发牌三、完整代码一、三人扑克 想不想带上好朋友来上一局三人扑克呢。 二、具体实现 Card类 定义一个花色color变量和...
    99+
    2024-04-02
  • Java使用ArrayList实现扑克牌的示例代码
    目录前言一、项目要求二、具体实现2.1 Card类2.2 生成扑克牌2.3 打乱顺序2.4 发牌三、Test.java前言 学习了关于集合类的知识,我们可以做一个小项目来加深对集合类...
    99+
    2024-04-02
  • java实现的各种排序算法代码示例
    折半插入排序折半插入排序是对直接插入排序的简单改进。此处介绍的折半插入,其实就是通过不断地折半来快速确定第i个元素的插入位置,这实际上是一种查找算法:折半查找。Java的Arrays类里的binarySearch()方法,就是折半查找的实现...
    99+
    2023-05-31
    java 排序 算法
  • Java实现基本排序算法的示例代码
    目录1. 概述2. 插入排序2.1 直接插入排序2.2 希尔排序(缩小增量排序) 3. 选择排序3.1 直接选择排序3.2 堆排序4. 交换排序4.1 冒泡排序4.2 快速...
    99+
    2024-04-02
  • C++ 实现桶排序的示例代码
    目录原理实现步骤:模拟生成整数随机数桶排序实现完整版可运行程序时间复杂度计算桶排序:整数  原理 原理简述:按照需要排序数组的实际情况,生成一个一定长度的一维数组,用于统计...
    99+
    2024-04-02
  • c++实现堆排序的示例代码
    看了一下优先队列,查了一下堆排序。堆排序主要就是建最大堆(最小堆)和交换2个操作。如果建的是最大堆,那么交换的时候,父节点就和最大的子节点比较,如果它比最大的子节点还大,那就不用比了...
    99+
    2023-02-02
    c++ 堆排序
  • Java实现常见的排序算法的示例代码
    目录一、优化后的冒泡排序二、选择排序三、插入排序四、希尔排序五、快速排序六、随机化快速排序七、归并排序八、可处理负数的基数排序一、优化后的冒泡排序 package com.yzh.s...
    99+
    2022-11-13
    Java常见排序算法 Java排序算法 Java排序
  • C/C++浅析邻接表拓扑排序算法的实现
    目录前言一、拓扑排序算法的思路二、实现步骤1.求个顶点的入度2.拓扑排序的实现三、测试结果总结前言 在软件开发、施工过程、教学安排等等的一系列活动中,往往需要一个有向无环图来表示其是...
    99+
    2024-04-02
  • Java数据结构之有向图的拓扑排序详解
    目录前言拓扑排序介绍检测有向图中的环实现思路API设计代码实现基于深度优先的顶点排序实现思路API设计代码实现拓扑排序API设计代码实现测试验证前言 在现实生活中,我们经常会同一时间...
    99+
    2022-11-13
    Java有向图 拓扑排序 Java 有向图 Java 拓扑排序
  • Java编程实现直接插入排序代码示例
    算法描述:对于给定的一个数组,初始时假设第一个记录自成一个有序序列,其余记录为无序序列。接着从第二个记录开始,按照记录的大小依次将当前处理的记录插入到其之前的有序序列中,直至最后一个记录插入到有序序列中为止。直接插入排序Java实现教程示例...
    99+
    2023-05-30
    java 直接插入 排序
  • Python实现希尔排序,归并排序和桶排序的示例代码
    目录1. 前言2. 希尔排序2.1 前后切分2.2 增量切分3. 归并排序3.1 分解子问题3.2 求解子问题3.3 合并排序4. 基数排序5. 总结1. 前言 本文将介绍希尔排序、...
    99+
    2024-04-02
  • Java实现快速排序算法可视化的示例代码
    实现效果 示例代码 import java.awt.*; public class AlgoVisualizer { private static int DELA...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作