Provjera ima li Java Graph ciklus
1. Pregled
U ovom brzom vodiču naučit ćemo kako možemo detektirati ciklus u zadanom usmjerenom grafu.
2. Prikaz grafikona
Za ovaj se vodič pridržavamo prikazivanja grafa popisa susjednosti.
Prvo, krenimo definiranjem a Vrh na Javi:
javna klasa Vertex {oznaka privatnog niza; private boolean beingVisited; posjećena privatna logička vrijednost; privatni popis adjacencyList; javni vrh (oznaka niza) {this.label = label; this.adjacencyList = novi ArrayList (); } javna void addNeighbor (susjedni vrh) {this.adjacencyList.add (susjedni); } // geteri i postavljači}
Evo, adjacencyList vrha v sadrži popis svih vrhova susjednih v. The addNeighbor () metoda dodaje susjedni vrh na listu susjednosti v.
Također smo definirali dvije boolean parametri,biti posjećen i posjetili, koji predstavljaju da li se čvor trenutno posjećuje ili je već posjećen.
Graf se može smatrati skupom vrhova ili čvorova povezanih rubovima.
Dakle, hajde sada brzo predstavimo a Grafikon na Javi:
javni razred Graf {vrhovi privatnog popisa; javni grafikon () {this.vertices = novi ArrayList (); } javna praznina addVertex (Vertex vertex) {this.vertices.add (vertex); } javna praznina addEdge (Vertex from, Vertex to) {from.addNeighbor (to); } // ...}
Koristit ćemo addVertex () i addEdge () metode za dodavanje novih vrhova i bridova u naš graf.
3. Otkrivanje ciklusa
Da biste otkrili ciklus u usmjerenom grafu, koristit ćemo varijaciju DFS prijelaz:
- Podignite ne posjećeni vrh v i označite njegovo stanje kao biti posjećen
- Za svaki susjedni vrh u od v, ček:
- Ako u je već u biti posjećen država, to jasno znači postoji stražnji rub i tako je otkriven ciklus
- Ako u još uvijek nije u posjeti, posjetit ćemo ga rekurzivno u na dubinski način
- Ažurirajte vrh v‘S biti posjećen zastava do lažno I je posjetili zastava do pravi
Imajte na umu da svi vrhovi našeg grafa su u početku u ne posjećenom stanju kao i njihovi biti posjećen i posjetili zastavice su inicijalizirane s lažno.
Pogledajmo sada naše Java rješenje:
javni boolean hasCycle (Vertex sourceVertex) {sourceVertex.setBeingVisited (true); for (Vertex susjeda: sourceVertex.getAdjacencyList ()) {if (sjed.isBeingVisited ()) {// unatrag postoji rub return true; } inače if (! susjeda.isVisited () && hasCycle (susjed)) {return true; }} sourceVertex.setBeingVisited (false); sourceVertex.setVisited (true); return false; }
Bilo koji vrh u grafu možemo koristiti kao izvor ili početni vrh.
Za nepovezani graf morat ćemo dodati dodatnu metodu omota:
javni boolean hasCycle () {for (Vertex vertex: vertices) {if (! vertex.isVisited () && hasCycle (vertex)) {return true; }} return false; }
To je osiguravanje da posjetimo svaku komponentu nepovezanog grafa za otkrivanje ciklusa.
4. Provjera provedbe
Razmotrimo donji ciklički usmjereni graf:
Možemo brzo napisati JUnit kako bismo provjerili naš hasCycle () metoda za ovaj graf:
@Test javna praznina givenGraph_whenCycleExists_thenReturnTrue () {Vertex vertexA = new Vertex ("A"); Vrh tjemenaB = novi vrh ("B"); Vrh tjemenaC = novi vrh ("C") Vrh vrhaD = novi vrh ("D"); Grafikon grafa = novi Grafikon (); graph.addVertex (vertexA); graph.addVertex (vrhB); graph.addVertex (vertexC); graph.addVertex (vertexD); graph.addEdge (vrhA, vrhB); graph.addEdge (vrhB, vrhC); graph.addEdge (vrhC, vrhA); graph.addEdge (vertexD, vertexC); assertTrue (graph.hasCycle ()); }
Evo, naša hasCycle () metoda vraćena pravi označavajući da je naš graf ciklički.
5. Zaključak
U ovom uputstvu naučili smo kako provjeriti postoji li ciklus u danom usmjerenom grafu na Javi.
Kao i obično, implementacija koda s primjerima dostupna je na Githubu.