Skip to content
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

Lab2 #47

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Binary file added D-кучи.doc
Binary file not shown.
42 changes: 42 additions & 0 deletions lab2/include/DHBPQ.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once
#include "priority_queue.h"
#include "dheap.h"

template <typename T>
class DHBPQ : public priority_queue<T>
{
dheap<T> heap;
public:
DHBPQ() = default;
DHBPQ(vector<T> elems, int d);
bool is_full() const override;
bool is_empty() const override;
void push(T a) override;
T pop() override;
};

template <typename T>
DHBPQ<T>::DHBPQ(vector<T> elems, int d) {
heap = dheap<T>(elems, d);
}

template <typename T>
bool DHBPQ<T>::is_full() const {
return false;
}

template <typename T>
bool DHBPQ<T>::is_empty() const {
return heap.is_empty();
}

template <typename T>
void DHBPQ<T>::push(T a) {
heap.insert(a);
}

template <typename T>
T DHBPQ<T>::pop() {
T a = heap.get_min_value();
return a;
}
111 changes: 111 additions & 0 deletions lab2/include/dheap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#pragma once
#include <algorithm>
#include <vector>
using namespace std;

template <typename T>
class dheap
{
vector<T> keys;
int d;
public:
dheap();
dheap(vector<T> 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 <typename T>
dheap<T>::dheap() : d(3) {
}

template <typename T>
dheap<T>::dheap(vector<T> keys, int d) {
this->d = d;
this->keys = keys;
hilling();
}

template <typename T>
void dheap<T>::sink(int idx) {
int c = minchild(idx);
while (c != -1 && keys[c] < keys[idx]) {
transpose(c, idx);
idx = c;
c = minchild(idx);
}
}

template <typename T>
void dheap<T>::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 <typename T>
void dheap<T>::transpose(int idx1, int idx2) {
swap(keys[idx1], keys[idx2]);
}

template <typename T>
void dheap<T>::hilling() {
for (int i = keys.size() - 1; i >= 0; i--) {
sink(i);
}
}

template <typename T>
void dheap<T>::insert(T key) {
keys.push_back(key);
rise(keys.size() - 1);
}

template <typename T>
void dheap<T>::remove(int idx) {
if (idx < 0 || idx >= keys.size()) throw "Index error";

swap(keys.back(), keys[idx]);
keys.pop_back();
sink(idx);
}

template <typename T>
T dheap<T>::get_min_value() {
T tmp = keys.front();
swap(keys.front(), keys.back());
keys.pop_back();
sink(0);
return tmp;
}

template <typename T>
int dheap<T>::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 <typename T>
bool dheap<T>::is_empty() const {
return keys.empty();
}
32 changes: 32 additions & 0 deletions lab2/include/edge.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once
#include <iostream>
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;
}
};
33 changes: 33 additions & 0 deletions lab2/include/graph.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once
#include"edge.h"
#include <vector>
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<edge> edges;
vector<int> points;
public:
graph(int n, int m);
graph(vector<edge> edges);
int points_size() const;
int edges_size() const;
vector<edge> get_edges() const;
vector<int> get_points() const;
void print();
};
10 changes: 10 additions & 0 deletions lab2/include/priority_queue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once
template <typename T>
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;
};
90 changes: 90 additions & 0 deletions lab2/src/deikstra.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include <DHBPQ.h>
#include <graph.h>
#include <vector>

using namespace std;

vector<vertex> alg_deikstra(const graph& g, const int start) {
vector<int> points = g.get_points();
int n = points.size();
vector<vector<double>> matrix = vector<vector<double>>(n);
for (int i = 0; i < n; i++) {
matrix[i] = vector<double>(n, 0);
}

vector<edge> 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<double> distance = vector<double>(g.points_size(), numeric_limits<double>::infinity());
vector<int> from = vector<int>(g.points_size(), -1);

distance[start] = 0;

DHBPQ<vertex> queue = DHBPQ<vertex>();
queue.push(vertex(start, distance[start], from[start]));

while (!queue.is_empty()) {
const vertex p = queue.pop();
vector<double>& 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<vertex> result = vector<vertex>();
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<vertex> 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;
}
Loading