Enhance docs, add more tests in HamiltonianCycle (#5963)

This commit is contained in:
Hardik Pawar
2024-10-24 10:52:24 +05:30
committed by GitHub
parent 1b51e3e988
commit 3a9a2c4160
2 changed files with 92 additions and 34 deletions

View File

@ -1,8 +1,14 @@
package com.thealgorithms.datastructures.graphs;
import java.util.Arrays;
/**
* Java program for Hamiltonian Cycle
* <a href="https://en.wikipedia.org/wiki/Hamiltonian_path">wikipedia</a>
* Java program to find a Hamiltonian Cycle in a graph.
* A Hamiltonian Cycle is a cycle that visits every vertex exactly once
* and returns to the starting vertex.
*
* <p>For more details, see the
* <a href="https://en.wikipedia.org/wiki/Hamiltonian_path">Wikipedia article</a>.
*
* @author <a href="https://github.com/itsAkshayDubey">Akshay Dubey</a>
*/
@ -14,30 +20,30 @@ public class HamiltonianCycle {
private int[][] graph;
/**
* Find hamiltonian cycle for given graph G(V,E)
* Finds a Hamiltonian Cycle for the given graph.
*
* @param graph Adjacency matrix of a graph G(V, E)
* for which hamiltonian path is to be found
* @return Array containing hamiltonian cycle
* else returns 1D array with value -1.
* @param graph Adjacency matrix representing the graph G(V, E), where V is
* the set of vertices and E is the set of edges.
* @return An array representing the Hamiltonian cycle if found, otherwise an
* array filled with -1 indicating no Hamiltonian cycle exists.
*/
public int[] findHamiltonianCycle(int[][] graph) {
// Single vertex graph
if (graph.length == 1) {
return new int[] {0, 0};
}
this.vertex = graph.length;
this.cycle = new int[this.vertex + 1];
// Initialize path array with -1 value
for (int i = 0; i < this.cycle.length; i++) {
this.cycle[i] = -1;
}
// Initialize the cycle array with -1 to represent unvisited vertices
Arrays.fill(this.cycle, -1);
this.graph = graph;
this.cycle[0] = 0;
this.pathCount = 1;
if (!isPathFound(0)) {
for (int i = 0; i < this.cycle.length; i++) {
this.cycle[i] = -1;
}
Arrays.fill(this.cycle, -1);
} else {
this.cycle[this.cycle.length - 1] = this.cycle[0];
}
@ -46,11 +52,10 @@ public class HamiltonianCycle {
}
/**
* function to find paths recursively
* Find paths recursively from given vertex
* Recursively searches for a Hamiltonian cycle from the given vertex.
*
* @param vertex Vertex from which path is to be found
* @returns true if path is found false otherwise
* @param vertex The current vertex from which to explore paths.
* @return {@code true} if a Hamiltonian cycle is found, otherwise {@code false}.
*/
public boolean isPathFound(int vertex) {
boolean isLastVertexConnectedToStart = this.graph[vertex][0] == 1 && this.pathCount == this.vertex;
@ -58,31 +63,26 @@ public class HamiltonianCycle {
return true;
}
/* all vertices selected but last vertex not linked to 0 **/
// If all vertices are visited but the last vertex is not connected to the start
if (this.pathCount == this.vertex) {
return false;
}
for (int v = 0; v < this.vertex; v++) {
/* if connected **/
if (this.graph[vertex][v] == 1) {
/* add to path **/
this.cycle[this.pathCount++] = v;
/* remove connection **/
if (this.graph[vertex][v] == 1) { // Check if there is an edge
this.cycle[this.pathCount++] = v; // Add the vertex to the cycle
this.graph[vertex][v] = 0;
this.graph[v][vertex] = 0;
/* if vertex not already selected solve recursively **/
// Recursively attempt to complete the cycle
if (!isPresent(v)) {
return isPathFound(v);
}
/* restore connection **/
// Restore the edge if the path does not work
this.graph[vertex][v] = 1;
this.graph[v][vertex] = 1;
/* remove path **/
this.cycle[--this.pathCount] = -1;
}
}
@ -90,10 +90,10 @@ public class HamiltonianCycle {
}
/**
* function to check if path is already selected
* Check if path is already selected
* Checks if a vertex is already part of the current Hamiltonian path.
*
* @param vertex Starting vertex
* @param vertex The vertex to check.
* @return {@code true} if the vertex is already in the path, otherwise {@code false}.
*/
public boolean isPresent(int vertex) {
for (int i = 0; i < pathCount - 1; i++) {
@ -101,7 +101,6 @@ public class HamiltonianCycle {
return true;
}
}
return false;
}
}

View File

@ -6,7 +6,7 @@ import org.junit.jupiter.api.Test;
class HamiltonianCycleTest {
private HamiltonianCycle hamiltonianCycle = new HamiltonianCycle();
private final HamiltonianCycle hamiltonianCycle = new HamiltonianCycle();
@Test
void testFindHamiltonianCycleShouldReturnHamiltonianCycle() {
@ -36,4 +36,63 @@ class HamiltonianCycleTest {
assertArrayEquals(expectedArray, hamiltonianCycle.findHamiltonianCycle(inputArray));
}
@Test
void testSingleVertexGraph() {
int[] expectedArray = {0, 0};
int[][] inputArray = {{0}};
assertArrayEquals(expectedArray, hamiltonianCycle.findHamiltonianCycle(inputArray));
}
@Test
void testDisconnectedGraphShouldReturnInfinityArray() {
int[] expectedArray = {-1, -1, -1, -1, -1};
int[][] inputArray = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};
assertArrayEquals(expectedArray, hamiltonianCycle.findHamiltonianCycle(inputArray));
}
@Test
void testCompleteGraphShouldReturnHamiltonianCycle() {
int[] expectedArray = {0, 1, 2, 3, 4, 0};
int[][] inputArray = {
{0, 1, 1, 1, 1},
{1, 0, 1, 1, 1},
{1, 1, 0, 1, 1},
{1, 1, 1, 0, 1},
{1, 1, 1, 1, 0},
};
assertArrayEquals(expectedArray, hamiltonianCycle.findHamiltonianCycle(inputArray));
}
@Test
void testGraphWithNoEdgesShouldReturnInfinityArray() {
int[] expectedArray = {-1, -1, -1, -1, -1, -1};
int[][] inputArray = {
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
};
assertArrayEquals(expectedArray, hamiltonianCycle.findHamiltonianCycle(inputArray));
}
@Test
void testLargeGraphWithHamiltonianCycle() {
int[] expectedArray = {0, 1, 2, 3, 4, 0};
int[][] inputArray = {
{0, 1, 0, 1, 1},
{1, 0, 1, 1, 0},
{0, 1, 0, 1, 1},
{1, 1, 1, 0, 1},
{1, 0, 1, 1, 0},
};
assertArrayEquals(expectedArray, hamiltonianCycle.findHamiltonianCycle(inputArray));
}
}