图拓扑排序的两种方法实现

方法一:

(1)在有向图中选一个没有前驱(入度为0)的点输出。

(2)从图中删除该顶点和所有以它为尾的弧。

重复以上步骤,直至全部顶点均已输出,或者当前图中不存在五前驱的顶点为止。


在实现中,我们可以用一个队列存入所有入度为0的顶点。然后依次删除这些顶点,和其对应的边,如果对应边删除后其终点的入度减为0者也将其存入队列中,如此循环下去,直到队列为空。最后比较列表中的节点数是否等于图的顶点数,如果不等者图存在一个环。

基于以上的规则可以用下面的代码来实现图的拓扑排序。

 

Java代码  收藏代码
  1. /** 
  2.      * 图的拓扑排序2,该方法会改变图的结构 
  3.      * @param <T> 
  4.      * @return 
  5.      */  
  6.     public static<T> List<T> topologicalSort2(Graph<T> graph){  
  7.         Queue<T> vQueue = new LinkedList<T>();  
  8.         List<T> vList = new ArrayList<T>();  
  9.         Set<T> vSet = graph.vertexSet();  
  10.         Set<T> neighbors = null;  
  11.         T vertex = null;  
  12.         //将入度为0的节点存入队列中  
  13.         for(T v : vSet){  
  14.             if(graph.getIndegree(v) == 0){  
  15.                 vQueue.add(v);  
  16.                 vList.add(v);  
  17.             }  
  18.         }  
  19.         while(!vQueue.isEmpty()){  
  20.             vertex = vQueue.poll();  
  21.             neighbors = graph.getNeighbors(vertex);  
  22.             for(T neighbor : neighbors){  
  23.                 graph.removeEdge(vertex, neighbor);//删除该边  
  24.                 if(graph.getIndegree(neighbor) == 0){//若neighbor的入度变为0,者也将其加入队列中  
  25.                     vQueue.add(neighbor);  
  26.                     vList.add(neighbor);  
  27.                 }  
  28.             }  
  29.         }  
  30.         if(vList.size() != graph.numberOfVertices()){  
  31.             throw new IllegalStateException("存在环");  
  32.         }  
  33.         return vList;  
  34.     }  

 

 方法二:

可以证明在被路径p(v,w)连接的任意顶点所在的图中,对于v和w来说,v在列表中必须出现在w之前。

依据这个结论可以对图的每个节点进行一个dfs的遍历,最终的节点列表就是拓扑排序的一个结果(要对这个列表反转).

 

 

Java代码  收藏代码
  1. /** 
  2.      * 图的拓扑排序 
  3.      * @param <T> 
  4.      * @param graph 
  5.      * @return 
  6.      */  
  7.     public static<T> List<T> topologicalSort(Graph<T> graph){  
  8.         List<T> vList = new ArrayList<T>();  
  9.         graph.allUnVisted();  
  10.         for(T v : graph.vertexSet()){  
  11.             if(graph.getState(v) == VertexState.UNVISITED){  
  12.                 try{  
  13.                     dfsHandler(graph, v, true, vList);  
  14.                 }catch (IllegalStateException e) {  
  15.                     throw new IllegalStateException("图有一个环");  
  16.                 }  
  17.             }  
  18.         }  
  19.         Collections.reverse(vList);  
  20.         return vList;  
  21.           
  22.           
  23.     }  

 

 测试:

针对下面这个图进行测试



 /**

Java代码  收藏代码
  1.  * 测试图的拓扑排序  
  2.  */  
  3. public void testTopologicalSort(){  
  4.     List<String> vList = GraphUtil.topologicalSort(graph);  
  5.     System.out.println(Arrays.toString(vList.toArray()));  
  6.       
  7.     vList = GraphUtil.topologicalSort2(graph);  
  8.     System.out.println(Arrays.toString(vList.toArray()));  
  9. }  

 Output:

[c2, c5, c1, c3, c7, c6, c4, c8]

[c1, c2, c3, c5, c4, c6, c7, c8]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值