GraphLib
Bearbeitung der Aufgabe Mini Graph Library für OOP WiSe 2023/24
Loading...
Searching...
No Matches
adjacency_list.h
Go to the documentation of this file.
1#ifndef GRAPHLIB_INTERNAL_ADJACENCY_LIST_H
2#define GRAPHLIB_INTERNAL_ADJACENCY_LIST_H
3
4#include <algorithm>
5#include <cassert>
6#include <iterator>
7#include <ostream>
8#include <set>
9#include <unordered_map>
10#include <unordered_set>
11
13
22
23namespace GraphLib::Internal {
24
25template <valid_id_type I, valid_edge_type<I> E>
26class AdjacencyList;
27
28template <typename I, typename E>
29std::ostream& operator<<(std::ostream& os, const AdjacencyList<I, E>& adj_list);
30
38template <valid_id_type I, valid_edge_type<I> E>
40public:
41 using id_type = I;
42 using edge_type = E;
43
50 bool has_node_id(const id_type node_id) const
51 {
52 return adj_map_.contains(node_id);
53 }
54
60 std::unordered_set<id_type> get_node_ids() const
61 {
62 auto keys = std::unordered_set<id_type> {};
63 std::transform(adj_map_.begin(), adj_map_.end(), std::inserter(keys, keys.end()),
64 [](const auto& pair) { return pair.first; });
65 return keys;
66 }
67
75 std::set<id_type> get_neighboring_node_ids(const id_type node_id) const
76 {
77 assert(has_node_id(node_id));
78
79 auto edges = adj_map_.at(node_id);
80 auto neighbor_ids = std::set<id_type> {};
81 std::transform(edges.begin(), edges.end(), std::inserter(neighbor_ids, neighbor_ids.end()),
82 [](const edge_type edge) { return edge.node_id; });
83 return neighbor_ids;
84 }
85
93 void add_node_id(const id_type node_id)
94 {
95 assert(!has_node_id(node_id));
96
97 adj_map_.insert({node_id, std::set<edge_type> {}});
98 }
99
107 void remove_node_id(const id_type node_id)
108 {
109 assert(has_node_id(node_id));
110
111 for (auto& [_, edge_set] : adj_map_) {
112 for (auto it = edge_set.begin(); it != edge_set.end();) {
113 if (it->node_id == node_id)
114 it = edge_set.erase(it);
115 else
116 ++it;
117 }
118 }
119
120 adj_map_.erase(node_id);
121 }
122
130 bool has_edge(const id_type from_id, const id_type to_id) const
131 {
132 assert(has_node_id(from_id) && has_node_id(to_id));
133
134 auto it = std::find_if(adj_map_.at(from_id).begin(), adj_map_.at(from_id).end(),
135 [to_id](const edge_type& edge) { return edge.node_id == to_id; });
136 return it != adj_map_.at(from_id).end();
137 }
138
147 edge_type get_edge(const id_type from_id, const id_type to_id) const
148 {
149 assert(has_edge(from_id, to_id));
150
151 auto it = std::find_if(adj_map_.at(from_id).begin(), adj_map_.at(from_id).end(),
152 [to_id](const edge_type& edge) { return edge.node_id == to_id; });
153 return *it;
154 }
155
162 std::set<edge_type> get_edges(const id_type from_id) const
163 {
164 assert(has_node_id(from_id));
165
166 return adj_map_.at(from_id);
167 }
168
176 void add_edge(const id_type from_id, edge_type edge)
177 {
178 assert(has_node_id(from_id) && has_node_id(edge.node_id) && !has_edge(from_id, edge.node_id));
179
180 adj_map_.at(from_id).insert(edge);
181 }
182
189 void remove_edge(const id_type from_id, const id_type to_id)
190 {
191 assert(has_edge(from_id, to_id));
192
193 adj_map_.at(from_id).erase(get_edge(from_id, to_id));
194 }
195
201 std::size_t node_id_count() const
202 {
203 return get_node_ids().size();
204 }
205
213 std::size_t edge_count() const
214 {
215 std::size_t count {0};
216 for (const auto& [_, edge_set] : adj_map_)
217 count += edge_set.size();
218 return count;
219 }
220
229 constexpr bool operator==(const AdjacencyList& other) const
230 {
231 return adj_map_ == other.adj_map_;
232 }
233
248 template <typename D>
250 void print_with_data_map(std::ostream& os, const std::unordered_map<I, D> data_map) const
251 {
252 for (const auto& [node, edges] : adj_map_) {
253 D node_value = data_map.at(node);
254 os << node_value << ": [";
255 bool first = true;
256 for (const auto& edge : edges) {
257 if (!first)
258 os << ", ";
259 edge.print_with_data(os, data_map.at(edge.node_id));
260 first = false;
261 }
262 os << "]\n";
263 }
264 }
265
266private:
267 std::unordered_map<id_type, std::set<edge_type>> adj_map_ {};
269 std::ostream& os,
270 const AdjacencyList<id_type, edge_type>& adj_list);
271};
272
289template <typename I, typename E>
290std::ostream& operator<<(std::ostream& os, const AdjacencyList<I, E>& adj_list)
291{
292 for (const auto& [node, edges] : adj_list.adj_map_) {
293 os << node << ": [";
294 bool first = true;
295 for (const auto& edge : edges) {
296 if (!first)
297 os << ", ";
298 os << edge;
299 first = false;
300 }
301 os << "]\n";
302 }
303 return os;
304}
305
306} // namespace GraphLib::Internal
307
308#endif
std::ostream & operator<<(std::ostream &os, const Graph< D, I, E > &graph)
Stream insertion operator for any valid graph type.
Represents a directed (by nature) Adjacency List Graph Structure.
void print_with_data_map(std::ostream &os, const std::unordered_map< I, D > data_map) const
Outputs the adjacency map to the given output stream, but with data instead of IDs.
std::unordered_set< id_type > get_node_ids() const
Retrieves all node IDs present in the graph.
I id_type
Alias for the node ID type.
void add_node_id(const id_type node_id)
Adds a node with the specified ID to the graph.
bool has_node_id(const id_type node_id) const
Checks if a node with given ID exists in the graph.
std::set< edge_type > get_edges(const id_type from_id) const
Retrieves all edges outgoing from the specified node.
constexpr bool operator==(const AdjacencyList &other) const
Equality comparison operator.
edge_type get_edge(const id_type from_id, const id_type to_id) const
Retrieves the edge from from_id to to_id.
bool has_edge(const id_type from_id, const id_type to_id) const
Checks if an edge from from_id to to_id exists.
void add_edge(const id_type from_id, edge_type edge)
Adds an edge from from_id to the edge's target node.
void remove_node_id(const id_type node_id)
Removes the node with the specified ID and all edges pointing to it.
void remove_edge(const id_type from_id, const id_type to_id)
Removes the edge from from_id to to_id.
std::unordered_map< id_type, std::set< edge_type > > adj_map_
Maps node IDs to their outgoing edges.
std::set< id_type > get_neighboring_node_ids(const id_type node_id) const
Gets the neighboring node IDs of a given node.
friend std::ostream & operator(std::ostream &os, const AdjacencyList< id_type, edge_type > &adj_list)
friend for outputting to a std::ostream.
E edge_type
Alias for the edge type.
std::size_t edge_count() const
Returns the total number of edges in the graph.
std::size_t node_id_count() const
Returns the number of nodes in the graph.
Checks whether a type supports streaming to std::ostream.
Definition concepts.h:32
Placeholder for user-defined data types used in vertices or edges.
Definition concepts.h:46
Defines C++20 concepts used for type constraints in the GraphLib library.