Erkennen von Zyklen in einem Diagramm mit DFS: 2 verschiedene Ansätze und was ist der Unterschied
Beachten Sie, dass ein graph wird dargestellt als ein angrenzens Liste.
Ich gehört habe 2 Ansätze zu finden, ein Zyklus in einem Graphen:
- Halten Sie ein array von booleschen Werte, um zu verfolgen, ob Sie schon einen Knoten vor. Wenn Sie neue Knoten zu gehen (ohne auf einen Knoten, der Sie bereits), dann einfach neu ansetzen und versuchen einen anderen Zweig.
- Der von Cormen ist CLRS oder Skiena: Für die Tiefensuche in ungerichteten Graphen gibt es zwei Arten von Kanten -, Baum-und zurück. Der graph hat einen Zyklus, wenn, und nur wenn es gibt eine back edge.
Kann jemand erklären, was sind die Kanten eines Graphen und was die diffirence zwischen den oben genannten 2 Methoden.
Dank.
Update:
Hier ist der code zum erkennen von Zyklen in beiden Fällen. Graph ist eine einfache Klasse, die repräsentiert alle graph-Knoten als eindeutige Nummern für Einfachheit, jeder Knoten hat seine angrenzenden benachbarten Knoten (g.getAdjacentNodes(int)):
public class Graph {
private int[][] nodes; //all nodes; e.g. int[][] nodes = {{1,2,3}, {3,2,1,5,6}...};
public int[] getAdjacentNodes(int v) {
return nodes[v];
}
//number of vertices in a graph
public int vSize() {
return nodes.length;
}
}
Java-code, der zum erkennen von Zyklen in ungerichteten Graphen:
public class DFSCycle {
private boolean marked[];
private int s;
private Graph g;
private boolean hasCycle;
//s - starting node
public DFSCycle(Graph g, int s) {
this.g = g;
this.s = s;
marked = new boolean[g.vSize()];
findCycle(g,s,s);
}
public boolean hasCycle() {
return hasCycle;
}
public void findCycle(Graph g, int v, int u) {
marked[v] = true;
for (int w : g.getAdjacentNodes(v)) {
if(!marked[w]) {
marked[w] = true;
findCycle(g,w,v);
} else if (v != u) {
hasCycle = true;
return;
}
}
}
}
Java-code, der zum erkennen von Zyklen in einem gerichteten Graphen:
public class DFSDirectedCycle {
private boolean marked[];
private boolean onStack[];
private int s;
private Graph g;
private boolean hasCycle;
public DFSDirectedCycle(Graph g, int s) {
this.s = s
this.g = g;
marked = new boolean[g.vSize()];
onStack = new boolean[g.vSize()];
findCycle(g,s);
}
public boolean hasCycle() {
return hasCycle;
}
public void findCycle(Graph g, int v) {
marked[v] = true;
onStack[v] = true;
for (int w : g.adjacentNodes(v)) {
if(!marked[w]) {
findCycle(g,w);
} else if (onStack[w]) {
hasCycle = true;
return;
}
}
onStack[v] = false;
}
}
InformationsquelleAutor der Frage Ivan Voroshilin | 2013-10-01
Du musst angemeldet sein, um einen Kommentar abzugeben.
Beantwortung meiner Frage:
Der graph hat einen Zyklus, wenn, und nur wenn es gibt eine back edge. Eine hintere Kante ist eine Kante von einem Knoten zu sich selbst (selfloop) oder einer seiner Vorfahren im Baum produziert von der DFS bilden einen Zyklus.
Beide Ansätze oben eigentlich das gleiche bedeuten. Diese Methode kann jedoch nur angewandt werden, um ungerichtete Graphen.
Der Grund, warum dieser Algorithmus funktioniert nicht für gerichtete Graphen ist, dass in einem gerichteten Graphen 2 verschiedene Wege zum gleichen vertex machen Sie nicht einen Zyklus. Zum Beispiel: A-->B, B-->C, A-->C - machen Sie nicht einen Zyklus in der Erwägung, dass in ungerichteten: A--B, B--C, C--A hat.
Finden Sie einen Zyklus im ungerichteten Graphen
Einem ungerichteten graph hat einen Zyklus, wenn, und nur wenn ein depth-first-search (DFS) findet eine Kante, die Punkte zu einem bereits besuchten Knoten (eine back-edge).
Finden eines Zyklus in gerichteten Graphen
Zusätzlich zu den besuchten Ecken, die wir brauchen, um zu verfolgen Eckpunkte derzeit in der Rekursion-stack der Funktion für die DFS-Traversierung. Wenn wir erreichen einen Scheitelpunkt, der bereits in der Rekursion-stack, dann gibt es einen Zyklus im Baum.
Update:
Arbeiten code ist in der Frage oben.
InformationsquelleAutor der Antwort Ivan Voroshilin
Zur Vervollständigung, es ist möglich, zu finden von Zyklen in einem gerichteten Graphen mit DFS (aus wikipedia):
InformationsquelleAutor der Antwort Igor Zelaya
Hier ist der code, den ich geschrieben hab in C, basierend auf DFS, um herauszufinden, ob ein bestimmtes ungerichtete Graphen angeschlossen ist/zyklische oder nicht. mit einigen Probe-Ausgabe am Ende. Hoffe, es wird hilfreich sein 🙂
Beispiel-Ausgabe:
InformationsquelleAutor der Antwort Majid NK