Controleren of een Java-grafiek een cyclus heeft

1. Overzicht

In deze korte tutorial leren we hoe we dat kunnen detecteer een cyclus in een bepaalde gerichte grafiek.

2. Grafische weergave

Voor deze zelfstudie houden we ons aan de grafiekweergave van de aangrenzende lijst.

Laten we eerst beginnen met het definiëren van een Vertex in Java:

openbare klasse Vertex {private String-label; privé boolean beingVisited; privé boolean bezocht; privélijst adjacencyList; public Vertex (String label) {this.label = label; this.adjacencyList = nieuwe ArrayList (); } public void addNe Neighbor (Vertex aangrenzend) {this.adjacencyList.add (aangrenzend); } // getters en setters}

Hier de adjacencyList van een hoekpunt v bevat een lijst met alle hoekpunten naast v. De Voeg buurman toe() methode voegt een aangrenzend hoekpunt toe aan de aangrenzende lijst van v.

We hebben er ook twee gedefinieerd boolean parameters,wordt bezocht en bezocht, die aangeven of het knooppunt momenteel wordt bezocht of al is bezocht.

Een graaf kan worden gezien als een groep hoekpunten of knooppunten die via de randen zijn verbonden.

Dus laten we nu snel een Grafiek in Java:

openbare klasse Graph {hoekpunten van de privélijst; openbare Graph () {this.vertices = nieuwe ArrayList (); } public void addVertex (Vertex vertex) {this.vertices.add (vertex); } public void addEdge (Vertex from, Vertex to) {from.addNe Neighbor (to); } // ...}

We gebruiken de addVertex () en addEdge () methoden om nieuwe hoekpunten en randen in onze grafiek toe te voegen.

3. Cyclusdetectie

Om een ​​cyclus in een gerichte grafiek te detecteren, we gebruiken een variatie van DFS doorkruisen:

  • Pak een onbezochte top op v en markeer de staat als wordt bezocht
  • Voor elk aangrenzend hoekpunt u van v, controleren:
    • Als u is al in de wordt bezocht staat, het betekent duidelijk er is een achterrand en dus is er een cyclus gedetecteerd
    • Als u is nog in een onbezochte staat, zullen we recursief bezoeken u op een diepte-eerste manier
  • Werk het hoekpunt bij v‘S wordt bezocht vlag naar false en zijn bezocht vlag naar waar

Let daar op alle hoekpunten van onze graaf bevinden zich aanvankelijk in een niet-bezochte staat, aangezien beide hun wordt bezocht en bezocht vlaggen worden geïnitialiseerd met false.

Laten we nu eens kijken naar onze Java-oplossing:

openbare boolean hasCycle (Vertex sourceVertex) {sourceVertex.setBeingVisited (true); for (Vertex neighbour: sourceVertex.getAdjacencyList ()) {if (neighbour.isBeingVisited ()) {// backward edge exist return true; } else if (! neighbour.isVisited () && hasCycle (neighbour)) {return true; }} sourceVertex.setBeingVisited (false); sourceVertex.setVisited (true); teruggeven false; }

We kunnen elk hoekpunt in een grafiek gebruiken om de bron of het beginpunt te zijn.

Voor een losgekoppelde grafiek moeten we een extra wrapper-methode toevoegen:

openbare boolean hasCycle () {for (Vertex vertex: hoekpunten) {if (! vertex.isVisited () && hasCycle (vertex)) {return true; }} return false; }

Dit is om ervoor te zorgen dat we elk onderdeel van een losgekoppelde grafiek bezoeken om een ​​cyclus te detecteren.

4. Implementatietesten

Laten we eens kijken naar de onderstaande cyclisch gerichte grafiek:

We kunnen snel een JUnit schrijven om onze hasCycle () methode voor deze grafiek:

@Test openbare leegte gegevenGraph_whenCycleExists_thenReturnTrue () {Vertex vertexA = nieuwe Vertex ("A"); Vertex vertexB = nieuw Vertex ("B"); Vertex vertexC = nieuw Vertex ("C") Vertex vertexD = nieuw Vertex ("D"); Graph graph = nieuwe Graph (); graph.addVertex (vertexA); graph.addVertex (vertexB); graph.addVertex (vertexC); graph.addVertex (vertexD); graph.addEdge (vertexA, vertexB); graph.addEdge (vertexB, vertexC); graph.addEdge (vertexC, vertexA); graph.addEdge (vertexD, vertexC); assertTrue (graph.hasCycle ()); }

Hier, onze hasCycle () methode geretourneerd waar wat aangeeft dat onze grafiek cyclisch is.

5. Conclusie

In deze tutorial hebben we geleerd hoe we kunnen controleren of een cyclus bestaat in een bepaalde gerichte grafiek in Java.

Zoals gewoonlijk is de code-implementatie met voorbeelden beschikbaar op Github.


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