有向圖中,打印出所有的迴路(Java)
具體思路:利用DFS算法深度遍歷圖中的每一個節點。在遍歷的同時設置一個list,用來存放已經遍歷過的點;如果再遍歷到這個點(說明形成了迴路)的時候就打印出來。
注意點:
- 需要記錄每一個點“是否被訪問過”的狀態。
- 由於是有向圖,所以實際上並不能保證從一個特定的點出發能夠遍歷到圖中所有的點,因此需要從圖中每一個點出發將圖遍歷一遍。
- 在遍歷不同的節點的時候需要注意將圖中點的狀態全部恢復
下面是具體代碼
最後兩個函數sortString
和bubbleArray
兩個函數是沒有必要的,是爲了讓輸出更加的美觀添加的函數。
import java.io.*;
import java.util.*;
public class Main {
/*要求:判斷一個有向圖中是否有迴路,並且打印出所有的迴路。
思路:通過修改的DFS算法遍歷有向圖。
在遍歷的過程中,把遍歷到的所有的元素都存儲到一個隊列裏面,然後每次遍歷到一個節點的時候就檢查一下這個隊列;要是隊列裏面已經有重複的元素
那就表明已經形成了迴路,然後打印出來這個迴路;然後中斷遍歷,回去遍歷別的節點。
*/
private String filename = "";
//用鄰接表來初始化要檢查的有向圖
private Map<String,ArrayList<String>> Graph = new HashMap<String, ArrayList<String>>();
ArrayList POINTS = new ArrayList();
public void initGraph() throws IOException {
File file = new File(filename);
FileInputStream fileInputStream = new FileInputStream(file);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
String line = null;
while ((line = bufferedReader.readLine()) != null){
String[] temp = line.split(",");
if (!POINTS.contains(temp[0])){
POINTS.add(temp[0]);
}
if (!POINTS.contains(temp[1])){
POINTS.add(temp[1]);
}
if (this.Graph.containsKey(temp[0])){
ArrayList<String> A = Graph.get(temp[0]);
A.add(temp[1]);
this.Graph.put(temp[0],A);
}
else {
ArrayList<String> newList = new ArrayList<String>();
newList.add(temp[1]);
this.Graph.put(temp[0],newList);
}
}
bufferedReader.close();
}
//建造一個HashMap來記錄每一個點的狀態(是否被訪問過)
private HashMap<String,Boolean> NodeState = new HashMap<String, Boolean>();
//用來存放已經被遍歷過的點
private ArrayList<String> nodeList = new ArrayList<String>();
//設置以用來存放最後的結果
ArrayList<ArrayList<String>> result = new ArrayList<ArrayList<String>>();
public void SearchingStart(String firstNode){
nodeList.add(firstNode);
NodeState.put(firstNode,true);
List<String> tempList = Graph.get(firstNode);
//遍歷x的鄰接節點
if (tempList == null){
return;
}
for (String x : tempList){
/*
for (String mmm : nodeList){
System.out.print(mmm);
}
System.out.println();
System.out.println("現在正在訪問的是"+x);
*/
//檢測這個點是否已經在list中,如果已經在list中說明x與x之後遍歷的所有元素形成了一個迴路,打印出來
if (nodeList.contains(x)){
List<String> loopList = nodeList.subList(nodeList.indexOf(x),nodeList.size());
ArrayList<String> toBeAddedInToReault = new ArrayList<String>();
for (String points:loopList){
toBeAddedInToReault.add(points);
continue;
}
//檢查要被加進去的迴路是否已經存在
if (!HasHave(result,toBeAddedInToReault)) {
result.add(toBeAddedInToReault);
}
}
else {
//如果這個節點沒有鄰接點了
if (Graph.get(x) == null) {
NodeState.put(x,true);
continue;
}
//如果這個節點指向的所有鄰接點都已經被訪問過了
boolean allVisited = true;
for (String neighborPoints : Graph.get(x)){
if (!NodeState.containsKey(neighborPoints)){
allVisited = false;
break;
}
if (NodeState.get(neighborPoints) == true){
continue;
}
else {
allVisited = false;
break;
}
}
//描述"所有的鄰接點都被訪問過,但是其中有能夠構成迴路的鄰接點"
boolean b1 = false;
for (String neighborPoints : Graph.get(x)) {
if (nodeList.contains(neighborPoints)) {
b1 = true;
}
}
if (allVisited && b1){
allVisited = false;
}
//描述"所有的鄰接點都被訪問過,而且這些鄰接點都不能構成迴路"
if (allVisited){
continue;
}
//如果這個節點有沒有被訪問過的鄰接點
else {
SearchingStart(x);
}
}
}
nodeList.remove(nodeList.size() - 1);
}
public static void main(String[] args) {
Main a = new Main();
try {
a.initGraph();
} catch (IOException e) {
e.printStackTrace();
}
ArrayList<String> nodes = a.POINTS;
for (int i = 0 ; i < nodes.size() ; i ++){
String temp = nodes.get(i);
a.SearchingStart(temp);
a.nodeList.clear();
a.NodeState.clear();
}
ArrayList R = a.result;
if (R.isEmpty()){
System.out.println(0);
}
else {
System.out.println(1);
System.out.println(R.size());
R = bubbleArray(R);
for (int i = 0 ; i <= R.size() - 1 ; i ++){
ArrayList A = (ArrayList) R.get(i);
A = sortString(A);
for (int j = 1 ; j <= A.size() - 1 ; j ++){
System.out.print(A.get(j - 1)+" ");
}
System.out.println(A.get(A.size() - 1));
}
}
}
public static ArrayList sortString(ArrayList<String> R){
int minIndex = 0 ;
for (int i = 1 ; i <= R.size() - 1 ; i ++){
if (Integer.valueOf(R.get(i))<Integer.valueOf(R.get(minIndex))){
minIndex = i;
}
}
ArrayList result = new ArrayList();
for (int j = minIndex ; j <= R.size() - 1 ; j ++ ){
result.add(R.get(j));
}
for (int k = 0 ; k < minIndex ; k ++){
result.add(R.get(k));
}
return result;
}
public static ArrayList bubbleArray(ArrayList<ArrayList> R){
for (int i = 0 ; i < R.size()-1 ; i ++){
for (int j = 0 ; j < R.size() - 1 - i ; j ++ ){
if (R.get(j + 1).size() < R.get(j).size()){
ArrayList temp1 = R.get(j);
ArrayList temp2 = R.get(j+1);
R.remove(j);
R.add(j,temp2);
R.remove(j+1);
R.add(j+1,temp1);
}
}
}
return R;
}
public boolean HasHave(ArrayList<ArrayList<String>> A , ArrayList<String> a){
for (int i = 0 ; i < A.size() ; i ++){
if (A.get(i).size() == a.size()){
int j = 0;
while (j < A.get(i).size()){
String k = A.get(i).get(j);
j++;
if (!a.contains(k)){
return false;
}
else continue;
}
return true;
}
}
return false;
}
}