使用深度优先搜索对有向无环图进行拓扑排序
来源:互联网 发布:淘宝怎么用erp转订单 编辑:程序博客网 时间:2024/06/05 07:51
拓扑排序是图G中所有节点的一种线性次序,该次序满足以下条件:如果图G包含边(u,v),则节点u在拓扑排序中处于节点v的前面。
在实际生活中有很多应用需要用有向无环图来指明事件的优先次序。下面以一个穿衣的例子来讲解拓扑排序:
在穿每一件衣服之间,要考虑是否要求先穿上某件衣服。拓扑排序可以解决这个问题,算法的主要思想如下:
通过深度优先搜索,记录每个节点的开始扫描的时间d和将其所有子节点全部扫描完的时间f,按照f从大到小的顺序,从左向右排列,得到的即为拓扑排序。在具体代码操作中,由于先扫描完成的节点总是f最小的,所以将每个扫描完的节点添加到数组中,再按照反序输出即可。
具体代码如下:
import java.util.ArrayList;import java.util.LinkedList;import java.util.Scanner;/** * * @author Founder * 作者原创,转载请注明出处 */public class Main{ static int time = 0; static ArrayList<Integer> topology; public static void main(String[] args){ /** * 输入方式: * 第一行输入节点的个数n * 后面n行输入第n个节点(从0开始数)链接的子节点,没有子节点则直接换行 */ Scanner input = new Scanner(System.in); int n = input.nextInt(); Node[] nodes = new Node[n]; topology = new ArrayList<>(); for(int i = 0; i < n; ++i){ nodes[i] = new Node(); } input.nextLine(); for(int i = 0; i < n; ++i){ String line = input.nextLine(); LinkedList<Integer> linkNodes = new LinkedList<>(); if(!line.equals("")){ String[] tempIntStr = line.split(" "); for(int j = 0; j < tempIntStr.length; ++j){ linkNodes.add(Integer.parseInt(tempIntStr[j])); } } nodes[i].setLinkNodes(linkNodes); } dfs(nodes); for(int i = topology.size() - 1; i >= 0; --i){ System.out.print(topology.get(i) + " "); } } public static void dfs(Node[] nodes){ for(int i = 0; i < nodes.length; ++i){ if(nodes[i].getColor() == Node.WHITE) dfsVisit(nodes,i); } } public static void dfsVisit(Node[] nodes,int no){ time++; nodes[no].setColor(Node.GRAY); nodes[no].setD(time); LinkedList<Integer> linkNodes = nodes[no].getLinkNodes(); for(int i = 0; i < linkNodes.size(); ++i){ Node temp = nodes[linkNodes.get(i)]; if(temp.getColor() == Node.WHITE){ temp.setParent(nodes[no]); dfsVisit(nodes,linkNodes.get(i)); } } nodes[no].setColor(Node.BLACK); topology.add(no); time++; nodes[no].setF(time); }}class Node{ public static final int WHITE = 0; public static final int GRAY = 1; public static final int BLACK = 2; private int color = WHITE; private int d = 0; private int f = 0; private Node parent = null; private LinkedList<Integer> linkNodes = null; public int getColor() { return color; } public void setColor(int color) { this.color = color; } public int getD() { return d; } public void setD(int d) { this.d = d; } public int getF() { return f; } public void setF(int f) { this.f = f; } public Node getParent() { return parent; } public void setParent(Node parent) { this.parent = parent; } public LinkedList<Integer> getLinkNodes() { return linkNodes; } public void setLinkNodes(LinkedList<Integer> linkNodes) { this.linkNodes = linkNodes; } @Override public String toString() { return "Node [d=" + d + ", f=" + f + "]"; }}
对于本例,输入如下:
9
1 7
2 7
5
2 4
5
(没有输入,直接换行)
7
(没有输入,直接换行)
(没有输入,直接换行)
输出:
8 6 3 4 0 1 7 2 5
即按照如下顺序进行:
符合题目要求。
基本原理理解:
深度优先搜索森林中,每个树里f最小的节点,没有子节点,因此放在该树的最右边,在回溯时,将其父节点放在左边,使每个树符合拓扑排序的要求;森林中不同树之间不干扰,因此不同树的放置顺序不影响拓扑排序,所以整个排序符合拓扑排序要求。
1 0
- 使用深度优先搜索对有向无环图进行拓扑排序
- 有向图(4)--基于深度优先的拓扑排序
- 深度优先搜索+拓扑排序
- 对输入的有向图进行拓扑排序
- Lintcode:拓扑排序(深度优先搜索,广度优先搜索)
- 深度优先搜索及拓扑排序(链式前向星实现)
- 有向图(2)--深度优先搜索&&广度优先搜索
- 数据结构上机实验--有向图邻接表的建立,深度广度搜索及拓扑排序
- 拓扑排序之关键路径(深度优先搜索)
- 深度优先搜索DFS(depth first search),拓扑排序
- 图的深度优先搜索及拓扑排序
- 图的拓扑排序,广度和深度优先搜索
- 【算法导论】有向图的深度优先搜索遍历
- 有向无环图的拓扑排序
- 有向无环图的拓扑排序
- 有向无环图的拓扑排序
- CSU 1804: 有向无环图 (拓扑排序)
- 有向无环图- CSU1804(拓扑排序)
- LCM分析及移植流程
- 使用Stanford CoreNLP工具包处理中文
- java读取文件读取工具类-将文件到byte数组的几种方式
- Java之获取表字段名
- Linux 常用命令
- 使用深度优先搜索对有向无环图进行拓扑排序
- 简单使用gitHub客户端
- 简单的数据发送给其他应用程序
- AFNetworking如何post一个json数据到服务器
- (六)IBM Sterling OMS 环境构建之WebsphereApplicationServer配置
- 判断状态为0显示文字,case when的用法
- andorid studio 主题字体更改
- 自定义View之开关按钮:SwitchButton
- jasperreport 文本太多,显示不全,解决办法