实施Kosaraju算法以找到强连接的组件

上次我给出了数学推理来证明Dijkstra的算法。

这次,我为Kosaraju算法提供了一种可能的实现方式,该算法可在有向图中找到强连接的组件。 “牢固连接的组件”的简称是SCC

程序的目的

=========================

该程序在有向图中找到5个最密集的强连接组件中的节点数。 稠密的是指SCC中顶点的数量。

如果少于五个,则说最多找到三个。 并假设这些组件中的节点数为3、2、1,则结果将显示为

3

2

1个

0

0

假设条件

============

代表图形的文本文件不包含任何隔离的节点。 如果包含该程序,可以很容易地进行修改以考虑到这一点。

说明

==========

1>文本文件代表每行一个有向边。

2>需要将附件zip中的文件提取到名为c:\ test的文件夹中。 如果不存在,则需要创建该文件夹。

3>必须将Test.txt文件复制到C:\ folder。 如果不存在,则需要创建该文件夹。

4>命令提示符应打开(cmd)

5>以下命令应以完全相同的顺序给出。

> cd \

> cd测试

> C:\ <javahome> \ bin \ javac Graph.java

> C:\ <javahome> \ bin \ java -Xss8m -XX:+ UseSerialGC图形

注意

====

1>该程序已编译并以Java版本1.7.0_13运行

2> -Xss8m -XX:+ UseSerialGC选项已被使用,因为如果test.txt表示的节点大于10000,那么如果没有该选项,则可能会出现stackoverflow错误。

3>由于算法本身有点复杂,因此使用了递归版本的dfs。 阅读器可能实现非递归版本

这是代码:

Graph.java
 
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList; 
/**
 * 
 * @author Sankar
 * This talks about directed graph. This class runs Kosaraju's algorithm
 * to find out the connected components and at last gives us 5 mostly 
 * dense Strongly connected components in decreasing order
 * The word dense is defined by the number of nodes here.
 * Answer should appear like 3,3,3,0,0 or something like
 * that. These denotes the number of nodes in SCC
 */
public class Graph { 
    private static final int SIZE = 9;//Number of nodes in the graph
    private final static String space = " ";    
    /**
     * All node vertexes
     */
    private static Vertex[] allVert = null;
    /**
     * After dfs is carried out in the reversed graph
     */
    private static Vertex[] after1Pass = null;
    /**
     * finishing times
     */
    private static int fTime = -1;
    private static int totCon = 0;
    /**
     * In the main method the array has been initialized with 5 vertexes
     */
    private static LinkedList<Vertex> leaders = new LinkedList<Vertex>(); 
    /**
     * This method creates graph from the file and closes the file.
     */
    public static void createGraph(){  
        allVert = new Vertex[SIZE];//Array created but elements are null  
        BufferedReader br = null;
        String sCurrentLine; 
        try { 
            br = new BufferedReader(new FileReader("C:\\folder\\Test.txt"));
                while ((sCurrentLine = br.readLine()) != null) {  
                    int vertIdx = sCurrentLine.trim().indexOf(space);
                    String ver = sCurrentLine.trim().substring(0, vertIdx);
                    int vrtInt = Integer.parseInt(ver); 
                    int edgeIdx = sCurrentLine.trim().lastIndexOf(space);
                    String edge = sCurrentLine.trim().substring(edgeIdx+1);
                    int edgeInt = Integer.parseInt(edge); 
                    if(allVert[vrtInt-1]==null){
                        allVert[vrtInt-1] = new Vertex();
                        allVert[vrtInt-1].setNodeNo(vrtInt-1);
                    } 
                    if(allVert[edgeInt-1]==null){
                        allVert[edgeInt-1] = new Vertex();
                        allVert[edgeInt-1].setNodeNo(edgeInt-1);
                    } 
                    Vertex v = allVert[vrtInt-1];
                    Vertex u = allVert[edgeInt-1]; 
                    /**
                     * For the original graph
                     */
                    v.setOriginal(u);
                    /**
                     * For the reversed graph
                     */
                    u.setReverse(v);                      
                }                   
        }catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            try {
                if (br != null)br.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        } 
        /**
         * For testing of graph creation
         */   
    }   
    /**
     * 
     * @param v 
     * @param 
     * @return
     * This method runs the dfs algorithm through reversed graph
     */
    private static void dfsReverse(Vertex v){
        v.setExplored(1);
        ArrayList<Vertex> vArr = null;        
        vArr = v.getReverse();     
        /**
         * For all edges call dfs
         */        
        for(Vertex s:vArr){
            if(s.getExplored()==0){
                dfsReverse(s);                
            }
        }        
        fTime++; 
        //Set the finish time of this node
        v.setFTime(fTime); 
    }
    /**
     * DFS on the Original graph starting with maX finish time
     * @param v
     */
    private static void dfsOrig(Vertex v){
        v.setExplored(1);
        ArrayList<Vertex> vArr = null;
        /**
         * totCon counts the total number of nodes in this strongly connected component
         */
        totCon++;
        vArr = v.getOriginal(); 
        for(Vertex s:vArr){
            if(s.getExplored()==0){
                dfsOrig(s);                
            }
        }
    } 
    /**
     *  DFS Loop
     *  This method runs dfs twice
     *  Once on the reversed graph and then on the original graph
     */
    private static void dfsLoop(){
        for(int i = SIZE-1;i>=0;i--){
            if(allVert[i]!=null){
                if(allVert[i].getExplored()==0){
                    //Run DFS on the reversed graph
                    dfsReverse(allVert[i]);
                }
            }
        } 
        /**
         * This new array Stores Vertexes according to their finishing time
         */
        after1Pass = new Vertex[SIZE]; 
        for(int i = SIZE-1;i>=0;i--){
            if(allVert[i]!=null){
                Vertex v = allVert[i]; 
                int newInd = v.getFTime();
                after1Pass[newInd] = v;
                v.setExplored(0); 
            }
        } 
        /**
         * This array is no more required
         */
        allVert = null; 
        for(int i = SIZE-1;i>=0;i--){
            if(after1Pass[i]!=null){
                Vertex v = after1Pass[i];                
                if(v.getExplored()==0){ 
                    totCon = 0;
                    leaders.add(v);
                    dfsOrig(v); 
                    /**
                     * After dfs completes, set the number of strongly connected nodes
                     * to this node from where the dfs started
                     */
                    v.setLeaderOf(totCon); 
                    for(int k=0;k<5;k++){
                        if(leaders.get(k).getLeaderOf()<=totCon){
                            leaders.add(k,v);
                            break;
                        }
                    }
                }
            }
        } 
    }
    public static void main(String args[]){
        /**
         * add 5 vertexes
         */
        for(int k=0;k<5;k++){            
            leaders.add(new Vertex());
        }
        createGraph();
        dfsLoop();
        for(int k=0;k<5;k++){ 
            System.out.println(leaders.get(k).getLeaderOf());
        }
    }  
} 
顶点

import java.util.ArrayList; 
/**
 * 
 * @author Sankar
 * This class represents a node/vertex of the graph
 */
public class Vertex {
    /**
     * nodeNo indicates the vertex no
     */
    private int nodeNo = 0;
    private int fTime  = 0;
    private int explored = 0;
    private int leaderOf = 0;  
    private ArrayList<Vertex> original = new ArrayList<Vertex>();
    private ArrayList<Vertex> reverse = new ArrayList<Vertex>();
    public void setNodeNo(int n){
        nodeNo = n;
    }
    public int getNodeNo(){
        return nodeNo;
    }
    public void setFTime(int n){
        fTime = n;
    } 
    public int getFTime(){
        return fTime;
    }
    public int getExplored() {
        return explored;
    }
    public void setExplored(int explored) {
        this.explored = explored;
    }
    public int getLeaderOf() {
        return leaderOf;
    }
    public void setLeaderOf(int leaderOf) {
        this.leaderOf = leaderOf;
    }
    public ArrayList<Vertex> getOriginal() {
        return original;
    }
    public void setOriginal(Vertex v) {
        this.original.add(v);
    }
    public ArrayList<Vertex> getReverse() {
        return reverse;
    }
    public void setReverse(Vertex v) {
        this.reverse.add(v);
    }  
} 
test.txt

1 4

2 8

3 6

4 7

5 2

6 9

7 1

8 6

9 7

8 5

9 3

附加的文件
文件类型:zip test.zip (2.5 KB,178视图)

From: https://bytes.com/topic/algorithms/insights/951575-implementation-kosarajus-algo-find-strongly-connected-components

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值