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.


$config[zx-auto] not found$config[zx-overlay] not found