1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
|
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <stdexcept>
using adjacency_node = std::pair<std::string const, std::vector<std::string>>;
using adjacency_table = std::unordered_map<std::string, std::vector<std::string>>;
// See: https://en.wikipedia.org/wiki/Topological_sorting
std::vector<adjacency_node> topological_sort(adjacency_table t)
{
enum class mark { none, temporary, permanent };
struct helper
{
explicit helper(adjacency_table&& t)
: table(std::move(t))
{}
adjacency_table table;
std::unordered_map<std::string, mark> marks;
std::vector<adjacency_node> result;
void visit(adjacency_node const& n)
{
auto const& [name, outgoing_edges] = n;
if (marks[name] == mark::permanent) return;
if (marks[name] == mark::temporary) throw std::invalid_argument{ "cyclic graph" };
marks[name] = mark::temporary;
for (auto const& edge : outgoing_edges)
visit({ edge, table[edge] });
marks[name] = mark::permanent;
result.push_back(n);
}
std::vector<adjacency_node> sort()
{
for (auto& m : table) if (marks[m.first] == mark::none) visit(m);
return result;
}
} helper{ std::move(t) };
return helper.sort();
}
int main()
{
adjacency_table dependencies
{
adjacency_node{"pants", {"shirt", "underclothes"}},
adjacency_node{"shirt", {"underclothes"}},
adjacency_node{"shoes", {"pants", "socks"}},
adjacency_node{"tie", {"shirt"}},
adjacency_node{"jacket", {"shirt", "tie", "belt", "pants"}},
adjacency_node{"belt", {"pants", "shirt"}}
};
for (auto node : topological_sort(dependencies))
std::cout << node.first << '\n';
}
|