Skip to content

Commit aae5985

Browse files
Merge branch 'master' into master
2 parents e3582d8 + 3a9a2c4 commit aae5985

File tree

4 files changed

+151
-90
lines changed

4 files changed

+151
-90
lines changed
Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
package com.thealgorithms.datastructures.graphs;
22

3+
import java.util.Arrays;
4+
35
/**
4-
* Java program for Hamiltonian Cycle
5-
* <a href="https://en.wikipedia.org/wiki/Hamiltonian_path">wikipedia</a>
6+
* Java program to find a Hamiltonian Cycle in a graph.
7+
* A Hamiltonian Cycle is a cycle that visits every vertex exactly once
8+
* and returns to the starting vertex.
9+
*
10+
* <p>For more details, see the
11+
* <a href="https://en.wikipedia.org/wiki/Hamiltonian_path">Wikipedia article</a>.
612
*
713
* @author <a href="https://github.com/itsAkshayDubey">Akshay Dubey</a>
814
*/
@@ -14,30 +20,30 @@ public class HamiltonianCycle {
1420
private int[][] graph;
1521

1622
/**
17-
* Find hamiltonian cycle for given graph G(V,E)
23+
* Finds a Hamiltonian Cycle for the given graph.
1824
*
19-
* @param graph Adjacency matrix of a graph G(V, E)
20-
* for which hamiltonian path is to be found
21-
* @return Array containing hamiltonian cycle
22-
* else returns 1D array with value -1.
25+
* @param graph Adjacency matrix representing the graph G(V, E), where V is
26+
* the set of vertices and E is the set of edges.
27+
* @return An array representing the Hamiltonian cycle if found, otherwise an
28+
* array filled with -1 indicating no Hamiltonian cycle exists.
2329
*/
2430
public int[] findHamiltonianCycle(int[][] graph) {
31+
// Single vertex graph
32+
if (graph.length == 1) {
33+
return new int[] {0, 0};
34+
}
35+
2536
this.vertex = graph.length;
2637
this.cycle = new int[this.vertex + 1];
2738

28-
// Initialize path array with -1 value
29-
for (int i = 0; i < this.cycle.length; i++) {
30-
this.cycle[i] = -1;
31-
}
39+
// Initialize the cycle array with -1 to represent unvisited vertices
40+
Arrays.fill(this.cycle, -1);
3241

3342
this.graph = graph;
34-
3543
this.cycle[0] = 0;
3644
this.pathCount = 1;
3745
if (!isPathFound(0)) {
38-
for (int i = 0; i < this.cycle.length; i++) {
39-
this.cycle[i] = -1;
40-
}
46+
Arrays.fill(this.cycle, -1);
4147
} else {
4248
this.cycle[this.cycle.length - 1] = this.cycle[0];
4349
}
@@ -46,62 +52,55 @@ public int[] findHamiltonianCycle(int[][] graph) {
4652
}
4753

4854
/**
49-
* function to find paths recursively
50-
* Find paths recursively from given vertex
55+
* Recursively searches for a Hamiltonian cycle from the given vertex.
5156
*
52-
* @param vertex Vertex from which path is to be found
53-
* @returns true if path is found false otherwise
57+
* @param vertex The current vertex from which to explore paths.
58+
* @return {@code true} if a Hamiltonian cycle is found, otherwise {@code false}.
5459
*/
5560
public boolean isPathFound(int vertex) {
5661
boolean isLastVertexConnectedToStart = this.graph[vertex][0] == 1 && this.pathCount == this.vertex;
5762
if (isLastVertexConnectedToStart) {
5863
return true;
5964
}
6065

61-
/* all vertices selected but last vertex not linked to 0 **/
66+
// If all vertices are visited but the last vertex is not connected to the start
6267
if (this.pathCount == this.vertex) {
6368
return false;
6469
}
6570

6671
for (int v = 0; v < this.vertex; v++) {
67-
/* if connected **/
68-
if (this.graph[vertex][v] == 1) {
69-
/* add to path **/
70-
this.cycle[this.pathCount++] = v;
71-
72-
/* remove connection **/
72+
if (this.graph[vertex][v] == 1) { // Check if there is an edge
73+
this.cycle[this.pathCount++] = v; // Add the vertex to the cycle
7374
this.graph[vertex][v] = 0;
7475
this.graph[v][vertex] = 0;
7576

76-
/* if vertex not already selected solve recursively **/
77+
// Recursively attempt to complete the cycle
7778
if (!isPresent(v)) {
7879
return isPathFound(v);
7980
}
8081

81-
/* restore connection **/
82+
// Restore the edge if the path does not work
8283
this.graph[vertex][v] = 1;
8384
this.graph[v][vertex] = 1;
8485

85-
/* remove path **/
8686
this.cycle[--this.pathCount] = -1;
8787
}
8888
}
8989
return false;
9090
}
9191

9292
/**
93-
* function to check if path is already selected
94-
* Check if path is already selected
93+
* Checks if a vertex is already part of the current Hamiltonian path.
9594
*
96-
* @param vertex Starting vertex
95+
* @param vertex The vertex to check.
96+
* @return {@code true} if the vertex is already in the path, otherwise {@code false}.
9797
*/
9898
public boolean isPresent(int vertex) {
9999
for (int i = 0; i < pathCount - 1; i++) {
100100
if (cycle[i] == vertex) {
101101
return true;
102102
}
103103
}
104-
105104
return false;
106105
}
107106
}

src/main/java/com/thealgorithms/datastructures/graphs/JohnsonsAlgorithm.java

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,18 @@
2121
*/
2222
public final class JohnsonsAlgorithm {
2323

24-
// Constant representing infinity
2524
private static final double INF = Double.POSITIVE_INFINITY;
2625

27-
/**
28-
* A private constructor to hide the implicit public one.
29-
*/
3026
private JohnsonsAlgorithm() {
3127
}
3228

3329
/**
3430
* Executes Johnson's algorithm on the given graph.
31+
* Steps:
32+
* 1. Add a new vertex to the graph and run Bellman-Ford to compute modified weights
33+
* 2. t the graph using the modified weights
34+
* 3. Run Dijkstra's algorithm for each vertex to compute the shortest paths
35+
* The final result is a 2D array of shortest distances between all pairs of vertices.
3536
*
3637
* @param graph The input graph represented as an adjacency matrix.
3738
* @return A 2D array representing the shortest distances between all pairs of vertices.
@@ -40,13 +41,10 @@ public static double[][] johnsonAlgorithm(double[][] graph) {
4041
int numVertices = graph.length;
4142
double[][] edges = convertToEdgeList(graph);
4243

43-
// Step 1: Add a new vertex and run Bellman-Ford
4444
double[] modifiedWeights = bellmanFord(edges, numVertices);
4545

46-
// Step 2: Reweight the graph
4746
double[][] reweightedGraph = reweightGraph(graph, modifiedWeights);
4847

49-
// Step 3: Run Dijkstra's algorithm for each vertex
5048
double[][] shortestDistances = new double[numVertices][numVertices];
5149
for (int source = 0; source < numVertices; source++) {
5250
shortestDistances[source] = dijkstra(reweightedGraph, source, modifiedWeights);
@@ -74,7 +72,6 @@ public static double[][] convertToEdgeList(double[][] graph) {
7472
}
7573
}
7674

77-
// Convert the List to a 2D array
7875
return edgeList.toArray(new double[0][]);
7976
}
8077

@@ -89,7 +86,7 @@ public static double[][] convertToEdgeList(double[][] graph) {
8986
private static double[] bellmanFord(double[][] edges, int numVertices) {
9087
double[] dist = new double[numVertices + 1];
9188
Arrays.fill(dist, INF);
92-
dist[numVertices] = 0; // Distance to the new source vertex is 0
89+
dist[numVertices] = 0;
9390

9491
// Add edges from the new vertex to all original vertices
9592
double[][] allEdges = Arrays.copyOf(edges, edges.length + numVertices);

src/test/java/com/thealgorithms/datastructures/graphs/HamiltonianCycleTest.java

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
class HamiltonianCycleTest {
88

9-
private HamiltonianCycle hamiltonianCycle = new HamiltonianCycle();
9+
private final HamiltonianCycle hamiltonianCycle = new HamiltonianCycle();
1010

1111
@Test
1212
void testFindHamiltonianCycleShouldReturnHamiltonianCycle() {
@@ -36,4 +36,63 @@ void testFindHamiltonianCycleShouldReturnInfinityArray() {
3636

3737
assertArrayEquals(expectedArray, hamiltonianCycle.findHamiltonianCycle(inputArray));
3838
}
39+
40+
@Test
41+
void testSingleVertexGraph() {
42+
int[] expectedArray = {0, 0};
43+
int[][] inputArray = {{0}};
44+
45+
assertArrayEquals(expectedArray, hamiltonianCycle.findHamiltonianCycle(inputArray));
46+
}
47+
48+
@Test
49+
void testDisconnectedGraphShouldReturnInfinityArray() {
50+
int[] expectedArray = {-1, -1, -1, -1, -1};
51+
int[][] inputArray = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};
52+
53+
assertArrayEquals(expectedArray, hamiltonianCycle.findHamiltonianCycle(inputArray));
54+
}
55+
56+
@Test
57+
void testCompleteGraphShouldReturnHamiltonianCycle() {
58+
int[] expectedArray = {0, 1, 2, 3, 4, 0};
59+
int[][] inputArray = {
60+
{0, 1, 1, 1, 1},
61+
{1, 0, 1, 1, 1},
62+
{1, 1, 0, 1, 1},
63+
{1, 1, 1, 0, 1},
64+
{1, 1, 1, 1, 0},
65+
};
66+
67+
assertArrayEquals(expectedArray, hamiltonianCycle.findHamiltonianCycle(inputArray));
68+
}
69+
70+
@Test
71+
void testGraphWithNoEdgesShouldReturnInfinityArray() {
72+
int[] expectedArray = {-1, -1, -1, -1, -1, -1};
73+
74+
int[][] inputArray = {
75+
{0, 0, 0, 0, 0},
76+
{0, 0, 0, 0, 0},
77+
{0, 0, 0, 0, 0},
78+
{0, 0, 0, 0, 0},
79+
{0, 0, 0, 0, 0},
80+
};
81+
82+
assertArrayEquals(expectedArray, hamiltonianCycle.findHamiltonianCycle(inputArray));
83+
}
84+
85+
@Test
86+
void testLargeGraphWithHamiltonianCycle() {
87+
int[] expectedArray = {0, 1, 2, 3, 4, 0};
88+
int[][] inputArray = {
89+
{0, 1, 0, 1, 1},
90+
{1, 0, 1, 1, 0},
91+
{0, 1, 0, 1, 1},
92+
{1, 1, 1, 0, 1},
93+
{1, 0, 1, 1, 0},
94+
};
95+
96+
assertArrayEquals(expectedArray, hamiltonianCycle.findHamiltonianCycle(inputArray));
97+
}
3998
}

0 commit comments

Comments
 (0)