diff --git a/src/main/java/com/thealgorithms/datastructures/graphs/WelshPowell.java b/src/main/java/com/thealgorithms/datastructures/graphs/WelshPowell.java
index 0981638d4903..26ca97736fe9 100644
--- a/src/main/java/com/thealgorithms/datastructures/graphs/WelshPowell.java
+++ b/src/main/java/com/thealgorithms/datastructures/graphs/WelshPowell.java
@@ -5,21 +5,41 @@
import java.util.HashSet;
import java.util.stream.IntStream;
-/*
- * The Welsh-Powell algorithm is a graph coloring algorithm
- * used for coloring a graph with the minimum number of colors.
- * https://en.wikipedia.org/wiki/Graph_coloring
+/**
+ * The Welsh-Powell algorithm is a graph coloring algorithm that aims to color a graph
+ * using the minimum number of colors such that no two adjacent vertices share the same color.
+ *
+ *
+ * The algorithm works by:
+ *
+ * - Sorting the vertices in descending order based on their degrees (number of edges connected).
+ * - Iterating through each vertex and assigning it the smallest available color that has not been used by its adjacent vertices.
+ * - Coloring adjacent vertices with the same color is avoided.
+ *
+ *
+ *
+ *
+ * For more information, see Graph Coloring.
+ *
*/
-
public final class WelshPowell {
- private static final int BLANK_COLOR = -1; // Representing uncolored state
+ private static final int BLANK_COLOR = -1; // Constant representing an uncolored state
private WelshPowell() {
}
+ /**
+ * Represents a graph using an adjacency list.
+ */
static final class Graph {
- private HashSet[] adjacencyLists;
-
+ private final HashSet[] adjacencyLists;
+
+ /**
+ * Initializes a graph with a specified number of vertices.
+ *
+ * @param vertices the number of vertices in the graph
+ * @throws IllegalArgumentException if the number of vertices is negative
+ */
private Graph(int vertices) {
if (vertices < 0) {
throw new IllegalArgumentException("Number of vertices cannot be negative");
@@ -29,6 +49,13 @@ private Graph(int vertices) {
Arrays.setAll(adjacencyLists, i -> new HashSet<>());
}
+ /**
+ * Adds an edge between two vertices in the graph.
+ *
+ * @param nodeA one end of the edge
+ * @param nodeB the other end of the edge
+ * @throws IllegalArgumentException if the vertices are out of bounds or if a self-loop is attempted
+ */
private void addEdge(int nodeA, int nodeB) {
validateVertex(nodeA);
validateVertex(nodeB);
@@ -39,21 +66,46 @@ private void addEdge(int nodeA, int nodeB) {
adjacencyLists[nodeB].add(nodeA);
}
+ /**
+ * Validates that the vertex index is within the bounds of the graph.
+ *
+ * @param vertex the index of the vertex to validate
+ * @throws IllegalArgumentException if the vertex is out of bounds
+ */
private void validateVertex(int vertex) {
if (vertex < 0 || vertex >= getNumVertices()) {
throw new IllegalArgumentException("Vertex " + vertex + " is out of bounds");
}
}
+ /**
+ * Returns the adjacency list for a specific vertex.
+ *
+ * @param vertex the index of the vertex
+ * @return the set of adjacent vertices
+ */
HashSet getAdjacencyList(int vertex) {
return adjacencyLists[vertex];
}
+ /**
+ * Returns the number of vertices in the graph.
+ *
+ * @return the number of vertices
+ */
int getNumVertices() {
return adjacencyLists.length;
}
}
+ /**
+ * Creates a graph with the specified number of vertices and edges.
+ *
+ * @param numberOfVertices the total number of vertices
+ * @param listOfEdges a 2D array representing edges where each inner array contains two vertex indices
+ * @return a Graph object representing the created graph
+ * @throws IllegalArgumentException if the edge array is invalid or vertices are out of bounds
+ */
public static Graph makeGraph(int numberOfVertices, int[][] listOfEdges) {
Graph graph = new Graph(numberOfVertices);
for (int[] edge : listOfEdges) {
@@ -65,6 +117,12 @@ public static Graph makeGraph(int numberOfVertices, int[][] listOfEdges) {
return graph;
}
+ /**
+ * Finds the coloring of the given graph using the Welsh-Powell algorithm.
+ *
+ * @param graph the input graph to color
+ * @return an array of integers where each index represents a vertex and the value represents the color assigned
+ */
public static int[] findColoring(Graph graph) {
int[] colors = initializeColors(graph.getNumVertices());
Integer[] sortedVertices = getSortedNodes(graph);
@@ -83,30 +141,70 @@ public static int[] findColoring(Graph graph) {
return colors;
}
+ /**
+ * Helper method to check if a color is unassigned
+ *
+ * @param color the color to check
+ * @return {@code true} if the color is unassigned, {@code false} otherwise
+ */
private static boolean isBlank(int color) {
return color == BLANK_COLOR;
}
+ /**
+ * Checks if a vertex has adjacent colored vertices
+ *
+ * @param graph the input graph
+ * @param vertex the vertex to check
+ * @param colors the array of colors assigned to the vertices
+ * @return {@code true} if the vertex has adjacent colored vertices, {@code false} otherwise
+ */
private static boolean isAdjacentToColored(Graph graph, int vertex, int[] colors) {
return graph.getAdjacencyList(vertex).stream().anyMatch(otherVertex -> !isBlank(colors[otherVertex]));
}
+ /**
+ * Initializes the colors array with blank color
+ *
+ * @param numberOfVertices the number of vertices in the graph
+ * @return an array of integers representing the colors assigned to the vertices
+ */
private static int[] initializeColors(int numberOfVertices) {
int[] colors = new int[numberOfVertices];
Arrays.fill(colors, BLANK_COLOR);
return colors;
}
+ /**
+ * Sorts the vertices by their degree in descending order
+ *
+ * @param graph the input graph
+ * @return an array of integers representing the vertices sorted by degree
+ */
private static Integer[] getSortedNodes(final Graph graph) {
return IntStream.range(0, graph.getNumVertices()).boxed().sorted(Comparator.comparingInt(v -> - graph.getAdjacencyList(v).size())).toArray(Integer[] ::new);
}
+ /**
+ * Computes the colors already used by the adjacent vertices
+ *
+ * @param graph the input graph
+ * @param vertex the vertex to check
+ * @param colors the array of colors assigned to the vertices
+ * @return an array of booleans representing the colors used by the adjacent vertices
+ */
private static boolean[] computeUsedColors(final Graph graph, final int vertex, final int[] colors) {
boolean[] usedColors = new boolean[graph.getNumVertices()];
graph.getAdjacencyList(vertex).stream().map(neighbor -> colors[neighbor]).filter(color -> !isBlank(color)).forEach(color -> usedColors[color] = true);
return usedColors;
}
+ /**
+ * Finds the first unused color
+ *
+ * @param usedColors the array of colors used by the adjacent vertices
+ * @return the first unused color
+ */
private static int firstUnusedColor(boolean[] usedColors) {
return IntStream.range(0, usedColors.length).filter(color -> !usedColors[color]).findFirst().getAsInt();
}
diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/WelshPowellTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/WelshPowellTest.java
index b37657db5c05..f45c4e10be56 100644
--- a/src/test/java/com/thealgorithms/datastructures/graphs/WelshPowellTest.java
+++ b/src/test/java/com/thealgorithms/datastructures/graphs/WelshPowellTest.java
@@ -34,26 +34,25 @@ void testCompleteGraph() {
assertEquals(3, countDistinctColors(colors));
}
- // The following test originates from the following website : https://www.geeksforgeeks.org/welsh-powell-graph-colouring-algorithm/
@Test
void testComplexGraph() {
int[][] edges = {
- {0, 7}, // A-H
- {0, 1}, // A-B
- {1, 3}, // B-D
- {2, 3}, // C-D
- {3, 8}, // D-I
- {3, 10}, // D-K
- {4, 10}, // E-K
- {4, 5}, // E-F
- {5, 6}, // F-G
- {6, 10}, // G-K
- {6, 7}, // G-H
- {7, 8}, // H-I
- {7, 9}, // H-J
- {7, 10}, // H-K
- {8, 9}, // I-J
- {9, 10}, // J-K
+ {0, 7},
+ {0, 1},
+ {1, 3},
+ {2, 3},
+ {3, 8},
+ {3, 10},
+ {4, 10},
+ {4, 5},
+ {5, 6},
+ {6, 10},
+ {6, 7},
+ {7, 8},
+ {7, 9},
+ {7, 10},
+ {8, 9},
+ {9, 10},
};
final var graph = WelshPowell.makeGraph(11, edges); // 11 vertices from A (0) to K (10)
@@ -86,24 +85,35 @@ void testInvalidEdgeArray() {
@Test
void testWithPreColoredVertex() {
- // Create a linear graph with 4 vertices and edges connecting them in sequence
final var graph = WelshPowell.makeGraph(4, new int[][] {{0, 1}, {1, 2}, {2, 3}});
-
- // Apply the Welsh-Powell coloring algorithm to the graph
int[] colors = WelshPowell.findColoring(graph);
-
- // Validate that the coloring is correct (no two adjacent vertices have the same color)
assertTrue(isColoringValid(graph, colors));
-
- // Check if the algorithm has used at least 2 colors (expected for a linear graph)
assertTrue(countDistinctColors(colors) >= 2);
-
- // Verify that all vertices have been assigned a color
for (int color : colors) {
assertTrue(color >= 0);
}
}
+ @Test
+ void testLargeGraph() {
+ int[][] edges = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 0}, {6, 7}, {7, 8}, {8, 6}, {9, 10}, {10, 11}, {11, 9}, {12, 13}, {13, 14}, {14, 15}};
+
+ final var graph = WelshPowell.makeGraph(16, edges); // 16 vertices
+ int[] colors = WelshPowell.findColoring(graph);
+ assertTrue(isColoringValid(graph, colors));
+ assertEquals(3, countDistinctColors(colors)); // Expecting a maximum of 3 colors
+ }
+
+ @Test
+ void testStarGraph() {
+ int[][] edges = {{0, 1}, {0, 2}, {0, 3}, {0, 4}};
+
+ final var graph = WelshPowell.makeGraph(5, edges); // 5 vertices in a star formation
+ int[] colors = WelshPowell.findColoring(graph);
+ assertTrue(isColoringValid(graph, colors));
+ assertEquals(2, countDistinctColors(colors)); // Star graph can be colored with 2 colors
+ }
+
private boolean isColoringValid(Graph graph, int[] colors) {
if (Arrays.stream(colors).anyMatch(n -> n < 0)) {
return false;
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy