diff --git "a/D-\320\272\321\203\321\207\320\270.doc" "b/D-\320\272\321\203\321\207\320\270.doc" new file mode 100644 index 000000000..2638d5979 Binary files /dev/null and "b/D-\320\272\321\203\321\207\320\270.doc" differ diff --git a/include/DHBPQ.h b/include/DHBPQ.h new file mode 100644 index 000000000..ca2e5c3d6 --- /dev/null +++ b/include/DHBPQ.h @@ -0,0 +1,42 @@ +#pragma once +#include "priority_queue.h" +#include "dheap.h" + +template +class DHBPQ : public priority_queue +{ + dheap heap; +public: + DHBPQ() = default; + DHBPQ(vector elems, int d); + bool is_full() const override; + bool is_empty() const override; + void push(T a) override; + T pop() override; +}; + +template +DHBPQ::DHBPQ(vector elems, int d) { + heap = dheap(elems, d); +} + +template +bool DHBPQ::is_full() const { + return false; +} + +template +bool DHBPQ::is_empty() const { + return heap.is_empty(); +} + +template +void DHBPQ::push(T a) { + heap.insert(a); +} + +template +T DHBPQ::pop() { + T a = heap.get_min_value(); + return a; +} diff --git a/include/dheap.h b/include/dheap.h new file mode 100644 index 000000000..8f0b12a2f --- /dev/null +++ b/include/dheap.h @@ -0,0 +1,111 @@ +#pragma once +#include +#include +using namespace std; + +template +class dheap +{ + vector keys; + int d; +public: + dheap(); + dheap(vector keys, int d); + dheap(const dheap& heap) = default; + void sink(int idx); + void rise(int idx); + void transpose(int idx1, int idx2); + void hilling(); + void insert(T key); + void remove(int idx); + T get_min_value(); + int minchild(int idx); + bool is_empty() const; +}; + +template +dheap::dheap() : d(3) { +} + +template +dheap::dheap(vector keys, int d) { + this->d = d; + this->keys = keys; + hilling(); +} + +template +void dheap::sink(int idx) { + int c = minchild(idx); + while (c != -1 && keys[c] < keys[idx]) { + transpose(c, idx); + idx = c; + c = minchild(idx); + } +} + +template +void dheap::rise(int idx) { + int p = (idx - 1) / d; + while (p > 0) { + if (keys[idx] < keys[p]) { + transpose(p, idx); + } + idx = p; + p = (idx - 1) / d; + } +} + +template +void dheap::transpose(int idx1, int idx2) { + swap(keys[idx1], keys[idx2]); +} + +template +void dheap::hilling() { + for (int i = keys.size() - 1; i >= 0; i--) { + sink(i); + } +} + +template +void dheap::insert(T key) { + keys.push_back(key); + rise(keys.size() - 1); +} + +template +void dheap::remove(int idx) { + if (idx < 0 || idx >= keys.size()) throw "Index error"; + + swap(keys.back(), keys[idx]); + keys.pop_back(); + sink(idx); +} + +template +T dheap::get_min_value() { + T tmp = keys.front(); + swap(keys.front(), keys.back()); + keys.pop_back(); + sink(0); + return tmp; +} + +template +int dheap::minchild(int idx) { + if (idx * d + 1 >= keys.size()) return -1; + int minidx = idx * d + 1; + int idx1 = idx * d + 1; + int idx2 = min(idx * d + d, (int)keys.size() - 1); + for (int i = idx1; i <= idx2; i++) { + if (keys[i] < keys[minidx]) + minidx = i; + } + return minidx; +} + +template +bool dheap::is_empty() const { + return keys.empty(); +} diff --git a/include/edge.h b/include/edge.h new file mode 100644 index 000000000..956b2212a --- /dev/null +++ b/include/edge.h @@ -0,0 +1,32 @@ +#pragma once +#include +using namespace std; + +struct edge +{ + int begin; + int end; + double weight; + + bool operator <(const edge& A) const { + return weight < A.weight; + } + + edge() = default; + + edge(int begin, int end, double weight) { + this->begin = begin; + this->end = end; + this->weight = weight; + } + + friend ostream& operator<<(ostream& o, const edge& e) { + o << "start = " << e.begin << ", weight = " << e.weight << ", finish = " << e.end; + return o; + } + + bool operator ==(const edge& a) const { + return begin == a.begin && end == a.end || + end == a.begin && begin == a.end; + } +}; diff --git a/include/graph.h b/include/graph.h new file mode 100644 index 000000000..50c057ae7 --- /dev/null +++ b/include/graph.h @@ -0,0 +1,33 @@ +#pragma once +#include"edge.h" +#include +using namespace std; + +struct vertex +{ + int point_index = 0; + double distance = 0; + int from = -1; + + vertex(int point_index, double distance, int from) + : point_index(point_index), distance(distance), from(from) { + } + + bool operator<(const vertex& p) const { return distance < p.distance; } +}; + + +class graph +{ + void generate(int n, int m); + vector edges; + vector points; +public: + graph(int n, int m); + graph(vector edges); + int points_size() const; + int edges_size() const; + vector get_edges() const; + vector get_points() const; + void print(); +}; diff --git a/include/priority_queue.h b/include/priority_queue.h new file mode 100644 index 000000000..9b69e8305 --- /dev/null +++ b/include/priority_queue.h @@ -0,0 +1,10 @@ +#pragma once +template +class priority_queue +{ +public: + virtual bool is_full() const = 0; + virtual bool is_empty() const = 0; + virtual void push(T a) = 0; + virtual T pop() = 0; +}; diff --git a/src/deikstra.cpp b/src/deikstra.cpp new file mode 100644 index 000000000..7447276c9 --- /dev/null +++ b/src/deikstra.cpp @@ -0,0 +1,90 @@ +#include +#include +#include + +using namespace std; + +vector alg_deikstra(const graph& g, const int start) { + vector points = g.get_points(); + int n = points.size(); + vector> matrix = vector>(n); + for (int i = 0; i < n; i++) { + matrix[i] = vector(n, 0); + } + + vector edges = g.get_edges(); + int m = edges.size(); + for (int i = 0; i < m; i++) { + matrix[edges[i].begin][edges[i].end] = edges[i].weight; + matrix[edges[i].end][edges[i].begin] = edges[i].weight; + } + + vector distance = vector(g.points_size(), numeric_limits::infinity()); + vector from = vector(g.points_size(), -1); + + distance[start] = 0; + + DHBPQ queue = DHBPQ(); + queue.push(vertex(start, distance[start], from[start])); + + while (!queue.is_empty()) { + const vertex p = queue.pop(); + vector& weight = matrix[p.point_index]; + for (unsigned int i = 0; i < weight.size(); i++) { + if (weight[i] == 0) + continue; + + const double new_dist = distance[p.point_index] + weight[i]; + if (new_dist < distance[i]) { + distance[i] = new_dist; + from[i] = p.point_index; + queue.push(vertex(i, distance[i], from[i])); + } + } + } + + vector result = vector(); + result.reserve(n); + for (int i = 0; i < n; i++) { + result.push_back(vertex(points[i], distance[i], from[i])); + } + return result; +} + + +int main() { + char IsEnded = 'y'; + int n, m; + while (IsEnded == 'Y' || IsEnded == 'y') + { + cout << "Enter n,m" << endl; + cin >> n >> m; + try { + graph g = graph(n, m); + g.print(); + vector v = alg_deikstra(g, 0); + + + cout << "Point: "; + for (int i = 0; i < v.size(); i++) { + cout.width(4); + cout << v[i].point_index; + } + cout << endl << "Distance: "; + for (int i = 0; i < v.size(); i++) { + cout.width(4); + cout << v[i].distance; + } + cout << endl << "From: "; + for (int i = 0; i < v.size(); i++) { + cout.width(4); + cout << v[i].from; + } + } + catch (exception& l) { cout << l.what() << endl; } + cout << endl; + cout << "Do u wanna try again (Y/N)" << endl; + cin >> IsEnded; + } + return 0; +} diff --git a/src/graph.cpp b/src/graph.cpp new file mode 100644 index 000000000..3c112643d --- /dev/null +++ b/src/graph.cpp @@ -0,0 +1,103 @@ +#include "graph.h" +#include "DHBPQ.h" +#include +#include +#include +using namespace std; + +bool exists(const vector& points, int p) { + for (double point : points) { + if (p == point) { + return true; + } + } + return false; +} + +void graph::generate(int cPoints, int cEdges) { + if (cPoints <= 1 || cEdges <= 0 || cPoints * (cPoints - 1) / 2 < cEdges || cPoints - 1 > cEdges) { + throw exception("Can't generate graph"); + } + + points = vector(); + points.reserve(cPoints); + for (int i = 0; i < cPoints; i++) { + points.push_back(i); + } + + srand(time(nullptr)); + edges.reserve(cEdges); + for (int i = 0; i < cPoints - 1; i++) { + edges.push_back(edge(i, i + 1, rand() % 45 + 1)); + cEdges--; + } + + while (cEdges > 0) { + const edge e = edge(rand() % cPoints, rand() % cPoints, rand() % 45 + 1); + if (e.begin == e.end) continue; + int i; + for (i = 0; i < edges.size(); i++) { + if (e == edges[i]) { + break; + } + } + if (i == edges.size()) { + edges.push_back(e); + cEdges--; + } + } +} + + +graph::graph(int cPoints, int cEdges) { + generate(cPoints, cEdges); +} + +graph::graph(vector edges) { + points.reserve(2 * edges.size()); + for (int i = 0; i < edges.size(); i++) { + if (!exists(points, edges[i].begin)) { + points.push_back(edges[i].begin); + } + if (!exists(points, edges[i].end)) { + points.push_back(edges[i].end); + } + } + + this->edges = edges; +} + + +int graph::points_size() const { + return points.size(); +} + +int graph::edges_size() const { + return edges.size(); +} + +vector graph::get_edges() const { + return edges; +} + +vector graph::get_points() const { + return points; +} + +void graph::print() { + cout << "points" << endl; + for (int i = 0; i < points.size(); i++) { + + cout.width(4); + cout << points[i]; + } + cout << endl << "edges" << endl; + for (edge e : edges) { + cout.width(4); + cout << e.begin; + cout.width(4); + cout << e.end; + cout.width(4); + cout << e.weight << endl; + } +} diff --git a/src/kruskal.cpp b/src/kruskal.cpp new file mode 100644 index 000000000..bcc2e96a9 --- /dev/null +++ b/src/kruskal.cpp @@ -0,0 +1,51 @@ +#include +#include +#include + +using namespace std; + +vector kruskal(const graph& g) { + vector groups = vector(); + groups.reserve(g.points_size()); + for (int i = 0; i < g.points_size(); i++) { + groups.push_back(i); + } + vector result; + DHBPQ queue(g.get_edges(), 2); + const int n = g.points_size(); + while (!queue.is_empty() && result.size() < n - 1) { + const edge edge = queue.pop(); + if (groups[edge.begin] != groups[edge.end]) { + for (int i = 0; i < n; i++) { + if (groups[i] == groups[edge.end]) { + groups[i] = groups[edge.begin]; + } + } + result.push_back(edge); + } + } + return result; +} + + +int main() { + char IsEnded = 'y'; + int n, m; + while (IsEnded == 'Y' || IsEnded == 'y') + { + try { + cout << "Enter n,m" << endl; + cin >> n >> m; + graph g = graph(n, m); + g.print(); + vector v = kruskal(g); + for (int i = 0; i < v.size(); i++) { + cout << v[i] << endl; + } + } + catch (exception& l) { cout << l.what() << endl; } + cout << "Do u wanna try again (Y/N)" << endl; + cin >> IsEnded; + } + return 0; +} diff --git a/src/piramid_sort.cpp b/src/piramid_sort.cpp new file mode 100644 index 000000000..230aef102 --- /dev/null +++ b/src/piramid_sort.cpp @@ -0,0 +1,43 @@ +#include +#include +#include +#include + +using namespace std; + +template +vector piramid_sort(vector m) { + DHBPQ queue = DHBPQ(m, 2); + vector sorted; + while (!queue.is_empty()) { + sorted.push_back(queue.pop()); + } + return sorted; +} + + +int main() { + srand(time(nullptr)); + + for (int arr = 1; arr <= 8; arr++) { + const int length = rand() % 10 + 5; + vector v = vector(); + for (int i = 0; i < length; i++) { + v.push_back(rand() % 30 - 10); + } + cout << "Array #" << arr << ": "; + for (int i = 0; i < v.size(); i++) { + cout.width(4); + cout << v[i]; + } + cout << endl << "Sorted: "; + v = piramid_sort(v); + for (int i = 0; i < v.size(); i++) { + cout.width(4); + cout << v[i]; + } + cout << "\n\n"; + } + + return 0; +}