diff --git a/.gitignore b/.gitignore index 41f1b1b..96c0402 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,8 @@ _deps .cache/* .vscode/* -build/* \ No newline at end of file +build/* +.vs +WeightedGraph.i +out +CMakeSettings.json diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 98320e1..f2cf684 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -3,7 +3,10 @@ project(Utils) set(CMAKE_CXX_STANDARD 23) -file(GLOB_RECURSE lib_source_list "src/*.cpp" "src/*.hpp") +file(GLOB_RECURSE lib_source_list "src/*.cpp") + +SET(BASEPATH "${CMAKE_SOURCE_DIR}") +INCLUDE_DIRECTORIES("${BASEPATH}") add_library(${PROJECT_NAME} ${lib_source_list}) diff --git a/lib/src/BellmanFordAlgorithm.cpp b/lib/src/BellmanFordAlgorithm.cpp new file mode 100644 index 0000000..e5a7931 --- /dev/null +++ b/lib/src/BellmanFordAlgorithm.cpp @@ -0,0 +1,35 @@ +#include + +#include "BellmanForlAlgorithm.h" + +std::vector BellmanFordAlgorithm(const WeightedGraph& graph, + int start_id) { + int n = graph.GetVerts(); + std::vector pathLength(n, DBL_MAX); + pathLength[start_id] = 0; + for (int i = 0; i < n; ++i) + for (int j = 0; j < n; ++j) + for (int k = 0; k < n; ++k) + if (graph[j][k] && pathLength[j] != DBL_MAX && + pathLength[j] + graph[j][k] < pathLength[k]) { + if (i == n - 1) return std::vector(0); + pathLength[k] = pathLength[j] + graph[j][k]; + } + return pathLength; +} + +std::vector BellmanFordAlgorithm( + const OrientedWeightedGraphWithZeroWeight& graph, int start_id) { + int n = graph.GetVerts(); + std::vector pathLength(n, DBL_MAX); + pathLength[start_id] = 0; + for (int i = 0; i < n; ++i) + for (int j = 0; j < n; ++j) + for (int k = 0; k < n; ++k) + if (graph[j][k] && pathLength[j] != DBL_MAX && + pathLength[j] + graph.GetWeight(j, k) < pathLength[k]) { + if (i == n - 1) return std::vector(0); + pathLength[k] = pathLength[j] + graph.GetWeight(j, k); + } + return pathLength; +} diff --git a/lib/src/BellmanForlAlgorithm.h b/lib/src/BellmanForlAlgorithm.h new file mode 100644 index 0000000..e76e046 --- /dev/null +++ b/lib/src/BellmanForlAlgorithm.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +std::vector BellmanFordAlgorithm(const WeightedGraph& graph, + int start_id); +std::vector BellmanFordAlgorithm( + const OrientedWeightedGraphWithZeroWeight& graph, int start_id); diff --git a/lib/src/DeikstraAlgorithm.cpp b/lib/src/DeikstraAlgorithm.cpp new file mode 100644 index 0000000..7828306 --- /dev/null +++ b/lib/src/DeikstraAlgorithm.cpp @@ -0,0 +1,131 @@ +#include "DeikstraAlgorithm.h" + +#include + +double DeikstraAlgorithm(const WeightedGraph& graph, int start_id, int end_id) { + int n = graph.GetVerts(); + std::vector ended(n); + std::vector pathLength(n, DBL_MAX); + pathLength[start_id] = 0; + int this_id = start_id; + int counter = 0; + for (; true;) { + if (counter >= n) break; + for (int i = 0; i < n; ++i) { + if (graph[this_id][i]) + pathLength[i] = + std::min(pathLength[i], pathLength[this_id] + graph[this_id][i]); + } + ended[this_id] = true; + double min = DBL_MAX; + for (int j = 0; j < n; ++j) { + if (!ended[j]) + if (min > pathLength[j]) { + min = pathLength[j]; + this_id = j; + } + } + if (this_id == end_id) return pathLength[end_id]; + ++counter; + } + return pathLength[end_id]; +} + +double DeikstraAlgorithm(const OrientedWeightedGraphWithZeroWeight& graph, + int start_id, int end_id) { + int n = graph.GetVerts(); + std::vector ended(n); + std::vector pathLength(n, DBL_MAX); + pathLength[start_id] = 0; + int this_id = start_id; + int counter = 0; + for (; true;) { + if (counter >= n) break; + for (int i = 0; i < n; ++i) { + if (graph[this_id][i]) + pathLength[i] = std::min( + pathLength[i], pathLength[this_id] + graph.GetWeight(this_id, i)); + } + ended[this_id] = true; + double min = DBL_MAX; + for (int j = 0; j < n; ++j) { + if (!ended[j]) + if (min > pathLength[j]) { + min = pathLength[j]; + this_id = j; + } + } + if (this_id == end_id) return pathLength[end_id]; + ++counter; + } + return pathLength[end_id]; +} + +DeikstraReturn DeikstraPathAlgorithm(const WeightedGraph& graph, int start_id, + int end_id) { + int n = graph.GetVerts(); + std::vector ended(n); + std::vector pathLength(n, DBL_MAX); + std::vector prevs(n, -1); + pathLength[start_id] = 0; + int this_id = start_id; + for (int counter = 0; counter < n && this_id != end_id; ++counter) { + for (int i = 0; i < n; ++i) { + if (graph[this_id][i] && + pathLength[i] > pathLength[this_id] + graph[this_id][i]) { + pathLength[i] = pathLength[this_id] + graph[this_id][i]; + prevs[i] = this_id; + } + } + ended[this_id] = true; + double min = DBL_MAX; + for (int j = 0; j < n; ++j) { + if (!ended[j]) + if (min > pathLength[j]) { + min = pathLength[j]; + this_id = j; + } + } + } + std::vector path; + for (int i = end_id; i != start_id; i = prevs[i]) path.push_back(prevs[i]); + for (int i = 0; i < path.size() / 2; ++i) + std::swap(path[i], path[path.size() - 1 - i]); + return DeikstraReturn(path, pathLength[end_id]); +} + +DeikstraReturn DeikstraPathAlgorithm( + const OrientedWeightedGraphWithZeroWeight& graph, int start_id, + int end_id) { + if (start_id == end_id) return DeikstraReturn(std::vector(), 0); + int n = graph.GetVerts(); + std::vector ended(n); + std::vector pathLength(n, DBL_MAX); + std::vector prevs(n, -1); + pathLength[start_id] = 0; + int this_id = start_id; + for (int counter = 0; counter < n && this_id != end_id; ++counter) { + for (int i = 0; i < n; ++i) { + if (graph[this_id][i] && + pathLength[i] > pathLength[this_id] + graph.GetWeight(this_id, i)) { + pathLength[i] = pathLength[this_id] + graph.GetWeight(this_id, i); + prevs[i] = this_id; + } + } + ended[this_id] = true; + double min = DBL_MAX; + for (int j = 0; j < n; ++j) { + if (!ended[j]) + if (min > pathLength[j]) { + min = pathLength[j]; + this_id = j; + } + } + } + std::vector path; + path.push_back(end_id); + for (int i = end_id; i != start_id; i = prevs[i]) path.push_back(prevs[i]); + for (int i = 0; i < path.size() / 2; ++i) + std::swap(path[i], path[path.size() - 1 - i]); + return DeikstraReturn(path, pathLength[end_id]); +} diff --git a/lib/src/DeikstraAlgorithm.h b/lib/src/DeikstraAlgorithm.h new file mode 100644 index 0000000..61bf7d5 --- /dev/null +++ b/lib/src/DeikstraAlgorithm.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +struct DeikstraReturn { + std::vector path; + double pathLength; +}; + +double DeikstraAlgorithm(const WeightedGraph& graph, int start_id, int end_id); +double DeikstraAlgorithm(const OrientedWeightedGraphWithZeroWeight& graph, + int start_id, int end_id); +DeikstraReturn DeikstraPathAlgorithm(const WeightedGraph& graph, int start_id, + int end_id); +DeikstraReturn DeikstraPathAlgorithm( + const OrientedWeightedGraphWithZeroWeight& graph, int start_id, int end_id); diff --git a/lib/src/Graph.h b/lib/src/Graph.h new file mode 100644 index 0000000..6078a33 --- /dev/null +++ b/lib/src/Graph.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include + +class Graph : public WeightedGraph { + int GetEdges() { + int result = 0; + for (int i = 0; i < graph.size(); ++i) result += sum(graph[i]); + return result; + } +}; diff --git a/lib/src/GraphDFSIterator.cpp b/lib/src/GraphDFSIterator.cpp new file mode 100644 index 0000000..c8aa621 --- /dev/null +++ b/lib/src/GraphDFSIterator.cpp @@ -0,0 +1,31 @@ +#include + +GraphDFSIterator::GraphDFSIterator(const WeightedGraph* const graph, + int start_id) { + this->start_id = start_id; + this->graph = graph; + this->is_end = false; + this_id = start_id; + visited.resize(graph->GetVerts()); + visited[start_id] = true; + parent.resize(graph->GetVerts(), -1); +} + +int GraphDFSIterator::Next() { + for (int i = 0; i < graph->GetVerts(); ++i) { + if ((*graph)[this_id][i] != 0 && !visited[i]) { + visited[i] = true; + parent[i] = this_id; + this_id = i; + return i; + } + } + if (parent[this_id] == -1) { + is_end = true; + return this_id; + } + this_id = parent[this_id]; + return Next(); +} + +bool GraphDFSIterator::IsEnd() { return is_end; } diff --git a/lib/src/GraphDFSIterator.h b/lib/src/GraphDFSIterator.h new file mode 100644 index 0000000..a3bf147 --- /dev/null +++ b/lib/src/GraphDFSIterator.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#include + +class WeightedGraph; + +class GraphDFSIterator { + const WeightedGraph* graph; + int start_id; + int this_id; + bool is_end; + std::vector visited; + std::vector parent; + + int Next(); + + public: + GraphDFSIterator() = delete; + GraphDFSIterator(const WeightedGraph* const graph, int start_id); + + int operator++() { return Next(); } + int operator()() { return this_id; } + bool IsEnd(); +}; diff --git a/lib/src/JonsonAlgorithm.cpp b/lib/src/JonsonAlgorithm.cpp new file mode 100644 index 0000000..7654cac --- /dev/null +++ b/lib/src/JonsonAlgorithm.cpp @@ -0,0 +1,27 @@ +#include "JonsonAlgorithm.h" + +double GetPathLength(const WeightedGraph& graph, const std::vector& path) { + if (path.size() == 0) return 0; + double result = 0; + for (int i = 0; i < path.size() - 1; ++i) + result += graph[path[i]][path[i + 1]]; + return result; +} + +OrientedWeightedGraphWithZeroWeight JonsonAlgorithm( + const WeightedGraph& graph) { + int n = graph.GetVerts(); + OrientedWeightedGraphWithZeroWeight new_graph(graph); + for (int i = 0; i < n; ++i) new_graph.AddEdge(n, i, 0); + auto h = BellmanFordAlgorithm(new_graph, n); + if (h.size() == 0) return WeightedGraph(); + for (int i = 0; i < n; ++i) + for (int j = 0; j < n; ++j) new_graph.GetWeight(i, j) += h[i] - h[j]; + OrientedWeightedGraphWithZeroWeight resultGraph; + for (int i = 0; i < n; ++i) + for (int j = 0; j < n; ++j) + resultGraph.AddEdge( + i, j, + GetPathLength(graph, DeikstraPathAlgorithm(new_graph, i, j).path)); + return resultGraph; +} diff --git a/lib/src/JonsonAlgorithm.h b/lib/src/JonsonAlgorithm.h new file mode 100644 index 0000000..71392f9 --- /dev/null +++ b/lib/src/JonsonAlgorithm.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +#include "BellmanForlAlgorithm.h" +#include "DeikstraAlgorithm.h" + +OrientedWeightedGraphWithZeroWeight JonsonAlgorithm(const WeightedGraph& graph); diff --git a/lib/src/Lca.h b/lib/src/Lca.h new file mode 100644 index 0000000..8b36c94 --- /dev/null +++ b/lib/src/Lca.h @@ -0,0 +1,19 @@ +#pragma once + +struct Node { + int data; + Node* left; + Node* right; + Node(int val) { + data = val; + left = nullptr; + right = nullptr; + } +}; + +Node* LCA(Node* root, int n1, int n2) { + if (root == nullptr) return nullptr; + if (root->data > n1 && root->data > n2) return LCA(root->left, n1, n2); + if (root->data < n1 && root->data < n2) return LCA(root->right, n1, n2); + return root; +} diff --git a/lib/src/NonOrientedGraph.cpp b/lib/src/NonOrientedGraph.cpp new file mode 100644 index 0000000..6480764 --- /dev/null +++ b/lib/src/NonOrientedGraph.cpp @@ -0,0 +1,55 @@ +#include "NonOrientedGraph.h" + +bool NonOrientedGraph::IsCycled(int parent, int id, std::vector& result, + std::vector& visited) const { + for (int i = 0; i < graph.size(); ++i) { + if (graph[id][i] && !visited[i] && i != parent) { + visited[i] = true; + if (IsCycled(id, i, result, visited)) return true; + result.push_back(i); + } else if (graph[id][i] && visited[i] && i != id && i != parent) { + if (!in(result, i)) return true; + } + } + return false; +} + +bool NonOrientedGraph::IsCycled() const { + std::vector result; + std::vector visited(graph.size()); + visited[0] = true; + return IsCycled(0, 0, result, visited); +} + +bool NonOrientedGraph::AddVert(int id) { + if (id >= graph.size()) { + graph.resize(id + 1); + for (int i = 0; i < graph.size(); ++i) { + graph[i].resize(id + 1); + graph[i][i] = 1; + } + } + return false; +} + +bool NonOrientedGraph::AddEdge(int id0, int id1) { + if (id0 == id1) return true; + AddVert(std::max(id0, id1)); + graph[id0][id1] = 1; + graph[id1][id0] = 1; + return false; +} + +bool NonOrientedGraph::DeleteVert(int id) { + if (id >= graph.size()) return true; + graph.resize(id + 1); + for (int i = 0; i < graph.size(); ++i) graph[i].resize(id + 1); + return false; +} + +bool NonOrientedGraph::DeleteEdge(int id0, int id1) { + if (id0 == id1 || std::max(id0, id1) >= graph.size()) return true; + graph[id0][id1] = 0; + graph[id1][id0] = 0; + return false; +} diff --git a/lib/src/NonOrientedGraph.h b/lib/src/NonOrientedGraph.h new file mode 100644 index 0000000..50aff82 --- /dev/null +++ b/lib/src/NonOrientedGraph.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +#include "Graph.h" +#include "util.h" + +class NonOrientedGraph : public Graph { + private: + bool IsCycled(int parent, int id, std::vector& result, + std::vector& visited) const; + + public: + int GetEdges() { + int result = 0; + for (int i = 0; i < graph.size(); ++i) result += sum(graph[i]); + return result / 2; + } + bool AddVert(int id); + bool AddEdge(int id0, int id1); + bool DeleteVert(int id); + bool DeleteEdge(int id0, int id1); + + bool IsCycled() const; +}; diff --git a/lib/src/OrientedGraph.cpp b/lib/src/OrientedGraph.cpp new file mode 100644 index 0000000..bfea4d1 --- /dev/null +++ b/lib/src/OrientedGraph.cpp @@ -0,0 +1,32 @@ +#include "OrientedGraph.h" + +bool OrientedGraph::AddVert(int id) { + if (id >= graph.size()) { + graph.resize(id + 1); + for (int i = 0; i < graph.size(); ++i) { + graph[i].resize(id + 1); + graph[i][i] = 1; + } + } + return false; +} + +bool OrientedGraph::AddEdge(int id0, int id1) { + if (id0 == id1) return true; + AddVert(std::max(id0, id1)); + graph[id0][id1] = 1; + return false; +} + +bool OrientedGraph::DeleteVert(int id) { + if (id >= graph.size()) return true; + graph.resize(id + 1); + for (int i = 0; i < graph.size(); ++i) graph[i].resize(id + 1); + return false; +} + +bool OrientedGraph::DeleteEdge(int id0, int id1) { + if (id0 == id1 || std::max(id0, id1) >= graph.size()) return true; + graph[id0][id1] = 0; + return false; +} diff --git a/lib/src/OrientedGraph.h b/lib/src/OrientedGraph.h new file mode 100644 index 0000000..4697a24 --- /dev/null +++ b/lib/src/OrientedGraph.h @@ -0,0 +1,11 @@ +#pragma once + +#include "Graph.h" + +class OrientedGraph : public Graph { + public: + bool AddVert(int id); + bool AddEdge(int id0, int id1); + bool DeleteVert(int id); + bool DeleteEdge(int id0, int id1); +}; diff --git a/lib/src/RMQ.cpp b/lib/src/RMQ.cpp new file mode 100644 index 0000000..167b0e8 --- /dev/null +++ b/lib/src/RMQ.cpp @@ -0,0 +1,33 @@ +#include + +RMQ::RMQ(std::vector vec) : vector(vec), lookup(vec.size()) { + for (int i = 0; i < vec.size(); ++i) + lookup[i] = std::vector(vec.size()); + preprocess(); +} + +void RMQ::preprocess() { + for (int i = 0; i < vector.size(); i++) lookup[i][i] = i; + + for (int i = 0; i < vector.size(); i++) { + for (int j = i + 1; j < vector.size(); j++) + if (vector[lookup[i][j - 1]] < vector[j]) + lookup[i][j] = lookup[i][j - 1]; + else + lookup[i][j] = j; + } +} + +double RMQ::get_min(int i, int j) { return lookup[i][j]; } + +void RMQ::Print() { + for (int i = 0; i < vector.size(); ++i) { + std::cout << vector[i] << ", "; + } + std::cout << std::endl; + for (int i = 0; i < vector.size(); ++i) { + for (int j = 0; j < vector.size(); ++j) + std::cout << lookup[i][j] << '(' << vector[lookup[i][j]] << "), "; + std::cout << '\n'; + } +} diff --git a/lib/src/RMQ.h b/lib/src/RMQ.h new file mode 100644 index 0000000..8931871 --- /dev/null +++ b/lib/src/RMQ.h @@ -0,0 +1,16 @@ +#include +#include + +class RMQ { + std::vector vector; + std::vector> lookup; + + void preprocess(); + + public: + RMQ(std::vector vec); + RMQ() = delete; + + double get_min(int i, int j); + void Print(); +}; diff --git a/lib/src/SearchWeakVE.cpp b/lib/src/SearchWeakVE.cpp new file mode 100644 index 0000000..ea7a543 --- /dev/null +++ b/lib/src/SearchWeakVE.cpp @@ -0,0 +1,35 @@ +#include "SearchWeakVE.h" + +void dfs(WeakVE& result, const WeightedGraph& graph, int id, int parent, + std::vector& disc, std::vector& low, + std::vector& visited, int& time) { + disc[id] = time; + low[id] = time; + ++time; + visited[id] = true; + for (int i = 0; i < graph.GetVerts(); ++i) { + if (graph[id][i] && !visited[i]) { + dfs(result, graph, i, id, disc, low, visited, time); + low[id] = std::min(low[id], low[i]); + if (low[i] > disc[id]) result.second.push_back(std::make_pair(id, i)); + if (parent != -1 && low[i] >= disc[id]) result.first.push_back(id); + } else if (graph[id][i] && i != parent) + low[id] = std::min(low[id], low[i]); + } +} + +WeakVE SearchWeakVE(const WeightedGraph& graph) { + WeakVE result; + std::vector disc(graph.GetVerts()); + std::vector low(graph.GetVerts()); + std::vector visited(graph.GetVerts()); + int time = 0; + int start_id = 0; + dfs(result, graph, start_id, -1, disc, low, visited, time); + int num_start_id_daughters = 0; + for (int i = 0; i < graph.GetVerts(); ++i) { + if (graph[start_id][i] != 0) ++num_start_id_daughters; + } + if (num_start_id_daughters > 1) result.first.push_back(start_id); + return result; +} diff --git a/lib/src/SearchWeakVE.h b/lib/src/SearchWeakVE.h new file mode 100644 index 0000000..088c404 --- /dev/null +++ b/lib/src/SearchWeakVE.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#define WeakVE std::pair, std::vector>> + +WeakVE SearchWeakVE(const WeightedGraph& graph); diff --git a/lib/src/WeightedGraph.cpp b/lib/src/WeightedGraph.cpp new file mode 100644 index 0000000..5dc5a4b --- /dev/null +++ b/lib/src/WeightedGraph.cpp @@ -0,0 +1,118 @@ +#include "WeightedGraph.h" + +int WeightedGraph::GetEdges() const { + int result = 0; + for (int i = 0; i < graph.size(); ++i) + for (int j = 0; j < graph.size(); ++j) + if (graph[i][j]) ++result; + return result - graph.size(); +} + +bool WeightedGraph::IsCycled(int id, std::vector& result, + std::vector& visited) const { + for (int i = 0; i < graph.size(); ++i) { + if (graph[id][i] && !visited[i]) { + visited[i] = true; + if (IsCycled(i, result, visited)) return true; + result.push_back(i); + } else if (graph[id][i] && visited[i] && i != id) { + if (!in(result, i)) return true; + } + } + return false; +} + +bool WeightedGraph::IsCycled() const { + std::vector result; + std::vector visited(graph.size()); + visited[0] = true; + return IsCycled(0, result, visited); +} + +void WeightedGraph::Print() const { + for (int i = 0; i < graph.size(); ++i) { + for (int j = 0; j < graph.size(); ++j) std::cout << graph[i][j] << ", "; + std::cout << '\n'; + } +} + +bool WeightedGraph::SwapIds(int id0, int id1) { + if (std::max(id0, id1) >= graph.size() || id0 == id1) return true; + if (id0 > id1) std::swap(id0, id1); + + for (int i = 0; i < graph.size(); ++i) + std::swap(graph[i][id0], graph[i][id1]); + std::swap(graph[id0], graph[id1]); + return false; +} + +void WeightedGraph::DFS(int id, std::vector& result, + std::vector& visited, bool before) { + for (int i = 0; i < graph.size(); ++i) { + if (graph[id][i] && !visited[i]) { + visited[i] = true; + if (!before) result.push_back(i); + DFS(i, result, visited); + if (before) result.push_back(i); + } + } +} + +std::vector WeightedGraph::DFS(int id, bool before) { + std::vector visited(graph.size()); + std::vector result; + visited[id] = true; + if (!before) result.push_back(id); + + for (int i = 0; i < graph.size(); ++i) { + if (graph[id][i] && !visited[i]) { + visited[i] = true; + if (!before) result.push_back(i); + DFS(i, result, visited); + if (before) result.push_back(i); + } + } + if (before) result.push_back(id); + + return result; +} + +std::vector WeightedGraph::DFS(bool before) { return DFS(0, before); } + +void WeightedGraph::BFS(int id, std::vector& result, + std::vector& visited) { + std::vector need_visit; + for (int i = 0; i < graph.size(); ++i) { + if (graph[id][i] && !visited[i]) { + visited[i] = true; + result.push_back(i); + need_visit.push_back(i); + } + } + for (int i = 0; i < need_visit.size(); ++i) { + if (!visited[need_visit[i]]) BFS(need_visit[i], result, visited); + } +} + +std::vector WeightedGraph::BFS(int id) { + std::vector visited(graph.size()); + std::vector result; + visited[id] = true; + result.push_back(id); + + std::vector need_visit; + + for (int i = 0; i < graph.size(); ++i) { + if (graph[id][i] && !visited[i]) { + visited[i] = true; + result.push_back(i); + need_visit.push_back(i); + } + } + for (int i = 0; i < need_visit.size(); ++i) { + BFS(need_visit[i], result, visited); + } + return result; +} + +std::vector WeightedGraph::BFS() { return BFS(0); } diff --git a/lib/src/WeightedGraph.h b/lib/src/WeightedGraph.h new file mode 100644 index 0000000..0c9ec2d --- /dev/null +++ b/lib/src/WeightedGraph.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include +#include + +class WeightedGraph { + protected: + std::vector> graph; + + bool IsCycled(int id_start, std::vector& result, + std::vector& visited) const; + void DFS(int id_start, std::vector& result, std::vector& visited, + bool after = false); + void BFS(int id_start, std::vector& result, std::vector& visited); + + public: + const std::vector& operator[](int i) const { return graph[i]; } + std::vector& operator[](int i) { return graph[i]; } + int GetVerts() const { return graph.size(); } + int GetEdges() const; + bool IsCycled() const; + void Print() const; + + bool SwapIds(int id0, int id1); + + std::vector DFS(int id_start, bool after = false); + std::vector DFS(bool after = false); + std::vector BFS(int id_start); + std::vector BFS(); +}; diff --git a/lib/src/WeightedNonOrientedGraph.cpp b/lib/src/WeightedNonOrientedGraph.cpp new file mode 100644 index 0000000..daf021d --- /dev/null +++ b/lib/src/WeightedNonOrientedGraph.cpp @@ -0,0 +1,34 @@ +#include "WeightedNonOrientedGraph.h" + +bool WeightedNonOrientedGraph::AddVert(int id) { + if (id >= graph.size()) { + graph.resize(id + 1); + for (int i = 0; i < graph.size(); ++i) { + graph[i].resize(id + 1); + graph[i][i] = 1; + } + } + return false; +} + +bool WeightedNonOrientedGraph::AddEdge(int id0, int id1, double value) { + if (id0 == id1) return true; + AddVert(std::max(id0, id1)); + graph[id0][id1] = value; + graph[id1][id0] = value; + return false; +} + +bool WeightedNonOrientedGraph::DeleteVert(int id) { + if (id >= graph.size()) return true; + graph.resize(id + 1); + for (int i = 0; i < graph.size(); ++i) graph[i].resize(id + 1); + return false; +} + +bool WeightedNonOrientedGraph::DeleteEdge(int id0, int id1) { + if (id0 == id1 || std::max(id0, id1) >= graph.size()) return true; + graph[id0][id1] = 0; + graph[id1][id0] = 0; + return false; +} diff --git a/lib/src/WeightedNonOrientedGraph.h b/lib/src/WeightedNonOrientedGraph.h new file mode 100644 index 0000000..6aab16a --- /dev/null +++ b/lib/src/WeightedNonOrientedGraph.h @@ -0,0 +1,11 @@ +#pragma once + +#include "WeightedGraph.h" + +class WeightedNonOrientedGraph : public WeightedGraph { + public: + bool AddVert(int id); + bool AddEdge(int id0, int id1, double value); + bool DeleteVert(int id); + bool DeleteEdge(int id0, int id1); +}; diff --git a/lib/src/WeightedOrientedGraph.cpp b/lib/src/WeightedOrientedGraph.cpp new file mode 100644 index 0000000..2bf2257 --- /dev/null +++ b/lib/src/WeightedOrientedGraph.cpp @@ -0,0 +1,32 @@ +#include "WeightedOrientedGraph.h" + +bool WeightedOrientedGraph::AddVert(int id) { + if (id >= graph.size()) { + graph.resize(id + 1); + for (int i = 0; i < graph.size(); ++i) { + graph[i].resize(id + 1); + graph[i][i] = 1; + } + } + return false; +} + +bool WeightedOrientedGraph::AddEdge(int id0, int id1, double value) { + if (id0 == id1) return true; + AddVert(std::max(id0, id1)); + graph[id0][id1] = value; + return false; +} + +bool WeightedOrientedGraph::DeleteVert(int id) { + if (id >= graph.size()) return true; + graph.resize(id + 1); + for (int i = 0; i < graph.size(); ++i) graph[i].resize(id + 1); + return false; +} + +bool WeightedOrientedGraph::DeleteEdge(int id0, int id1) { + if (id0 == id1 || std::max(id0, id1) >= graph.size()) return true; + graph[id0][id1] = 0; + return false; +} diff --git a/lib/src/WeightedOrientedGraph.h b/lib/src/WeightedOrientedGraph.h new file mode 100644 index 0000000..fd9fd07 --- /dev/null +++ b/lib/src/WeightedOrientedGraph.h @@ -0,0 +1,11 @@ +#pragma once + +#include "WeightedGraph.h" + +class WeightedOrientedGraph : public WeightedGraph { + public: + bool AddVert(int id); + bool AddEdge(int id0, int id1, double value); + bool DeleteVert(int id); + bool DeleteEdge(int id0, int id1); +}; diff --git a/lib/src/WeightedOrientedGraphWithZeroWeight.cpp b/lib/src/WeightedOrientedGraphWithZeroWeight.cpp new file mode 100644 index 0000000..2a9cb02 --- /dev/null +++ b/lib/src/WeightedOrientedGraphWithZeroWeight.cpp @@ -0,0 +1,66 @@ +#include "WeightedOrientedGraphWithZeroWeight.h" + +OrientedWeightedGraphWithZeroWeight::OrientedWeightedGraphWithZeroWeight( + const WeightedGraph& graph) { + int n = graph.GetVerts(); + this->graph.resize(n); + this->weight_graph.resize(n); + for (int i = 0; i < n; ++i) { + this->graph[i].resize(n); + this->weight_graph[i].resize(n); + for (int j = 0; j < n; ++j) + if (graph[i][j]) { + this->graph[i][j] = 1; + this->weight_graph[i][j] = graph[i][j]; + } + } +} + +bool OrientedWeightedGraphWithZeroWeight::AddVert(int id) { + if (id >= graph.size()) { + graph.resize(id + 1); + weight_graph.resize(id + 1); + for (int i = 0; i < graph.size(); ++i) { + graph[i].resize(id + 1); + weight_graph[i].resize(id + 1); + graph[i][i] = 1; + } + } + return false; +} + +bool OrientedWeightedGraphWithZeroWeight::AddEdge(int id0, int id1, + double value) { + if (id0 == id1) return true; + AddVert(std::max(id0, id1)); + graph[id0][id1] = 1; + weight_graph[id0][id1] = value; + return false; +} + +bool OrientedWeightedGraphWithZeroWeight::DeleteVert(int id) { + if (id >= graph.size()) return true; + graph.resize(id + 1); + weight_graph.resize(id + 1); + for (int i = 0; i < graph.size(); ++i) { + graph[i].resize(id + 1); + weight_graph[i].resize(id + 1); + } + return false; +} + +bool OrientedWeightedGraphWithZeroWeight::DeleteEdge(int id0, int id1) { + if (id0 == id1 || std::max(id0, id1) >= graph.size()) return true; + graph[id0][id1] = 0; + weight_graph[id0][id1] = 0; + return false; +} + +void OrientedWeightedGraphWithZeroWeight::Print() { + for (int i = 0; i < graph.size(); ++i) { + for (int j = 0; j < graph.size(); ++j) + std::cout << "(" << graph[i][j] << ", " << weight_graph[i][j] << "), "; + std::cout << std::endl; + } + std::cout << std::endl; +} diff --git a/lib/src/WeightedOrientedGraphWithZeroWeight.h b/lib/src/WeightedOrientedGraphWithZeroWeight.h new file mode 100644 index 0000000..13f595b --- /dev/null +++ b/lib/src/WeightedOrientedGraphWithZeroWeight.h @@ -0,0 +1,26 @@ +#pragma once + +#include "WeightedGraph.h" + +class OrientedWeightedGraphWithZeroWeight { + private: + std::vector> graph; + std::vector> weight_graph; + + public: + OrientedWeightedGraphWithZeroWeight() = default; + OrientedWeightedGraphWithZeroWeight(const WeightedGraph& graph); + + const std::vector& operator[](int i) const { return graph[i]; } + std::vector& operator[](int i) { return graph[i]; } + int GetVerts() const { return graph.size(); } + void Print(); + + bool AddVert(int id); + bool AddEdge(int id0, int id1, double value); + bool DeleteVert(int id); + bool DeleteEdge(int id0, int id1); + + double GetWeight(int i, int j) const { return weight_graph[i][j]; } + double& GetWeight(int i, int j) { return weight_graph[i][j]; } +}; diff --git a/lib/src/includes.h b/lib/src/includes.h new file mode 100644 index 0000000..75bb903 --- /dev/null +++ b/lib/src/includes.h @@ -0,0 +1,11 @@ +#pragma once + +#include "Graph.h" +#include "GraphDFSIterator.h" +#include "NonOrientedGraph.h" +#include "OrientedGraph.h" +#include "WeightedGraph.h" +#include "WeightedNonOrientedGraph.h" +#include "WeightedOrientedGraph.h" +#include "WeightedOrientedGraphWithZeroWeight.h" +#include "util.h" diff --git a/lib/src/topologicalSort.cpp b/lib/src/topologicalSort.cpp new file mode 100644 index 0000000..5f7a1ac --- /dev/null +++ b/lib/src/topologicalSort.cpp @@ -0,0 +1,34 @@ +#include "topologicalSort.h" + +std::vector topologicalSort(WeightedGraph& graph) { + if (graph.IsCycled()) return std::vector{-1}; + + auto dfs = graph.DFS(true); + std::vector rdfs(dfs.size()); + for (int i = 0; i < dfs.size(); ++i) rdfs[graph.GetVerts() - 1 - i] = dfs[i]; + return rdfs; +} + +bool topologicalSorted(WeightedGraph& graph) { + auto rdfs = topologicalSort(graph); + if (rdfs.size() == 1 && rdfs[0] == -1) return true; + std::vector positions(graph.GetVerts()); + for (int i = 0; i < graph.GetVerts(); ++i) positions[i] = i; + for (int i = 0; i < graph.GetVerts(); ++i) { + int finded_id = -1; + for (int j = i; j < positions.size(); ++j) + if (positions[j] == rdfs[i]) { + finded_id = j; + break; + } + graph.SwapIds(i, finded_id); + std::swap(positions[i], positions[finded_id]); + } + return false; +} + +WeightedGraph* topologicalSorting(WeightedGraph& graph) { + WeightedGraph* new_graph = new WeightedGraph(graph); + if (topologicalSorted(*new_graph)) return nullptr; + return new_graph; +} diff --git a/lib/src/topologicalSort.h b/lib/src/topologicalSort.h new file mode 100644 index 0000000..3b9517d --- /dev/null +++ b/lib/src/topologicalSort.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +std::vector topologicalSort(WeightedGraph& graph); +bool topologicalSorted(WeightedGraph& graph); +WeightedGraph* topologicalSorting(WeightedGraph& graph); diff --git a/lib/src/util.cpp b/lib/src/util.cpp index 81e15bd..a848d1e 100644 --- a/lib/src/util.cpp +++ b/lib/src/util.cpp @@ -1 +1,44 @@ -#include "util.hpp" +#include "util.h" + +int partition(std::vector& vec, int low, int high) { + int pivot = vec[high]; + int i = (low - 1); + + for (int j = low; j <= high - 1; j++) { + if (vec[j] <= pivot) { + i++; + std::swap(vec[i], vec[j]); + } + } + std::swap(vec[i + 1], vec[high]); + return (i + 1); +} + +void quickSort(std::vector& vec, int low, int high) { + if (low < high) { + int pi = partition(vec, low, high); + quickSort(vec, low, pi - 1); + quickSort(vec, pi + 1, high); + } +} + +void bubbleSort(std::vector& vec) { + int n = vec.size(); + for (int i = 0; i < n - 1; i++) { + for (int j = 0; j < n - i - 1; j++) { + if (vec[j] > vec[j + 1]) std::swap(vec[j], vec[j + 1]); + } + } +} + +bool in(const std::vector& vec, int value) { + for (int i = 0; i < vec.size(); ++i) + if (vec[i] == value) return true; + return false; +} + +int sum(const std::vector& vec) { + int result = 0; + for (auto value : vec) result += value; + return result; +} diff --git a/lib/src/util.h b/lib/src/util.h new file mode 100644 index 0000000..b264ede --- /dev/null +++ b/lib/src/util.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +int partition(std::vector& vec, int low, int high); +void quickSort(std::vector& vec, int low, int high); + +void bubbleSort(std::vector& vec); + +bool in(const std::vector& vec, int value); + +int sum(const std::vector& vec); diff --git a/lib/src/util.hpp b/lib/src/util.hpp deleted file mode 100644 index e69de29..0000000 diff --git a/task_01/CMakeLists.txt b/task_01/CMakeLists.txt index 6612735..8f28021 100644 --- a/task_01/CMakeLists.txt +++ b/task_01/CMakeLists.txt @@ -17,7 +17,7 @@ list(REMOVE_ITEM source_list ${test_list}) include_directories(${PROJECT_NAME} PUBLIC src) -add_executable(${PROJECT_NAME} ${source_list}) +add_executable(${PROJECT_NAME} ${source_list} "../lib/src/topologicalSort.cpp") # Locate GTest enable_testing() @@ -29,7 +29,7 @@ find_library(Utils ../) target_link_libraries(${PROJECT_NAME} PUBLIC Utils) # Link runTests with what we want to test and the GTest and pthread library -add_executable(${PROJECT_NAME}_tests ${test_source_list}) +add_executable(${PROJECT_NAME}_tests ${test_source_list} "../lib/src/topologicalSort.cpp") target_link_libraries( ${PROJECT_NAME}_tests GTest::gtest_main diff --git a/task_01/src/main.cpp b/task_01/src/main.cpp index 76e8197..4171d95 100644 --- a/task_01/src/main.cpp +++ b/task_01/src/main.cpp @@ -1 +1,34 @@ -int main() { return 0; } +#include +#include + +std::ostream& operator<<(std::ostream& os, const std::vector& vec) { + for (int i = 0; i < vec.size(); ++i) os << vec[i] << ", "; + return os; +} + +int main() { + OrientedGraph graph; + graph.AddEdge(0, 3); + graph.AddEdge(3, 1); + graph.AddEdge(3, 2); + graph.AddEdge(2, 1); + graph.Print(); + std::cout << std::endl; + + std::cout << "DFS ITERATION: "; + for (auto iter = GraphDFSIterator(&graph, 0); !iter.IsEnd(); ++iter) { + std::cout << iter() << ", "; + } + std::cout << std::endl; + + std::cout << "IsCycled: " << graph.IsCycled() << std::endl; + + std::cout << "DFS: " << graph.DFS() << std::endl; + std::cout << "after DFS: " << graph.DFS(true) << std::endl; + std::cout << "BFS: " << graph.BFS() << std::endl; + + auto top_graph = topologicalSort(graph); + std::cout << "topological sort: " << top_graph << std::endl; + topologicalSorted(graph); + graph.Print(); +} diff --git a/task_01/src/test.cpp b/task_01/src/test.cpp index 87cef73..1fd7584 100644 --- a/task_01/src/test.cpp +++ b/task_01/src/test.cpp @@ -1,5 +1,13 @@ #include +#include +#include -TEST(Test, Simple) { - ASSERT_EQ(1, 1); // Stack [] -} \ No newline at end of file +TEST(TopologicalSortTest, Simple) { + OrientedGraph graph; + graph.AddEdge(0, 3); + graph.AddEdge(3, 1); + graph.AddEdge(3, 2); + graph.AddEdge(2, 1); + ASSERT_EQ(topologicalSort(graph), + std::vector({0, 3, 2, 1})); // Stack [] +} diff --git a/task_02/README.md b/task_02/README.md index 281bafb..2691b57 100644 --- a/task_02/README.md +++ b/task_02/README.md @@ -1,3 +1,3 @@ -# Задача: + # Задача: В городе N горожане одного из районов создали локальную сеть для того, чтобы обмениваться информацией и играть вместе по сети. У них было n роутеров. Между роутерами как-то были проложены кабели. Когда-то один нерадивый коммунальщик перерезал один из проводов, и сеть стала не связной. Пользователи восстановили этот провод и решили найти узкие места сети для того, чтобы позже устранить их. Для этого они решили найти провода, при повреждении которых сеть потеряет связность, и заодно ещё найти те роутеры, при выходе из строя которых сеть также потеряет связность. Задача состоит в том, чтобы помочь пользователям сделать свою сеть надежнее. \ No newline at end of file diff --git a/task_02/src/main.cpp b/task_02/src/main.cpp index 0e4393b..00a292e 100644 --- a/task_02/src/main.cpp +++ b/task_02/src/main.cpp @@ -1,3 +1,31 @@ +#include +#include + #include -int main() { return 0; } +int main() { + NonOrientedGraph graph; + graph.AddEdge(0, 1); + graph.AddEdge(0, 2); + graph.AddEdge(1, 2); + graph.AddEdge(2, 3); + graph.AddEdge(3, 4); + graph.AddEdge(0, 1); + graph.AddEdge(1, 2); + graph.AddEdge(0, 2); + graph.AddEdge(2, 3); + graph.AddEdge(3, 4); + graph.AddEdge(3, 5); + graph.AddEdge(4, 5); + graph.Print(); + WeakVE result = SearchWeakVE(graph); + std::cout << "Weak Points: "; + for (int i = 0; i < result.first.size(); ++i) + std::cout << result.first[i] << ", "; + std::cout << "\nWeak Edges: "; + for (int i = 0; i < result.second.size(); ++i) + std::cout << "(" << result.second[i].first << ", " + << result.second[i].second << "); "; + std::cout << std::endl; + return 0; +} diff --git a/task_02/src/stack.cpp b/task_02/src/stack.cpp deleted file mode 100644 index 8ca8990..0000000 --- a/task_02/src/stack.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "stack.hpp" - -#include - -void Stack::Push(int value) { data_.push(value); } - -int Stack::Pop() { - auto result = data_.top(); - data_.pop(); - return result; -} - -void MinStack::Push(int value) { data_.push_back(value); } - -int MinStack::Pop() { - auto result = data_.back(); - data_.pop_back(); - return result; -} - -int MinStack::GetMin() { return *std::min_element(data_.begin(), data_.end()); } \ No newline at end of file diff --git a/task_02/src/stack.hpp b/task_02/src/stack.hpp deleted file mode 100644 index 138ec40..0000000 --- a/task_02/src/stack.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include - -class Stack { - public: - void Push(int value); - int Pop(); - - private: - std::stack data_; -}; - -class MinStack { - public: - void Push(int value); - int Pop(); - int GetMin(); - - private: - std::vector data_; -}; diff --git a/task_02/src/test.cpp b/task_02/src/test.cpp index 54e7ce9..0397f0f 100644 --- a/task_02/src/test.cpp +++ b/task_02/src/test.cpp @@ -1,42 +1,23 @@ - +#include #include +#include -#include - -#include "stack.hpp" - -TEST(StackTest, Simple) { - Stack stack; - stack.Push(1); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] - stack.Push(1); // Stack [1] - stack.Push(2); // Stack [1, 2] - ASSERT_EQ(stack.Pop(), 2); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] - stack.Push(1); // Stack [1] - stack.Push(2); // Stack [1, 2] - ASSERT_EQ(stack.Pop(), 2); // Stack [1] - stack.Push(3); // Stack [1, 3] - ASSERT_EQ(stack.Pop(), 3); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] +TEST(SearchWeakVETest, Simple) { + NonOrientedGraph graph; + graph.AddEdge(0, 1); + graph.AddEdge(0, 2); + graph.AddEdge(1, 2); + graph.AddEdge(2, 3); + graph.AddEdge(3, 4); + graph.AddEdge(0, 1); + graph.AddEdge(1, 2); + graph.AddEdge(0, 2); + graph.AddEdge(2, 3); + graph.AddEdge(3, 4); + graph.AddEdge(3, 5); + graph.AddEdge(4, 5); + WeakVE result = SearchWeakVE(graph); + WeakVE true_result = WeakVE({{3, 2, 0}, {{2, 3}}}); + ASSERT_EQ(result.first, true_result.first); + ASSERT_EQ(result.second, true_result.second); } - -TEST(MinStackTest, Simple) { - MinStack stack; - stack.Push(1); // Stack [1] - ASSERT_EQ(stack.GetMin(), 1); - ASSERT_EQ(stack.Pop(), 1); // Stack [] - stack.Push(1); // Stack [1] - stack.Push(2); // Stack [1, 2] - ASSERT_EQ(stack.GetMin(), 1); - ASSERT_EQ(stack.Pop(), 2); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] - stack.Push(1); // Stack [1] - stack.Push(2); // Stack [1, 2] - ASSERT_EQ(stack.GetMin(), 1); - ASSERT_EQ(stack.Pop(), 2); // Stack [1] - stack.Push(3); // Stack [1, 3] - ASSERT_EQ(stack.GetMin(), 1); - ASSERT_EQ(stack.Pop(), 3); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] -} \ No newline at end of file diff --git a/task_03/src/main.cpp b/task_03/src/main.cpp index 0e4393b..9173904 100644 --- a/task_03/src/main.cpp +++ b/task_03/src/main.cpp @@ -1,3 +1,54 @@ +#include +#include +#include +#include + #include -int main() { return 0; } +int main() { + WeightedNonOrientedGraph graph; + graph.AddEdge(0, 1, 10); + graph.AddEdge(0, 2, 2); + graph.AddEdge(0, 3, 7); + graph.AddEdge(0, 4, 8); + graph.AddEdge(1, 3, 1); + graph.AddEdge(1, 5, 5); + graph.AddEdge(2, 3, 3); + graph.AddEdge(2, 4, 5); + graph.AddEdge(3, 4, 1); + graph.AddEdge(3, 5, 4); + graph.AddEdge(4, 5, 2); + + auto bf = BellmanFordAlgorithm(graph, 0); + auto deikstra = DeikstraPathAlgorithm(graph, 0, 5); + + graph.Print(); + std::cout << "Deikstra: " << deikstra.pathLength << std::endl; + for (int i = 0; i < deikstra.path.size(); ++i) + std::cout << deikstra.path[i] << ", "; + std::cout << std::endl; + std::cout << "Bellman Ford: "; + for (int i = 0; i < bf.size(); ++i) std::cout << bf[i] << ", "; + std::cout << std::endl; + + WeightedOrientedGraph secondGraph; + secondGraph.AddEdge(0, 1, 2); + secondGraph.AddEdge(0, 2, 3); + secondGraph.AddEdge(1, 0, -1); + secondGraph.AddEdge(1, 2, 4); + secondGraph.AddEdge(2, 0, -2); + secondGraph.AddEdge(2, 1, 1); + + bf = BellmanFordAlgorithm(secondGraph, 0); + + secondGraph.Print(); + std::cout << "Bellman Ford: "; + for (int i = 0; i < bf.size(); ++i) std::cout << bf[i] << ", "; + std::cout << std::endl; + std::cout << "Jonson: " << std::endl; + auto jons = JonsonAlgorithm(secondGraph); + jons.Print(); + std::cout << std::endl; + + return 0; +} diff --git a/task_03/src/test.cpp b/task_03/src/test.cpp index ef5a86a..d97de9b 100644 --- a/task_03/src/test.cpp +++ b/task_03/src/test.cpp @@ -1,8 +1,35 @@ - +#include #include +#include + +bool operator==(const OrientedWeightedGraphWithZeroWeight& first, + const OrientedWeightedGraphWithZeroWeight& second) { + if (first.GetVerts() != second.GetVerts()) return false; + for (int i = 0; i < first.GetVerts(); ++i) + for (int j = 0; j < first.GetVerts(); ++j) + if (first[i][j] != second[i][j] || + first.GetWeight(i, j) != second.GetWeight(i, j)) + return false; + return true; +} + +TEST(JonsonAlgorithmTest, Simple) { + WeightedOrientedGraph test_graph; + test_graph.AddEdge(0, 1, 2); + test_graph.AddEdge(0, 2, 3); + test_graph.AddEdge(1, 0, -1); + test_graph.AddEdge(1, 2, 4); + test_graph.AddEdge(2, 0, -2); + test_graph.AddEdge(2, 1, 1); + auto jons_graph = JonsonAlgorithm(test_graph); -#include "topology_sort.hpp" + OrientedWeightedGraphWithZeroWeight true_jons_graph; + true_jons_graph.AddEdge(0, 1, 2); + true_jons_graph.AddEdge(0, 2, 3); + true_jons_graph.AddEdge(1, 0, -1); + true_jons_graph.AddEdge(1, 2, 2); + true_jons_graph.AddEdge(2, 0, -2); + true_jons_graph.AddEdge(2, 1, 0); -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] + ASSERT_EQ(jons_graph, true_jons_graph); } diff --git a/task_03/src/topology_sort.cpp b/task_03/src/topology_sort.cpp deleted file mode 100644 index e53f670..0000000 --- a/task_03/src/topology_sort.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "topology_sort.hpp" diff --git a/task_03/src/topology_sort.hpp b/task_03/src/topology_sort.hpp deleted file mode 100644 index 6f70f09..0000000 --- a/task_03/src/topology_sort.hpp +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/task_04/src/main.cpp b/task_04/src/main.cpp index 0e4393b..1d5bba5 100644 --- a/task_04/src/main.cpp +++ b/task_04/src/main.cpp @@ -1,3 +1,26 @@ +#include + #include -int main() { return 0; } +int main() { + WeightedNonOrientedGraph graph; + graph.AddEdge(0, 1, 10); + graph.AddEdge(0, 2, 2); + graph.AddEdge(0, 3, 7); + graph.AddEdge(0, 4, 8); + graph.AddEdge(1, 3, 1); + graph.AddEdge(1, 5, 5); + graph.AddEdge(2, 3, 3); + graph.AddEdge(2, 4, 5); + graph.AddEdge(3, 4, 1); + graph.AddEdge(3, 5, 4); + graph.AddEdge(4, 5, 2); + + auto deikstra = DeikstraPathAlgorithm(graph, 0, 5); + + graph.Print(); + std::cout << "Deikstra: " << deikstra.pathLength << std::endl; + for (int i = 0; i < deikstra.path.size(); ++i) + std::cout << deikstra.path[i] << ", "; + std::cout << std::endl; +} diff --git a/task_04/src/test.cpp b/task_04/src/test.cpp index 5e11617..2db72f4 100644 --- a/task_04/src/test.cpp +++ b/task_04/src/test.cpp @@ -1,6 +1,29 @@ - #include +#include + +#include "DeikstraAlgorithm.h" + +bool operator==(const DeikstraReturn& first, const DeikstraReturn& second) { + if (first.path != second.path || first.pathLength != second.pathLength) + return false; + return true; +} + +TEST(DeikstraAlgorithmTest, Simple) { + WeightedNonOrientedGraph graph; + graph.AddEdge(0, 1, 10); + graph.AddEdge(0, 2, 2); + graph.AddEdge(0, 3, 7); + graph.AddEdge(0, 4, 8); + graph.AddEdge(1, 3, 1); + graph.AddEdge(1, 5, 5); + graph.AddEdge(2, 3, 3); + graph.AddEdge(2, 4, 5); + graph.AddEdge(3, 4, 1); + graph.AddEdge(3, 5, 4); + graph.AddEdge(4, 5, 2); -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] + auto deikstra = DeikstraPathAlgorithm(graph, 0, 5); + DeikstraReturn true_deikstra({0, 2, 3, 4}, 8); + ASSERT_EQ(deikstra, true_deikstra); } diff --git a/task_05/src/main.cpp b/task_05/src/main.cpp index 0e4393b..cc1c4a5 100644 --- a/task_05/src/main.cpp +++ b/task_05/src/main.cpp @@ -1,3 +1,8 @@ -#include +#include -int main() { return 0; } +int main() { + std::vector a = {1, 3, 2, 7, 9, 11, 5, 4, 6, 8}; + RMQ rmq(a); + rmq.Print(); + return 0; +} diff --git a/task_05/src/test.cpp b/task_05/src/test.cpp index 5e11617..2fd7fde 100644 --- a/task_05/src/test.cpp +++ b/task_05/src/test.cpp @@ -1,6 +1,13 @@ - +#include #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(RMQTest, Simple) { + std::vector testArray = {1, 3, 2, 7, 9, 11, 5, 4, 6, 8}; + RMQ testRMQ(testArray); + ASSERT_EQ(testRMQ.get_min(0, 5), 0); + ASSERT_EQ(testRMQ.get_min(3, 7), 7); + ASSERT_EQ(testRMQ.get_min(7, 8), 7); + ASSERT_EQ(testRMQ.get_min(2, 2), 2); + ASSERT_EQ(testRMQ.get_min(3, 5), 3); + ASSERT_EQ(testRMQ.get_min(5, 9), 7); } diff --git a/task_06/src/main.cpp b/task_06/src/main.cpp index 0e4393b..4caec39 100644 --- a/task_06/src/main.cpp +++ b/task_06/src/main.cpp @@ -1,3 +1,27 @@ +#include + #include -int main() { return 0; } +int main() { + Node* root = new Node(20); + root->left = new Node(8); + root->right = new Node(22); + root->left->left = new Node(4); + root->left->right = new Node(12); + root->left->right->left = new Node(10); + root->left->right->right = new Node(14); + + int n1 = 10, n2 = 14; + Node* t = LCA(root, n1, n2); + std::cout << n1 << " < " << t->data << " < " << n2 << std::endl; + + n1 = 14, n2 = 8; + t = LCA(root, n1, n2); + std::cout << n1 << " < " << t->data << " < " << n2 << std::endl; + + n1 = 10, n2 = 22; + t = LCA(root, n1, n2); + std::cout << n1 << " < " << t->data << " < " << n2 << std::endl; + + return 0; +} diff --git a/task_06/src/test.cpp b/task_06/src/test.cpp index 5e11617..8bea184 100644 --- a/task_06/src/test.cpp +++ b/task_06/src/test.cpp @@ -1,6 +1,24 @@ - +#include #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(LCATest, Simple) { + Node* root = new Node(20); + root->left = new Node(8); + root->right = new Node(22); + root->left->left = new Node(4); + root->left->right = new Node(12); + root->left->right->left = new Node(10); + root->left->right->right = new Node(14); + + int n1 = 10, n2 = 14; + Node* t = LCA(root, n1, n2); + ASSERT_EQ(t->data, 12); + + n1 = 8, n2 = 14; + t = LCA(root, n1, n2); + ASSERT_EQ(t->data, 8); + + n1 = 10, n2 = 22; + t = LCA(root, n1, n2); + ASSERT_EQ(t->data, 20); }