From 26f51a8951c810a15bb645622683f5bd5e2e13e3 Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Thu, 24 Oct 2024 10:12:49 +0530 Subject: [PATCH] refactor: Enhance docs, add more tests in `HamiltonianCycle` --- .../graphs/HamiltonianCycle.java | 65 +++++++++---------- .../graphs/HamiltonianCycleTest.java | 61 ++++++++++++++++- 2 files changed, 92 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/thealgorithms/datastructures/graphs/HamiltonianCycle.java b/src/main/java/com/thealgorithms/datastructures/graphs/HamiltonianCycle.java index f12e3892b1b2..5c95850c4971 100644 --- a/src/main/java/com/thealgorithms/datastructures/graphs/HamiltonianCycle.java +++ b/src/main/java/com/thealgorithms/datastructures/graphs/HamiltonianCycle.java @@ -1,8 +1,14 @@ package com.thealgorithms.datastructures.graphs; +import java.util.Arrays; + /** - * Java program for Hamiltonian Cycle - * wikipedia + * 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. + * + *

For more details, see the + * Wikipedia article. * * @author Akshay Dubey */ @@ -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 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; @@ -58,31 +63,26 @@ public boolean isPathFound(int vertex) { 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 boolean isPathFound(int vertex) { } /** - * 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 boolean isPresent(int vertex) { return true; } } - return false; } } diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/HamiltonianCycleTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/HamiltonianCycleTest.java index ed7c886d784e..4529606d7797 100644 --- a/src/test/java/com/thealgorithms/datastructures/graphs/HamiltonianCycleTest.java +++ b/src/test/java/com/thealgorithms/datastructures/graphs/HamiltonianCycleTest.java @@ -6,7 +6,7 @@ class HamiltonianCycleTest { - private HamiltonianCycle hamiltonianCycle = new HamiltonianCycle(); + private final HamiltonianCycle hamiltonianCycle = new HamiltonianCycle(); @Test void testFindHamiltonianCycleShouldReturnHamiltonianCycle() { @@ -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)); + } }