Skip to content

Commit c38b4cb

Browse files
author
=
committed
task_01
1 parent b793833 commit c38b4cb

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed

lib/src/graph.h

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#ifndef __GRAPH_H__
2+
#define __GRAPH_H__
3+
4+
#include <algorithm>
5+
#include <initializer_list>
6+
#include <iostream>
7+
#include <unordered_map>
8+
#include <vector>
9+
10+
template <typename T, typename NameType>
11+
class Node {
12+
public:
13+
Node(NameType name) : name{name}, paths{} {}
14+
NameType name{NameType()};
15+
std::unordered_map<Node*, T> paths;
16+
17+
void descr_path(Node* n, T lenght = 1) { paths[n] = lenght; }
18+
19+
~Node() {
20+
paths = {};
21+
name = NameType();
22+
}
23+
};
24+
25+
template <typename T, typename NameType>
26+
class Graph {
27+
static_assert(std::is_arithmetic<T>::value,
28+
"Graph: paths' lenghts must be arithmetic!");
29+
30+
public:
31+
Graph(std::initializer_list<std::pair<NameType, NameType>> links,
32+
T base_lenght = 1) {
33+
add_paths(links, base_lenght);
34+
}
35+
36+
Graph(std::initializer_list<std::pair<std::pair<NameType, NameType>, T>>
37+
links) {
38+
add_paths(links);
39+
}
40+
41+
Node<T, NameType>* find_via_name(NameType name) {
42+
auto ans = std::find_if(
43+
nodes.begin(), nodes.end(),
44+
[&name](const Node<T, NameType>* x) { return x->name == name; });
45+
if (ans == nodes.end()) {
46+
return nullptr;
47+
}
48+
return *ans;
49+
}
50+
51+
Node<T, NameType>* operator[](NameType name) { find_via_name(name); }
52+
53+
void add_paths(std::initializer_list<std::pair<NameType, NameType>> links,
54+
T base_lenght = 1) {
55+
/* { {Name1, Name2}, ... }*/
56+
for (auto i : links) {
57+
Node<T, NameType>* first = find_via_name(i.first);
58+
if (!first) {
59+
first = new Node<T, NameType>{i.first};
60+
nodes.push_back(first);
61+
}
62+
Node<T, NameType>* second = find_via_name(i.second);
63+
if (!second && first != second) {
64+
second = new Node<T, NameType>{i.second};
65+
nodes.push_back(second);
66+
}
67+
first->descr_path(second, base_lenght);
68+
continue;
69+
}
70+
}
71+
72+
void add_paths(
73+
std::initializer_list<std::pair<std::pair<NameType, NameType>, T>>
74+
links) {
75+
/* { { Name1, Name2 }, lenght }, ... }
76+
*/
77+
for (auto i : links) {
78+
Node<T, NameType>* first = find_via_name(i.first.first);
79+
if (!first) {
80+
first = new Node{i.first.first};
81+
nodes.push_back(first);
82+
}
83+
Node<T, NameType>* second = find_via_name(i.first.second);
84+
if (!second && first != second) {
85+
second = new Node{i.first.second};
86+
nodes.push_back(second);
87+
}
88+
first->descr_path(second, i.second);
89+
continue;
90+
}
91+
}
92+
93+
~Graph() {
94+
for (Node<T, NameType>* i : nodes) {
95+
delete i;
96+
}
97+
nodes = {};
98+
}
99+
100+
void see_vertical() {
101+
for (auto i : nodes) {
102+
if (i->paths.size() == 0) {
103+
std::cout << i->name << std::endl;
104+
continue;
105+
}
106+
for (auto k : i->paths) {
107+
std::cout << i->name << " -> " << k.first->name << ", l:" << k.second
108+
<< std::endl;
109+
}
110+
}
111+
}
112+
113+
friend std::ostream& operator<<(std::ostream& os,
114+
const Graph<T, NameType>& g) {
115+
os << "Graph( ";
116+
for (auto i : g.nodes) {
117+
if (i->paths.size() == 0) {
118+
os << "{" << i->name << "}";
119+
continue;
120+
}
121+
for (auto k : i->paths) {
122+
os << "{" << i->name << " -> " << k.first->name << ", l:" << k.second
123+
<< "}, ";
124+
}
125+
}
126+
os << ")";
127+
return os;
128+
}
129+
130+
std::vector<Node<T, NameType>*> nodes;
131+
};
132+
133+
#endif

task_01/src/topological_sort.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <stdexcept>
2+
#include <vector>
3+
4+
#include "../lib/src/graph.h"
5+
6+
template <typename T>
7+
void topological_rec(std::vector<Node<T, int>*>& st, Node<T, int>* n) {
8+
if (n->name == 0) {
9+
n->name = 1;
10+
// 1 - adjacent (as leafs) points
11+
12+
for (auto i : n->paths) {
13+
topological_rec(st, i.first);
14+
}
15+
n->name = 2;
16+
st.push_back(n);
17+
18+
} else if (n->name == 2) {
19+
return;
20+
} else {
21+
throw std::runtime_error("Incorrect graph");
22+
}
23+
}
24+
25+
template <typename T>
26+
Graph<T, int>& topological_sort(Graph<T, int>& g) {
27+
std::vector<Node<T, int>*> marked_points;
28+
for (auto i : g.nodes) {
29+
i->name = 0;
30+
// 0 - clear points
31+
}
32+
33+
// point_stack.push(g.nodes[0]);
34+
for (auto i : g.nodes) {
35+
if (i->name == 0) {
36+
topological_rec(marked_points, i);
37+
}
38+
}
39+
int stack_size = marked_points.size();
40+
for (int i = 1; i < stack_size + 1; ++i) {
41+
marked_points[stack_size - i]->name = i;
42+
}
43+
return g;
44+
}

0 commit comments

Comments
 (0)