Skip to content

refactor: Enhance docs, add more tests in HamiltonianCycle #5963

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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>
*/
Expand All @@ -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];
}
Expand All @@ -46,62 +52,55 @@ public int[] findHamiltonianCycle(int[][] graph) {
}

/**
* 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;
if (isLastVertexConnectedToStart) {
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;
}
}
return false;
}

/**
* 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++) {
if (cycle[i] == vertex) {
return true;
}
}

return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class HamiltonianCycleTest {

private HamiltonianCycle hamiltonianCycle = new HamiltonianCycle();
private final HamiltonianCycle hamiltonianCycle = new HamiltonianCycle();

@Test
void testFindHamiltonianCycleShouldReturnHamiltonianCycle() {
Expand Down Expand Up @@ -36,4 +36,63 @@ void testFindHamiltonianCycleShouldReturnInfinityArray() {

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));
}
}