55import java .util .HashSet ;
66import java .util .stream .IntStream ;
77
8- /*
9- * The Welsh-Powell algorithm is a graph coloring algorithm
10- * used for coloring a graph with the minimum number of colors.
11- * https://en.wikipedia.org/wiki/Graph_coloring
8+ /**
9+ * The Welsh-Powell algorithm is a graph coloring algorithm that aims to color a graph
10+ * using the minimum number of colors such that no two adjacent vertices share the same color.
11+ *
12+ * <p>
13+ * The algorithm works by:
14+ * <ol>
15+ * <li>Sorting the vertices in descending order based on their degrees (number of edges connected).</li>
16+ * <li>Iterating through each vertex and assigning it the smallest available color that has not been used by its adjacent vertices.</li>
17+ * <li>Coloring adjacent vertices with the same color is avoided.</li>
18+ * </ol>
19+ * </p>
20+ *
21+ * <p>
22+ * For more information, see <a href="https://en.wikipedia.org/wiki/Graph_coloring">Graph Coloring</a>.
23+ * </p>
1224 */
13-
1425public final class WelshPowell {
15- private static final int BLANK_COLOR = -1 ; // Representing uncolored state
26+ private static final int BLANK_COLOR = -1 ; // Constant representing an uncolored state
1627
1728 private WelshPowell () {
1829 }
1930
31+ /**
32+ * Represents a graph using an adjacency list.
33+ */
2034 static final class Graph {
21- private HashSet <Integer >[] adjacencyLists ;
22-
35+ private final HashSet <Integer >[] adjacencyLists ;
36+
37+ /**
38+ * Initializes a graph with a specified number of vertices.
39+ *
40+ * @param vertices the number of vertices in the graph
41+ * @throws IllegalArgumentException if the number of vertices is negative
42+ */
2343 private Graph (int vertices ) {
2444 if (vertices < 0 ) {
2545 throw new IllegalArgumentException ("Number of vertices cannot be negative" );
@@ -29,6 +49,13 @@ private Graph(int vertices) {
2949 Arrays .setAll (adjacencyLists , i -> new HashSet <>());
3050 }
3151
52+ /**
53+ * Adds an edge between two vertices in the graph.
54+ *
55+ * @param nodeA one end of the edge
56+ * @param nodeB the other end of the edge
57+ * @throws IllegalArgumentException if the vertices are out of bounds or if a self-loop is attempted
58+ */
3259 private void addEdge (int nodeA , int nodeB ) {
3360 validateVertex (nodeA );
3461 validateVertex (nodeB );
@@ -39,21 +66,46 @@ private void addEdge(int nodeA, int nodeB) {
3966 adjacencyLists [nodeB ].add (nodeA );
4067 }
4168
69+ /**
70+ * Validates that the vertex index is within the bounds of the graph.
71+ *
72+ * @param vertex the index of the vertex to validate
73+ * @throws IllegalArgumentException if the vertex is out of bounds
74+ */
4275 private void validateVertex (int vertex ) {
4376 if (vertex < 0 || vertex >= getNumVertices ()) {
4477 throw new IllegalArgumentException ("Vertex " + vertex + " is out of bounds" );
4578 }
4679 }
4780
81+ /**
82+ * Returns the adjacency list for a specific vertex.
83+ *
84+ * @param vertex the index of the vertex
85+ * @return the set of adjacent vertices
86+ */
4887 HashSet <Integer > getAdjacencyList (int vertex ) {
4988 return adjacencyLists [vertex ];
5089 }
5190
91+ /**
92+ * Returns the number of vertices in the graph.
93+ *
94+ * @return the number of vertices
95+ */
5296 int getNumVertices () {
5397 return adjacencyLists .length ;
5498 }
5599 }
56100
101+ /**
102+ * Creates a graph with the specified number of vertices and edges.
103+ *
104+ * @param numberOfVertices the total number of vertices
105+ * @param listOfEdges a 2D array representing edges where each inner array contains two vertex indices
106+ * @return a Graph object representing the created graph
107+ * @throws IllegalArgumentException if the edge array is invalid or vertices are out of bounds
108+ */
57109 public static Graph makeGraph (int numberOfVertices , int [][] listOfEdges ) {
58110 Graph graph = new Graph (numberOfVertices );
59111 for (int [] edge : listOfEdges ) {
@@ -65,6 +117,12 @@ public static Graph makeGraph(int numberOfVertices, int[][] listOfEdges) {
65117 return graph ;
66118 }
67119
120+ /**
121+ * Finds the coloring of the given graph using the Welsh-Powell algorithm.
122+ *
123+ * @param graph the input graph to color
124+ * @return an array of integers where each index represents a vertex and the value represents the color assigned
125+ */
68126 public static int [] findColoring (Graph graph ) {
69127 int [] colors = initializeColors (graph .getNumVertices ());
70128 Integer [] sortedVertices = getSortedNodes (graph );
@@ -83,30 +141,70 @@ public static int[] findColoring(Graph graph) {
83141 return colors ;
84142 }
85143
144+ /**
145+ * Helper method to check if a color is unassigned
146+ *
147+ * @param color the color to check
148+ * @return {@code true} if the color is unassigned, {@code false} otherwise
149+ */
86150 private static boolean isBlank (int color ) {
87151 return color == BLANK_COLOR ;
88152 }
89153
154+ /**
155+ * Checks if a vertex has adjacent colored vertices
156+ *
157+ * @param graph the input graph
158+ * @param vertex the vertex to check
159+ * @param colors the array of colors assigned to the vertices
160+ * @return {@code true} if the vertex has adjacent colored vertices, {@code false} otherwise
161+ */
90162 private static boolean isAdjacentToColored (Graph graph , int vertex , int [] colors ) {
91163 return graph .getAdjacencyList (vertex ).stream ().anyMatch (otherVertex -> !isBlank (colors [otherVertex ]));
92164 }
93165
166+ /**
167+ * Initializes the colors array with blank color
168+ *
169+ * @param numberOfVertices the number of vertices in the graph
170+ * @return an array of integers representing the colors assigned to the vertices
171+ */
94172 private static int [] initializeColors (int numberOfVertices ) {
95173 int [] colors = new int [numberOfVertices ];
96174 Arrays .fill (colors , BLANK_COLOR );
97175 return colors ;
98176 }
99177
178+ /**
179+ * Sorts the vertices by their degree in descending order
180+ *
181+ * @param graph the input graph
182+ * @return an array of integers representing the vertices sorted by degree
183+ */
100184 private static Integer [] getSortedNodes (final Graph graph ) {
101185 return IntStream .range (0 , graph .getNumVertices ()).boxed ().sorted (Comparator .comparingInt (v -> - graph .getAdjacencyList (v ).size ())).toArray (Integer [] ::new );
102186 }
103187
188+ /**
189+ * Computes the colors already used by the adjacent vertices
190+ *
191+ * @param graph the input graph
192+ * @param vertex the vertex to check
193+ * @param colors the array of colors assigned to the vertices
194+ * @return an array of booleans representing the colors used by the adjacent vertices
195+ */
104196 private static boolean [] computeUsedColors (final Graph graph , final int vertex , final int [] colors ) {
105197 boolean [] usedColors = new boolean [graph .getNumVertices ()];
106198 graph .getAdjacencyList (vertex ).stream ().map (neighbor -> colors [neighbor ]).filter (color -> !isBlank (color )).forEach (color -> usedColors [color ] = true );
107199 return usedColors ;
108200 }
109201
202+ /**
203+ * Finds the first unused color
204+ *
205+ * @param usedColors the array of colors used by the adjacent vertices
206+ * @return the first unused color
207+ */
110208 private static int firstUnusedColor (boolean [] usedColors ) {
111209 return IntStream .range (0 , usedColors .length ).filter (color -> !usedColors [color ]).findFirst ().getAsInt ();
112210 }
0 commit comments