Skip to content

Commit

Permalink
Modified: use Allocator to construct Weight with INFINITE
Browse files Browse the repository at this point in the history
  • Loading branch information
huanmie committed Jul 20, 2022
1 parent c254021 commit bc63ee5
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 23 deletions.
3 changes: 3 additions & 0 deletions Graph/Example.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <cassert>
#include <limits>
#include <numeric>
#include <algorithm>
Expand All @@ -20,12 +21,14 @@ int main()
out_path.clear();
graph.RemoveEdge("C", "D");
bool not_exist = graph.AddEdge("C", "D") == graph.INFINITE;
assert(not_exist);
graph.GetOutPath("C", [&out_path](auto&& new_path) {out_path.push_back(new_path); return true; });
auto in_path = graph.GetInPath("B");
in_path.clear();
graph.GetInPath("B", [&in_path](auto&& new_path) {in_path.push_back(new_path); return true; });
auto weight = graph.AddEdge("C", "E");
not_exist = graph.AddEdge("C", "T") == graph.INFINITE;
assert(not_exist);
auto result = graph.GetBestPath("A", "E");
return 0;
}
65 changes: 42 additions & 23 deletions Graph/Graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,64 @@
template<typename Vertex, typename Weight = int>
class Graph
{
using AdjacencyMatrix = std::unordered_map<Vertex, std::unordered_map<Vertex, Weight>>;
using PathType = AdjacencyMatrix::mapped_type::value_type;
using PathType = std::unordered_map<Vertex, Weight>::value_type;

template<typename T>
struct Allocator :public std::allocator<T>
{
void construct(std::same_as<PathType> auto* p, auto&& tag, auto&& key_tuple, auto&& value_tuple)
{
assert(std::tuple_size_v<std::remove_reference_t<decltype(value_tuple)>> == 0);
::new((void*)p) PathType(std::forward<decltype(tag)>(tag),
std::forward<decltype(key_tuple)>(key_tuple),
std::forward_as_tuple(Graph<Vertex, Weight>::INFINITE));
}

template<class U>
void destroy(U* p)
{
p->~U();
}

template<typename U>
struct rebind
{
using type = Allocator<U>;
};
};

using AdjacencyMatrix = std::unordered_map<Vertex, std::unordered_map<Vertex, Weight, std::hash<Vertex>, std::equal_to<Vertex>, Allocator<PathType>>>;
AdjacencyMatrix matrix;

using Compare = bool(*)(const Weight&, const Weight&);
std::function<std::vector<PathType>(const Vertex&, const Vertex&, Compare)> best_path;

public:
const Weight INFINITE;
static Weight INFINITE;

Graph(const Weight& Infinite) :INFINITE(Infinite) {}
Graph(const Weight& Infinite) { INFINITE = Infinite; }

Graph(const Weight& Infinite, auto&&... rests) :INFINITE(Infinite) { Construct(std::forward<decltype(rests)>(rests)...); }
Graph(const Weight& Infinite, auto&&... rests)
{
INFINITE = Infinite;
Construct(std::forward<decltype(rests)>(rests)...);
}

Graph(const Weight& Infinite, std::initializer_list<std::tuple<Vertex, Weight, Vertex>> list) :INFINITE(Infinite)
Graph(const Weight& Infinite, std::initializer_list<std::tuple<Vertex, Weight, Vertex>> list)
{
INFINITE = Infinite;
for (auto&& element : list)
AddEdge(std::get<0>(element), std::get<2>(element)) = std::get<1>(element);
}

Weight& AddEdge(const Vertex& begin, const Vertex& end)
{
if (matrix.contains(begin) && matrix[begin].contains(end))
return matrix[begin][end];
else
{
Weight& weight = matrix[begin][end];
weight = INFINITE;
return weight;
}
return matrix[begin][end];
}

Weight& AddEdge(Vertex&& begin, Vertex&& end)
{
if (matrix.contains(begin) && matrix[begin].contains(end))
return matrix[begin][end];
else
{
Weight& weight = matrix[std::move(begin)][std::move(end)];
weight = INFINITE;
return weight;
}
return matrix[std::move(begin)][std::move(end)];
}

void RemoveEdge(const Vertex& begin, const Vertex& end)
Expand Down Expand Up @@ -147,4 +163,7 @@ class Graph
IterateGraph(results, target, current_path, { vertex, weight }, set);
}
}
};
};

template<typename Vertex, typename Weight>
inline Weight Graph<Vertex, Weight>::INFINITE;

0 comments on commit bc63ee5

Please sign in to comment.