Skip to content

Commit 3385ccd

Browse files
authored
Merge pull request deutranium#249 from etzl/welshpowell
add c++ implementation of welsh powell algorithm
2 parents bf4040a + ee723fb commit 3385ccd

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#include <iostream>
2+
#include <vector>
3+
#include <algorithm>
4+
#include <list>
5+
#include <unordered_set>
6+
7+
8+
struct Vertex {
9+
char id; // An upper-case character representing the node label
10+
int degree;
11+
std::vector<char> adj; // a list of all the adjacent nodes: with their letters
12+
int label; // *color*
13+
14+
/** Add edge to undirected graph
15+
* \param node Another node to connect to
16+
* \return Void
17+
*/
18+
void addEdge(Vertex& node)
19+
{
20+
adj.push_back(node.id);
21+
degree++;
22+
23+
node.adj.push_back(id);
24+
node.degree++;
25+
}
26+
27+
/** Check whether current vertex is connected to the target vertex
28+
* \param target Vertex to check against
29+
* \return True if they're connected, false otherwise
30+
*/
31+
bool isConnected(const Vertex& target)
32+
{
33+
return std::find(adj.begin(), adj.end(), target.id) != adj.end();
34+
}
35+
};
36+
37+
struct Graph {
38+
// adding/deleting elements is more efficient
39+
std::list<Vertex> vertices;
40+
41+
void addVertex(Vertex node)
42+
{
43+
vertices.push_back(node);
44+
}
45+
void addVertex(Vertex&& node)
46+
{
47+
vertices.push_back(node);
48+
}
49+
};
50+
51+
void welshPowell(Graph& graph)
52+
{
53+
// sort vertices in descending order
54+
graph.vertices.sort([](const Vertex& a, const Vertex& b) -> bool {
55+
return a.degree > b.degree;
56+
});
57+
58+
std::list<Vertex*> unlabeledVertices;
59+
for (auto& vertex: graph.vertices) {
60+
unlabeledVertices.push_back(&vertex);
61+
}
62+
63+
int label = 1;
64+
for (auto iter = unlabeledVertices.begin(); iter != unlabeledVertices.end(); ++label) {
65+
(*iter)->label = label;
66+
67+
/** a set of all vertices with the same color, all operations has a
68+
* constant time of O(1) on average
69+
*/
70+
std::unordered_set<Vertex*> currentLabelVertices;
71+
currentLabelVertices.insert(*iter);
72+
73+
// check if we can label any other vertex with the current color
74+
auto nestedIter = iter; nestedIter++;
75+
for (; nestedIter != unlabeledVertices.end(); ) {
76+
// checking current vertex against any other colored vertex
77+
if (std::none_of(currentLabelVertices.begin(), currentLabelVertices.end(),
78+
[=](const Vertex* v){ return (*nestedIter)->isConnected(*v); })) {
79+
(*nestedIter)->label = label;
80+
currentLabelVertices.insert(*nestedIter);
81+
82+
nestedIter = unlabeledVertices.erase(nestedIter);
83+
}
84+
else {
85+
nestedIter++;
86+
}
87+
}
88+
89+
iter = unlabeledVertices.erase(iter);
90+
}
91+
}
92+
93+
int main()
94+
{
95+
Graph graph {{
96+
{'A', 3, {'B', 'C', 'D'}},
97+
{'B', 2, {'A', 'D'}},
98+
{'C', 2, {'A', 'D'}},
99+
{'D', 3, {'A', 'B', 'C'}}
100+
}};
101+
102+
welshPowell(graph);
103+
104+
for (const auto& v: graph.vertices) {
105+
std::cout << v.id << "-->" << v.label << '\n';
106+
}
107+
return 0;
108+
}

0 commit comments

Comments
 (0)