Skip to content

Alexander_homework #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions lib/src/graph.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#ifndef __GRAPH_H__
#define __GRAPH_H__

#include <algorithm>
#include <initializer_list>
#include <iostream>
#include <unordered_map>
#include <vector>

template <typename T, typename NameType>
class Node {
public:
Node(NameType name) : name{name}, paths{} {}
NameType name{NameType()};
std::unordered_map<Node*, T> paths;

void descr_path(Node* n, T lenght = 1) { paths[n] = lenght; }

~Node() {
paths = {};
name = NameType();
}
};

template <typename T, typename NameType>
class Graph {
static_assert(std::is_arithmetic<T>::value,
"Graph: paths' lenghts must be arithmetic!");

public:
Graph(std::initializer_list<std::pair<NameType, NameType>> links,
T base_lenght = 1) {
add_paths(links, base_lenght);
}

Graph(std::initializer_list<std::pair<std::pair<NameType, NameType>, T>>
links) {
add_paths(links);
}

Node<T, NameType>* find_via_name(NameType name) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FindByName по кодстайлу

auto ans = std::find_if(
nodes.begin(), nodes.end(),
[&name](const Node<T, NameType>* x) { return x->name == name; });
if (ans == nodes.end()) {
return nullptr;
}
return *ans;
}

Node<T, NameType>* operator[](NameType name) { find_via_name(name); }

void add_paths(std::initializer_list<std::pair<NameType, NameType>> links,
T base_lenght = 1) {
/* { {Name1, Name2}, ... }*/
for (auto i : links) {
Node<T, NameType>* first = find_via_name(i.first);
if (!first) {
first = new Node<T, NameType>{i.first};
nodes.push_back(first);
}
Node<T, NameType>* second = find_via_name(i.second);
if (!second && first != second) {
second = new Node<T, NameType>{i.second};
nodes.push_back(second);
}
first->descr_path(second, base_lenght);
continue;
}
}

void add_paths(
std::initializer_list<std::pair<std::pair<NameType, NameType>, T>>
links) {
/* { { Name1, Name2 }, lenght }, ... }
*/
for (auto i : links) {
Node<T, NameType>* first = find_via_name(i.first.first);
if (!first) {
first = new Node{i.first.first};
nodes.push_back(first);
}
Node<T, NameType>* second = find_via_name(i.first.second);
if (!second && first != second) {
second = new Node{i.first.second};
nodes.push_back(second);
}
first->descr_path(second, i.second);
continue;
}
}

~Graph() {
for (Node<T, NameType>* i : nodes) {
delete i;
}
nodes = {};
}

void see_vertical() {
for (auto i : nodes) {
if (i->paths.size() == 0) {
std::cout << i->name << std::endl;
continue;
}
for (auto k : i->paths) {
std::cout << i->name << " -> " << k.first->name << ", l:" << k.second
<< std::endl;
}
}
}

friend std::ostream& operator<<(std::ostream& os,
const Graph<T, NameType>& g) {
os << "Graph( ";
for (auto i : g.nodes) {
if (i->paths.size() == 0) {
os << "{" << i->name << "}";
continue;
}
for (auto k : i->paths) {
os << "{" << i->name << " -> " << k.first->name << ", l:" << k.second
<< "}, ";
}
}
os << ")";
return os;
}

std::vector<Node<T, NameType>*> nodes;
};

#endif
2 changes: 1 addition & 1 deletion task_01/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1 +1 @@
int main() { return 0; }
int main() { return 0; }
74 changes: 71 additions & 3 deletions task_01/src/test.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,73 @@
#include <gtest/gtest.h>

TEST(Test, Simple) {
ASSERT_EQ(1, 1); // Stack []
}
#include <stdexcept>

#include "topological_sort.hpp"

template <typename T>
bool check_graph_sorted(Graph<T, int>& g) {
for (auto i : g.nodes) {
for (auto k : i->paths) {
if (i->name >= k.first->name) {
return false;
}
}
}
return true;
}

TEST(TopologySort, TestSimple1) {
Graph<int, int> g({{1, 4}, {4, 2}, {3, 2}, {4, 3}});
ASSERT_EQ(check_graph_sorted(topological_sort(g)), true); // Stack []
}

TEST(TopologySort, TestSimple2) {
Graph<int, int> g({{1, 2}, {3, 2}, {2, 5}, {4, 2}, {4, 6}, {6, 5}});
ASSERT_EQ(check_graph_sorted(topological_sort(g)), true); // Stack []
}

TEST(TopologySort, TestExtraSourcePoint1) {
Graph<int, int> g({{1, 2}, {3, 2}, {2, 5}, {4, 2}, {4, 6}, {6, 5}, {8, 6}});
ASSERT_EQ(check_graph_sorted(topological_sort(g)), true); // Stack []
}

TEST(TopologySort, TestExtraSourcePoint2) {
Graph<int, int> g({{1, 2}, {3, 2}, {8, 5}, {2, 5}, {4, 2}, {4, 6}, {6, 5}});
ASSERT_EQ(check_graph_sorted(topological_sort(g)), true); // Stack []
}

TEST(TopologySort, TestExtraSourcePoint3) {
Graph<int, int> g({{1, 4}, {4, 2}, {3, 2}, {4, 3}, {9, 1}});
ASSERT_EQ(check_graph_sorted(topological_sort(g)), true); // Stack []
}

TEST(TopologySort, TestExtraSourcePoint4) {
Graph<int, int> g({{1, 2}, {3, 2}, {6, 5}, {2, 5}, {4, 2}, {4, 6}, {6, 5}});
ASSERT_EQ(check_graph_sorted(topological_sort(g)), true); // Stack []
}

TEST(TopologySort, TestExtraLeafPoint) {
Graph<int, int> g({{1, 2}, {3, 2}, {6, 9}, {2, 5}, {4, 2}, {4, 6}, {6, 5}});
ASSERT_EQ(check_graph_sorted(topological_sort(g)), true); // Stack []
}

TEST(TopologySort, TestLoopError1) {
Graph<int, int> g({{1, 4}, {4, 2}, {3, 2}, {4, 3}, {3, 3}});
EXPECT_THROW(topological_sort(g), std::runtime_error); // Stack []
}

TEST(TopologySort, TestLoopError2) {
Graph<int, int> g({{1, 2}, {1, 3}, {3, 2}, {2, 3}});
EXPECT_THROW(topological_sort(g), std::runtime_error); // Stack []
}

TEST(TopologySort, TestLoopError3) {
Graph<int, int> g({{1, 4}, {4, 2}, {3, 2}, {4, 3}, {4, 1}});
EXPECT_THROW(topological_sort(g),
std::runtime_error); // Stack []
}

TEST(TopologySort, TestLoopError4) {
Graph<int, int> g({{1, 2}, {1, 3}, {3, 2}, {2, 3}, {2, 1}, {3, 1}});
EXPECT_THROW(topological_sort(g), std::runtime_error); // Stack []
}
49 changes: 49 additions & 0 deletions task_01/src/topological_sort.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#ifndef __TOPOLOG_SORT_H__
#define __TOPOLOG_SORT_H__

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: declaration uses identifier 'TOPOLOG_SORT_H', which is a reserved identifier [bugprone-reserved-identifier]

Suggested change
#define __TOPOLOG_SORT_H__
#define TOPOLOG_SORT_H_

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: declaration uses identifier 'TOPOLOG_SORT_H', which is a reserved identifier [bugprone-reserved-identifier]

Suggested change
#define __TOPOLOG_SORT_H__
#define TOPOLOG_SORT_H_


#include <stdexcept>
#include <vector>

#include "../../lib/src/graph.hpp"

template <typename T>
void topological_rec(std::vector<Node<T, int>*>& st, Node<T, int>* n) {
if (n->name == 0) {
n->name = 1;
// 1 - adjacent (as leafs) points

for (auto i : n->paths) {
topological_rec(st, i.first);
}
n->name = 2;
st.push_back(n);

} else if (n->name == 2) {
return;
} else {
throw std::runtime_error("Incorrect graph");
}
}

template <typename T>
Graph<T, int>& topological_sort(Graph<T, int>& g) {
std::vector<Node<T, int>*> marked_points;
for (auto i : g.nodes) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(auto node : g.nodes)

а ещё лучше node_ptr так понятнее будет что там указатель)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

к сожалению эот класс я позже полностью поменял из за нехватки времени, но на будущее учту, спасибо)

i->name = 0;
// 0 - clear points
}

// point_stack.push(g.nodes[0]);
for (auto i : g.nodes) {
if (i->name == 0) {
topological_rec(marked_points, i);
}
}
int stack_size = marked_points.size();
for (int i = 1; i < stack_size + 1; ++i) {
marked_points[stack_size - i]->name = i;
}
return g;
}

#endif
Loading