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
kosaraju算法