图存储方式:
邻接表方式存储
class Node{
int visited = 0; // 是否被访问
int d = 0; // 初次遍历时间戳
int f = 0; // 最终遍历时间戳
LinkedList<Integer> linkNodes = null;
public Node(){
linkNodes = new LinkedList<>();
}
}
以上代码为一个节点的数据结构,最终用一个数组储存所有节点
求解: 深度优先算法
在使用dfs进行遍历时节点要记录两个索引,即以上代码中的 d 和 f。d 的值表示该节点第一次被遍历到时的时间戳,f 的值表示再次回溯到该节点的时间戳。该时间戳 f 与 d 共享,每遍历一个节点加一。
最终的拓扑排序以 f 的值降序排序。
java代码:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Scanner;
/**
* 求有向无环图的拓扑结构
*/
public class TopoLogical {
static int time = 0; //记录遍历次序
static ArrayList<Integer> topology; // 记录拓扑顺序的反序
static Node[] nodes;
public static void main(String[] args){
/**
* 输入方式:
* 第一行输入节点的个数n
* 后面n行输入第n个节点(从0开始数)链接的子节点,没有子节点则直接换行
*/
Scanner input = new Scanner(System.in);
int n = input.nextInt();
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();
if(!line.equals("")){
String[] tempIntStr = line.split(" ");
for(int j = 0; j < tempIntStr.length; ++j){
nodes[i].linkNodes.add(Integer.parseInt(tempIntStr[j]));
}
}
}
for(int i=0;i<nodes.length;i++){
dfs(nodes[i], i);
}
System.out.print("拓扑顺序: ");
for(int i=topology.size()-1;i>=0;i--){
System.out.print(topology.get(i) + " ");
}
}
static void dfs(Node node,int index){
if(node.visited==1 || node==null)
return;
time ++;
node.d = time;
node.visited = 1;
for(int i : node.linkNodes){
Node current = nodes[i];
if(current.visited == 0)
dfs(current, i);
}
topology.add(index);
time ++;
node.f = time;
}
}
class Node{
int visited = 0; // 是否被访问
int d = 0; // 遍历次序
int f = 0; // 最终遍历次序
LinkedList<Integer> linkNodes = null;
public Node(){
linkNodes = new LinkedList<>();
}
}