7template <
typename vert_t>
9 std::is_arithmetic_v<vert_t> || std::is_same_v<vert_t, std::string>;
11template <
typename weight_t>
16template <AllowedVertType vert_t, AllowedWeightType weight_t>
18 const std::tuple<vert_t, vert_t, weight_t>& edge) {
19 return std::get<0>(edge);
22template <AllowedVertType vert_t, AllowedWeightType weight_t>
24 const std::tuple<vert_t, vert_t, weight_t>& edge) {
25 return std::get<1>(edge);
28template <AllowedVertType vert_t, AllowedWeightType weight_t>
30 const std::tuple<vert_t, vert_t, weight_t>& edge) {
31 return std::get<2>(edge);
71 :
edges_(std::move(other.edges_)),
72 verts_(std::move(other.verts_)),
85 edges_ = std::move(other.edges_);
86 verts_ = std::move(other.verts_);
102 const std::vector<std::pair<vert_t, vert_t>>& edges_pairs) {
103 if (edges_pairs.empty())
return Graph();
105 std::vector<Edge> edges{};
106 edges.reserve(edges_pairs.size());
108 for (
const auto& edge : edges_pairs) edges.push_back(edge);
126 const std::vector<std::pair<vert_t, vert_t>>& edges_pairs,
127 const std::vector<weight_t>& weights) {
128 if (edges_pairs.empty() && weights.empty())
return Graph();
130 std::vector<Edge> edges{};
131 edges.reserve(edges_pairs.size());
133 if (edges_pairs.size() != weights.size())
134 throw std::invalid_argument(
135 "GraphWeighted: the sizes of the edges and weights vectors do not "
138 for (
size_t i = 0; i < weights.size(); i++)
139 edges.push_back(
Edge(edges_pairs[i], weights[i]));
153 const std::vector<std::tuple<vert_t, vert_t, weight_t>>& edges_tuples) {
154 if (edges_tuples.empty())
return Graph();
156 std::vector<Edge> edges;
158 for (
const auto& [start, end, weight] : edges_tuples)
159 edges.emplace_back(start, end, weight);
173 if (edges_strs.empty())
return Graph();
175 std::vector<Graph<vert_t, weight_t>::Edge> edges;
177 for (
const auto& edge_str : edges_strs) {
178 vert_t start_vert, end_vert;
181 edges.emplace_back(start_vert, end_vert);
196 const std::unordered_map<std::string, weight_t>& edges_dict) {
197 if (edges_dict.empty())
return Graph();
199 std::vector<Graph<vert_t, weight_t>::Edge> edges;
201 for (
const auto& [edge_str, weight] : edges_dict) {
202 vert_t start_vert, end_vert;
205 edges.emplace_back(start_vert, end_vert, weight);
227 const std::vector<std::vector<weight_t>>& adj_matrix,
228 bool is_weighted =
false) {
229 if constexpr (std::is_arithmetic_v<vert_t>) {
230 if (adj_matrix.empty())
return Graph();
232 std::vector<Edge> edges{};
234 if (adj_matrix.size() != adj_matrix[0].size())
235 throw std::invalid_argument(
236 "GraphFromAdjMatrix: AdjacencyMatrix is not squared.");
238 for (
size_t row = 0; row < adj_matrix.size(); row++) {
240 if (adj_matrix[row].size() != adj_matrix[row - 1].size())
241 throw std::invalid_argument(
242 "GraphFromAdjMatrix: AdjacencyMatrix is not squared [row "
245 for (
size_t col = 0; col < adj_matrix[row].size(); col++) {
246 if (adj_matrix[row][col] == 0)
continue;
249 edges.push_back(
Edge(col, row, adj_matrix[col][row]));
251 edges.push_back(
Edge(col, row));
257 }
else if constexpr (std::is_same_v<vert_t, std::string>)
258 throw std::logic_error(
259 "GraphFromAdjMatrix: this method (constructor) "
260 "is deleted for std::string.");
275 const std::vector<std::vector<vert_t>>& adj_list) {
276 if constexpr (std::is_arithmetic_v<vert_t>) {
277 if (adj_list.empty())
return Graph();
279 std::vector<Edge> edges{};
281 for (
size_t row = 0; row < adj_list.size(); row++)
282 for (
size_t col = 0; col < adj_list[row].size(); col++)
283 edges.push_back(
Edge(row, adj_list[row][col]));
287 }
else if constexpr (std::is_same_v<vert_t, std::string>)
288 throw std::logic_error(
289 "GraphFromAdjList: this method (constructor) "
290 "is deleted for std::string.");
302 const std::unordered_map<vert_t, std::vector<vert_t>>& adj_list_dict) {
303 if (adj_list_dict.empty())
return Graph();
305 std::vector<Edge> edges{};
307 for (
const auto& vert_str_pair : adj_list_dict) {
308 auto vert = vert_str_pair.first;
309 for (
const auto& vert_2 : vert_str_pair.second)
310 edges.push_back(
Edge(vert, vert_2));
329 std::vector<std::tuple<vert_t, vert_t, weight_t>>
Edges()
const {
330 if (
edges_.empty())
return {};
332 std::vector<std::tuple<vert_t, vert_t, weight_t>> edges_tuples(
334 std::transform(
edges_.begin(),
edges_.end(), edges_tuples.begin(),
335 [](
const Edge& edge) {
336 return std::make_tuple(edge.StartVert(), edge.EndVert(),
350 std::ostream&
PrintVerts(std::ostream& os = std::cout)
const {
362 std::ostream&
PrintEdges(std::ostream& os = std::cout)
const {
375 for (
const auto& vert :
Verts()) {
378 for (
const auto& neighbor :
edges_) {
379 if (neighbor.StartVert() == vert) os << neighbor.EndVert() <<
"; ";
381 if (neighbor.EndVert() == vert) os << neighbor.StartVert() <<
"; ";
392 std::unordered_set<size_t> seen_edges;
393 std::vector<Edge> unique_edges;
397 if (seen_edges.count(i) != 0)
continue;
402 seen_edges.insert(j);
406 unique_edges.push_back(
edges_[i]);
409 edges_ = std::move(unique_edges);
425 if constexpr (std::is_arithmetic_v<vert_t>) {
426 std::vector<std::vector<vert_t>> adj_list(
427 *std::max_element(
Verts().begin(),
Verts().end()) + 1);
429 for (
const auto& edge :
edges_) {
430 adj_list[edge.StartVert()].push_back(edge.EndVert());
431 if (!
IsDirected()) adj_list[edge.EndVert()].push_back(edge.StartVert());
437 else if constexpr (std::is_same_v<vert_t, std::string>)
438 throw std::logic_error(
439 "GetAdjListWithoutKeys: this method is deleted for std::string.");
444 std::unordered_map<vert_t, std::vector<vert_t>>
GetAdjList()
const {
445 auto adj_list_dict = std::unordered_map<vert_t, std::vector<vert_t>>();
447 for (
const auto& edge :
edges_) {
448 adj_list_dict[edge.StartVert()].push_back(edge.EndVert());
450 adj_list_dict[edge.EndVert()].push_back(edge.StartVert());
453 return adj_list_dict;
462 if constexpr (std::is_arithmetic_v<vert_t>) {
463 std::vector<std::vector<weight_t>> adj_matrix(
466 for (
const auto& edge :
edges_)
467 if (edge.IsWeighted()) {
468 adj_matrix[edge.StartVert()][edge.EndVert()] = edge.Weight();
470 adj_matrix[edge.EndVert()][edge.StartVert()] = edge.Weight();
472 adj_matrix[edge.StartVert()][edge.EndVert()] = 1;
473 if (!
IsDirected()) adj_matrix[edge.EndVert()][edge.StartVert()] = 1;
479 else if constexpr (std::is_same_v<vert_t, std::string>)
480 throw std::logic_error(
481 "GetAdjMatrix: this method is deleted for std::string.");
493 return std::find(
Verts().begin(),
Verts().end(), vert) !=
Verts().end();
506 bool ContainsEdge(
const std::tuple<vert_t, vert_t, weight_t>& edge)
const {
508 throw std::logic_error(
"ContainsEdge: graph is not weighted.");
537 throw std::logic_error(
"GetEdgeWeight: graph is not weighted.");
542 throw std::invalid_argument(
"GetEdgeWeight: there is no such edge: " +
558 weight_t new_weight) {
560 throw std::logic_error(
"SetEdgeWeight: graph is not weighted.");
565 throw std::invalid_argument(
"SetEdgeWeight: there is no such edge: " +
568 it->SetWeight(new_weight);
576 void AddEdge(
const std::tuple<vert_t, vert_t, weight_t>& edge_tuple,
577 bool ignore_warning =
false) {
586 void AddEdge(
const std::pair<vert_t, vert_t>& edge_pair,
587 bool ignore_warning =
false) {
589 std::cerr <<
"Warning! AddEdge: weighted graph should consist of "
593 AddEdge_(
Edge(edge_pair.first, edge_pair.second,
static_cast<weight_t
>(0)));
598 if constexpr (std::is_arithmetic_v<vert_t>) {
600 throw std::invalid_argument(
601 "RemoveVert: there is no such vert in graph: " +
602 std::to_string(vert));
605 else if constexpr (std::is_same_v<vert_t, std::string>)
607 throw std::invalid_argument(
608 "RemoveVert: there is no such vert in graph: " + vert);
613 [vert](
const Edge& edge) {
614 return edge.StartVert() == vert ||
615 edge.EndVert() == vert;
621 void RemoveEdge(
const std::pair<vert_t, vert_t>& edge_pair) {
623 throw std::invalid_argument(
624 "RemoveEdge: there is no such edge in graph: " +
625 Edge(edge_pair).Name());
628 [&edge_pair,
this](
const Edge& e) {
629 return (e == Edge(edge_pair)) ||
631 Edge(e.EndVert(), e.StartVert()) ==
638 void RemoveEdge(
const std::tuple<vert_t, vert_t, weight_t>& edge_tuple) {
640 throw std::invalid_argument(
641 "RemoveEdge: there is no such edge in graph: " +
642 Edge(edge_tuple).Name());
647 [&edge_tuple,
this](
const Edge& e) {
648 return (e == Edge(edge_tuple)) ||
650 e == Edge(std::make_tuple(EndVertFromTuple(edge_tuple),
651 StartVertFromTuple(edge_tuple),
652 WeightFromTuple(edge_tuple))));
662 Edge(
const vert_t start_vert,
const vert_t& end_vert)
665 Edge(
const vert_t& start_vert, vert_t end_vert, weight_t weight)
668 Edge(
const std::pair<vert_t, vert_t>& edge_pair)
671 Edge(
const std::pair<vert_t, vert_t>& edge_pair, weight_t weight)
676 Edge(
const std::tuple<vert_t, vert_t, weight_t>& edge_tuple)
703 const std::string&
Name()
const {
704 static std::string
name;
706 if constexpr (std::is_arithmetic_v<vert_t>) {
710 ", w: " + std::to_string(
Weight()) +
"]";
713 std::to_string(
EndVert()) +
"]";
717 }
else if constexpr (std::is_same_v<vert_t, std::string>) {
720 "', w: " + std::to_string(
Weight()) +
"]";
750 Graph(
const std::vector<Edge>& edges) {
751 if (edges.empty())
return;
753 for (
const auto& edge : edges) {
758 if constexpr (std::is_arithmetic_v<vert_t>) {
761 vert_t max_vert = edges[0].StartVert();
763 for (
const auto& edge :
edges_) {
764 max_vert = std::max(max_vert, edge.StartVert());
765 max_vert = std::max(max_vert, edge.EndVert());
768 verts_.resize(max_vert + 1);
771 }
else if constexpr (std::is_same_v<vert_t, std::string>)
772 for (
const auto& edge :
edges_) {
774 verts_.push_back(edge.StartVert());
777 verts_.push_back(edge.EndVert());
791 const std::string& edge_str) {
792 const size_t pos = edge_str.find(
"->");
796 if (pos == std::string::npos)
797 throw std::invalid_argument(
"EdgeString: invalid edge string format: " +
800 if constexpr (std::is_arithmetic_v<vert_t>) {
802 start_vert = std::stoul(edge_str.substr(0, pos));
803 end_vert = std::stoul(edge_str.substr(pos + 2));
806 catch (
const std::exception&) {
807 throw std::invalid_argument(
808 "EdgeString: invalid edge string format "
809 "(vertices should be numbers): " +
814 else if constexpr (std::is_same_v<vert_t, std::string>) {
815 start_vert = edge_str.substr(0, pos);
816 end_vert = edge_str.substr(pos + 2);
819 return {start_vert, end_vert};
823 auto [start_vert, end_vert] = edge;
827 [start_vert, end_vert,
this](
const auto& e) {
828 return (e.StartVert() == start_vert && e.EndVert() == end_vert) ||
829 (!IsDirected() && e.StartVert() == end_vert &&
830 e.EndVert() == start_vert);
835 auto [start_vert, end_vert] = edge;
839 [start_vert, end_vert,
this](
const auto& e) {
840 return (e.StartVert() == start_vert && e.EndVert() == end_vert) ||
841 (!IsDirected() && e.StartVert() == end_vert &&
842 e.EndVert() == start_vert);
846 auto GetEdgeIter_(
const std::tuple<vert_t, vert_t, weight_t>& edge)
const {
847 auto [start_vert, end_vert, weight] = edge;
851 [start_vert, end_vert, weight,
this](
const auto& e) {
852 return (e.StartVert() == start_vert && e.EndVert() == end_vert &&
853 e.Weight() == weight) ||
854 (!IsDirected() && e.StartVert() == end_vert &&
855 e.EndVert() == start_vert && e.Weight() == weight);
862template <AllowedVertType vert_t, AllowedWeightType weight_t>
870 os <<
"Vertices:\n ";
Edge(const vert_t &start_vert, vert_t end_vert, weight_t weight)
Definition graph.hpp:665
bool operator==(const Edge &rhs) const
Definition graph.hpp:690
Edge(const vert_t start_vert, const vert_t &end_vert)
Definition graph.hpp:662
const std::string & Name() const
Definition graph.hpp:703
Edge(const std::pair< vert_t, vert_t > &edge_pair)
Definition graph.hpp:668
Edge(const std::pair< vert_t, vert_t > &edge_pair, weight_t weight)
Definition graph.hpp:671
bool IsWeighted() const
Definition graph.hpp:681
auto operator<=>(const Edge &rhs) const
Definition graph.hpp:701
void SetWeight(weight_t new_weight)
Definition graph.hpp:688
Edge(const std::tuple< vert_t, vert_t, weight_t > &edge_tuple)
Definition graph.hpp:676
vert_t start_vert_
Definition graph.hpp:731
bool operator!=(const Edge &rhs) const
Definition graph.hpp:699
weight_t Weight() const
Definition graph.hpp:686
vert_t end_vert_
Definition graph.hpp:732
vert_t StartVert() const
Definition graph.hpp:683
vert_t EndVert() const
Definition graph.hpp:684
weight_t weight_
Definition graph.hpp:733
Класс графа (может быть взвешенным и ориентированным).
Definition graph.hpp:44
void AddEdge_(const Edge &edge)
Definition graph.hpp:781
void SetEdgeWeight(const std::pair< vert_t, vert_t > &edge, weight_t new_weight)
Меняет вес ребра в взвешенном графе.
Definition graph.hpp:557
bool is_direct_
Definition graph.hpp:739
std::vector< std::tuple< vert_t, vert_t, weight_t > > Edges() const
Definition graph.hpp:329
weight_t GetEdgeWeight(const std::pair< vert_t, vert_t > &edge) const
Находит вес ребра в взвешенном графе.
Definition graph.hpp:535
std::ostream & PrintEdges(std::ostream &os=std::cout) const
Выводит в поток список ребер.
Definition graph.hpp:362
std::vector< std::vector< vert_t > > GetAdjListWithoutKeys() const
Definition graph.hpp:424
static Graph GraphWeighted(const std::vector< std::tuple< vert_t, vert_t, weight_t > > &edges_tuples)
Создает новый экземпляр Graph по ребрам. представленными вектором std::tuple (ВЗВЕШЕННЫЙ).
Definition graph.hpp:152
auto GetEdgeIter_(const std::pair< vert_t, vert_t > &edge)
Definition graph.hpp:834
bool ContainsEdge(const std::pair< vert_t, vert_t > &edge) const
Проверяет, содержится ли ребро в графе (НЕВЗВЕШЕННЫЙ).
Definition graph.hpp:521
static Graph GraphFromAdjList(const std::unordered_map< vert_t, std::vector< vert_t > > &adj_list_dict)
Создает новый экземпляр Graph. по списку смежности с указанием вершины-ключа (НЕВЗВЕШЕННЫЙ).
Definition graph.hpp:301
size_t VertsAmount() const
Definition graph.hpp:320
static Graph GraphFromAdjMatrix(const std::vector< std::vector< weight_t > > &adj_matrix, bool is_weighted=false)
Создает новый экземпляр Graph по матрице смежности.
Definition graph.hpp:226
void MakeUndirected()
Делает граф ненаправленным (удаляет лишние ребра).
Definition graph.hpp:391
bool ContainsEdge(const std::tuple< vert_t, vert_t, weight_t > &edge) const
Проверяет, содержится ли ребро в графе (ВЗВЕШЕННЫЙ).
Definition graph.hpp:506
const std::vector< vert_t > & Verts() const
Definition graph.hpp:326
void MakeDirected()
Делает граф направленным (ничего).
Definition graph.hpp:414
auto GetEdgeIter_(const std::pair< vert_t, vert_t > &edge) const
Definition graph.hpp:822
void RemoveEdge(const std::tuple< vert_t, vert_t, weight_t > &edge_tuple)
Definition graph.hpp:638
std::vector< std::vector< weight_t > > GetAdjMatrix() const
Definition graph.hpp:461
void AddEdge(const std::tuple< vert_t, vert_t, weight_t > &edge_tuple, bool ignore_warning=false)
Definition graph.hpp:576
bool is_weighted_
Definition graph.hpp:740
Graph(const std::vector< Edge > &edges)
Definition graph.hpp:750
static Graph GraphWeighted(const std::vector< std::pair< vert_t, vert_t > > &edges_pairs, const std::vector< weight_t > &weights)
Создает новый экземпляр Graph по ребрам, представленными вектором std::pair и weight_t (ВЗВЕШЕННЫЙ).
Definition graph.hpp:125
std::unordered_map< vert_t, std::vector< vert_t > > GetAdjList() const
Definition graph.hpp:444
Graph(Graph &&other) noexcept
Перемещающий конструктор. Перемещает ресурсы из другого графа.
Definition graph.hpp:70
static Graph GraphNonWeighted(const std::vector< std::pair< vert_t, vert_t > > &edges_pairs)
Создает новый экземпляр Graph по ребрам, представленными вектором std::pair (НЕВЗВЕШЕННЫЙ).
Definition graph.hpp:101
Graph(const Graph &other)=default
Копирующий конструктор.
std::ostream & PrintAdjList(std::ostream &os=std::cout) const
Выводит в поток список смежности.
Definition graph.hpp:374
void RemoveEdge(const std::pair< vert_t, vert_t > &edge_pair)
Definition graph.hpp:621
Graph & operator=(const Graph &other)=default
Оператор копирующего присваивания.
std::ostream & PrintVerts(std::ostream &os=std::cout) const
Выводит в поток список вершин.
Definition graph.hpp:350
bool IsDirected() const
Проверяет, направлен ли граф.
Definition graph.hpp:417
static Graph GraphFromStrs(const std::vector< std::string > &edges_strs)
Создает новый экземпляр Graph по ребрам. представленными вектором std::string (НЕВЗВЕШЕННЫЙ).
Definition graph.hpp:172
std::vector< Edge > edges_
Definition graph.hpp:736
auto GetEdgeIter_(const std::tuple< vert_t, vert_t, weight_t > &edge) const
Definition graph.hpp:846
Graph()
Инициализирует новый экземпляр Graph.
Definition graph.hpp:47
bool ContainsVert(const vert_t &vert) const
Проверяет, содержится ли вершина в графе.
Definition graph.hpp:492
static Graph GraphFromAdjList(const std::vector< std::vector< vert_t > > &adj_list)
Создает новый экземпляр Graph. по списку смежности (НЕВЗВЕШЕННЫЙ).
Definition graph.hpp:274
static Graph GraphFromMap(const std::unordered_map< std::string, weight_t > &edges_dict)
Создает новый экземпляр Graph по ребрам. представленными словарем из std::string и weight_t (ВЗВЕШЕНН...
Definition graph.hpp:195
static std::pair< vert_t, vert_t > ParseEdgeString_(const std::string &edge_str)
Definition graph.hpp:790
void AddEdge(const std::pair< vert_t, vert_t > &edge_pair, bool ignore_warning=false)
Definition graph.hpp:586
bool IsWeighted() const
Проверяет, взвешен ли граф.
Definition graph.hpp:317
void RemoveVert(const vert_t &vert)
Definition graph.hpp:597
std::vector< vert_t > verts_
Definition graph.hpp:737
size_t EdgesAmount() const
Definition graph.hpp:323
Graph & operator=(Graph &&other) noexcept
Оператор перемещающего присваивания. Перемещает ресурсы из другого. графа.
Definition graph.hpp:83
friend std::ostream & operator<<(std::ostream &os, const Graph< vert_t, weight_t >::Edge &edge)
Definition graph.hpp:743
void AddVert(const vert_t &vert)
Definition graph.hpp:571
std::ostream & operator<<(std::ostream &os, const Graph< vert_t, weight_t > &graph)
Definition graph.hpp:863
vert_t EndVertFromTuple(const std::tuple< vert_t, vert_t, weight_t > &edge)
Definition graph.hpp:23
weight_t WeightFromTuple(const std::tuple< vert_t, vert_t, weight_t > &edge)
Definition graph.hpp:29
vert_t StartVertFromTuple(const std::tuple< vert_t, vert_t, weight_t > &edge)
Definition graph.hpp:17
bool Contains(const std::vector< T > &vec, const T &value)
Проверяет наличие элемента в векторе.
Definition utils.hpp:193