1.知识储备
2.检测有向图中的环:
代码:
package Graph;
public class DirectedCycle {
//索引代表顶点,值表示当前顶点是否已经被搜索
private boolean[] marked ;
//记录图中是否有环
private boolean hasCycle;
//索引代表顶点,使用栈的思想,记录当前顶点有没有已经处于正在搜索的有向路径上
private boolean[] onStack;
//创建一个检测环对象,检测图中G是否有环
public DirectedCycle(DiGraph G) {
// TODO Auto-generated constructor stub
//初始化marked数组
this.marked=new boolean[G.V()];
//初始化hasCycle
this.hasCycle=false;
//初始化onStack数组
this.onStack=new boolean[G.V()];
//找到图中每一个顶点,让每一个顶点作为入口,调用一次dfs搜索
for(int v=0;v<G.V();v++){
//判断如果当前顶点还没有搜索过,则调用dfs进行搜索
if(!marked[v]){
dfs(G,v);
}
}
}
//基于深度优先搜索,检测图G中是否有环
private void dfs(DiGraph G,int v){
//把顶点v标识为也搜索
marked[v]=true;
//把当前顶点进栈
onStack[v]=true;
//进行深度搜索
for(Integer w:G.adj(v)){
//判断如果当前顶点还没有被搜索过,则继续递归调用dfs方法完成深度优先搜索
if(!marked[w]){
dfs(G,w);
}
//判断当前顶点w是否已经在栈中,如果已经在栈中,说明当前顶点正处于搜索状态,那么现在又要搜索一次,就证明已经检测到环了
if(onStack[w]){
hasCycle=true;
return ;
}
}
//把当前顶点出栈
onStack[v]=false;
}
//判断当前图G中是否有环
public boolean hasCycle(){
return hasCycle;
}
}
3.顶点排序:
代码:
package Graph;
import Stack.Stack;
public class DepthFirstOrder {
//索引代表顶点,值表示当前顶点是否已经被搜索
private boolean[] marked;
//使用栈,存储顶点序列
private Stack<Integer> reverserPost;
//创建一个检测环对象,检测图G中是否有环
public DepthFirstOrder(DiGraph G){
//初始化marked数组
this.marked=new boolean[G.V()];
//初始化reverse栈
this.reverserPost=new Stack<Integer>();
//遍历图中的每一个顶点,让每个顶点作为入口,完成一次深度优先搜索
for(int v=0;v<G.V();v++){
if(!marked[v]){
dfs(G,v);
}
}
}
//基于深度优先搜索,把顶点排序
public void dfs(DiGraph G,int v){
//标记v已经被搜索
marked[v]=true;
//通过循环深度搜索顶点v
for(Integer w: G.adj(v)){
//如果当前顶点w没有被搜索,则继续调用dfs递归搜索
if(!marked[w]){
dfs(G,w);
}
}
//让顶点v进栈
reverserPost.push(v);
}
//获取顶点线性序列
public Stack<Integer> reversePost(){
return reverserPost;
}
}
4.拓扑排序的实现:
代码实现:
package Graph;
import Stack.Stack;
public class ToPoLogical {
//顶点的拓扑排序
private Stack<Integer> order;
//构造拓扑排序对象
public ToPoLogical(DiGraph G) {
// TODO Auto-generated constructor stub
//创建一个检测有向环的对象
DirectedCycle cycle=new DirectedCycle(G);
//判断G图中有没有环,如果没有环,则进行顶点排序,创建一个顶点排序对象
if(!cycle.hasCycle()){
DepthFirstOrder depthfirstorder= new DepthFirstOrder(G);
order=depthfirstorder.reversePost();
}
}
//判断图G是否有环
private boolean isCycle(){
return order==null;
}
//获取拓扑排序的所有顶点
public Stack<Integer> order(){
return order;
}
}
测试类:
package Graph;
import Stack.Stack;
public class TopoLogicalTest {
public static void main(String[] args) {
//准备有向图
DiGraph diGraph =new DiGraph(6);
diGraph.addEdge(0,2);
diGraph.addEdge(0,3);
diGraph.addEdge(2,4);
diGraph.addEdge(3,4);
diGraph.addEdge(4,5);
diGraph.addEdge(1,3);
//通过ToPoLogical对象对有向图的顶点进行排序
ToPoLogical topological=new ToPoLogical(diGraph);
//获取顶点的线性序列进行打印
Stack<Integer> order=topological.order();
StringBuilder sb=new StringBuilder();
for(Integer w: order){
sb.append(w+"->");
}
String str =sb.toString();
int index=str.lastIndexOf("->");
str=str.substring(0,index);
System.out.println(str);
}
}