diff options
| author | Daniel Shaw <danielshaw1212@gmail.com> | 2017-07-24 16:11:22 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-07-24 16:11:22 -0700 |
| commit | b277b4dda3a2793fd59a6cca5de96f8bc65f1357 (patch) | |
| tree | 67299d7ae4d032948d4d65a2f494b61fac025b0a /toolsrc/include/vcpkg_Graphs.h | |
| parent | 3c841c6128ebfe8e99a372f2907bd985b533a799 (diff) | |
| parent | 59389ca236b005922cf1101f66c957d2396f6371 (diff) | |
| download | vcpkg-b277b4dda3a2793fd59a6cca5de96f8bc65f1357.tar.gz vcpkg-b277b4dda3a2793fd59a6cca5de96f8bc65f1357.zip | |
Merge pull request #1461 from Microsoft/create_install_tests
feature packages graph algorithm
Diffstat (limited to 'toolsrc/include/vcpkg_Graphs.h')
| -rw-r--r-- | toolsrc/include/vcpkg_Graphs.h | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/toolsrc/include/vcpkg_Graphs.h b/toolsrc/include/vcpkg_Graphs.h index 3c8c024c2..13c0a7136 100644 --- a/toolsrc/include/vcpkg_Graphs.h +++ b/toolsrc/include/vcpkg_Graphs.h @@ -1,6 +1,7 @@ #pragma once #include <unordered_map> +#include <unordered_set> namespace vcpkg::Graphs { @@ -63,4 +64,96 @@ namespace vcpkg::Graphs return sorted; } + + template<class V> + struct GraphAdjacencyProvider final : AdjacencyProvider<V, V> + { + const std::unordered_map<V, std::unordered_set<V>>& vertices; + + GraphAdjacencyProvider(const std::unordered_map<V, std::unordered_set<V>>& vertices) : vertices(vertices) {} + + std::vector<V> adjacency_list(const V& vertex) const override + { + const std::unordered_set<V>& as_set = this->vertices.at(vertex); + return std::vector<V>(as_set.cbegin(), as_set.cend()); // TODO: Avoid redundant copy + } + + V load_vertex_data(const V& vertex) const override { return vertex; } + }; + + template<class V> + struct Graph + { + public: + void add_vertex(V v) { this->vertices[v]; } + + // TODO: Change with iterators + void add_vertices(const std::vector<V>& vs) + { + for (const V& v : vs) + { + this->vertices[v]; + } + } + + void add_edge(V u, V v) + { + this->vertices[v]; + this->vertices[u].insert(v); + } + + std::vector<V> topological_sort() const + { + GraphAdjacencyProvider<V> adjacency_provider{this->vertices}; + std::unordered_map<V, int> indegrees = count_indegrees(); + + std::vector<V> sorted; + sorted.reserve(indegrees.size()); + + std::unordered_map<V, ExplorationStatus> exploration_status; + exploration_status.reserve(indegrees.size()); + + for (auto& pair : indegrees) + { + if (pair.second == 0) // Starting from vertices with indegree == 0. Not required. + { + V vertex = pair.first; + topological_sort_internal(vertex, adjacency_provider, exploration_status, sorted); + } + } + + return sorted; + } + + std::unordered_map<V, int> count_indegrees() const + { + std::unordered_map<V, int> indegrees; + + for (auto& pair : this->vertices) + { + indegrees[pair.first]; + for (V neighbour : pair.second) + { + ++indegrees[neighbour]; + } + } + + return indegrees; + } + + const std::unordered_map<V, std::unordered_set<V>>& adjacency_list() const { return this->vertices; } + std::vector<V> vertex_list() const + { + // why no &? it returns 0 + std::vector<V> vertex_list; + for (const auto& vertex : this->vertices) + { + vertex_list.emplace_back(vertex.first); + } + return vertex_list; + } + + private: + std::unordered_map<V, std::unordered_set<V>> vertices; + }; } |
