思路:拓扑排序,使用图(二维数组)来存储各个位置之间的大小关系,例如G[0][4],则说明arr[0]<arr[4],同理G[4][2],说明arr[4]<arr[2],这里可以看到,G实际决定了数组各数的大小关系,而不是由数组的index顺序决定的
使用递归,遍历每个元素,对于每个元素,查找其子孙节点,看是否可以构成拓扑排序(如果出现有向环的话,则不能排序)
一边检查一边记录
package test;
import java.util.Arrays;
import java.util.Scanner;
public class Test{
static Scanner sc = new Scanner(System.in);
static String line;
static int n = 9;
static int[] c = new int[n];//存储各点状态
static int[] topo = new int[n];//存储排序结果
static int t = n;//当前topo数组序号
static int[][] G = new int[n][n];//图
static boolean toposort(){
t = n;
for(int u=0;u<n;u++){//遍历图上的每一个点
if(c[u]==0){//如果改点没有被访问过
if(!dfs(u)){//如果改点和它的所有子孙有一个不可以拓扑排序
return false;
}
}
}
return true;
}
/**
* 这个方法可以判断某节点以及其所有子孙节点,能否产生拓扑排序
* @param u
* @return
*/
private static boolean dfs(int u) {
c[u] = -1;//-1表示改点正在被访问
for(int v=0;v<n;v++){//循环查找子节点
if(G[u][v]==1){//子节点
if(c[v]==-1){//如果子节点正在被访问,说明存在有向环,失败退出
return false;
}else if(c[v]==0 && !dfs(v)){//如果该子节点没有被访问过,并且其子孙不可以产生拓扑排序,失败
return false;
}
}
}
c[u] = 1;//标记改节点以及其子孙节点被访问过,且可以正常排序
topo[--t] = u;//存储该节点
return true;
}
public static void main(String[] args) {
//虚拟数据
G[0][3] = 1;
G[1][3] = 1;
G[6][5] = 1;
G[4][2] = 1;
G[1][6] = 1;
if(toposort()){
System.out.println(Arrays.toString(topo));
}
}
}