diff --git a/app/main.cpp b/app/main.cpp index 4485790..1ea7527 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -1,6 +1,54 @@ -#include "add.h" #include +#include "kruskal.h" +#include "prim.h" +#include "graph.h" int main() { - std::cout << "2 + 2 = " << add(2, 2) << std::endl; + Graph g, g2; + Graph ostov; + char q1[] = "example.txt"; + char q2[] = "example2.txt"; + + // создаём граф по списку смежности + g = create_graph(q2); + std::cout << "Created graph:" << std::endl << std::endl; + Print(&g); + // алгоритм Краскала + Kruskal(&g, &ostov); + std::cout << "" << std::endl; + std::cout << "Minimum spanning tree of the graph:" << std::endl << std::endl; + Print(&ostov); + std::cout << "" << std::endl; + + // визуализация полученного графа и остова + + char graph1[] = "C:\\Users\\Марина\\Desktop\\graph1.gv"; + char ostov1[] = "C:\\Users\\Марина\\Desktop\\ostov1.gv"; + char g_and_o[] = "C:\\Users\\Марина\\Desktop\\graph_and_ostov_1.gv"; + + graph_to_gv(&g, graph1); + ostov_to_gv(&ostov, ostov1); + graph_and_ostov_to_gv(&g, &ostov, g_and_o); + + // создаём граф по матрице смежности + g2 = Create_graph(q1); + std::cout << "Created graph:" << std::endl << std::endl; + Print(&g2); + // алгоритм Прима + Prim(&g2, &ostov); + std::cout << "" << std::endl; + std::cout << "Minimum spanning tree of the graph:" << std::endl << std::endl; + Print(&ostov); + + // визуализация полученного графа и остова + + char graph2[] = "C:\\Users\\Марина\\Desktop\\graph2.gv"; + char ostov2[] = "C:\\Users\\Марина\\Desktop\\ostov2.gv"; + char g_and_o_2[] = "C:\\Users\\Марина\\Desktop\\graph_and_ostov_2.gv"; + + graph_to_gv(&g2, graph2); + ostov_to_gv(&ostov, ostov2); + graph_and_ostov_to_gv(&g2, &ostov, g_and_o_2); + + return 0; } diff --git a/example.txt b/example.txt new file mode 100644 index 0000000..3603172 --- /dev/null +++ b/example.txt @@ -0,0 +1,6 @@ +5 +0 5 2 0 7 +5 0 0 8 1 +2 0 0 5 4 +0 8 5 0 8 +7 1 4 8 0 \ No newline at end of file diff --git a/example2.txt b/example2.txt new file mode 100644 index 0000000..b4d61d5 --- /dev/null +++ b/example2.txt @@ -0,0 +1,6 @@ +5 8 +3 1 5 2 2 4 7 +3 0 5 3 8 4 1 +3 0 2 3 5 4 4 +3 1 8 2 5 4 8 +4 0 7 1 1 2 4 3 8 \ No newline at end of file diff --git a/graph1.gv b/graph1.gv new file mode 100644 index 0000000..6d20be8 --- /dev/null +++ b/graph1.gv @@ -0,0 +1,21 @@ +graph ostov { + rankdir=LR; + node[shape=circle]; + edge[color=black]; + edge[label=8]; + B -- D; + edge[label=8]; + D -- E; + edge[label=7]; + A -- E; + edge[label=5]; + A -- B; + edge[label=5]; + C -- D; + edge[label=4]; + C -- E; + edge[label=2]; + A -- C; + edge[label=1]; + B -- E; +} \ No newline at end of file diff --git a/graph2.gv b/graph2.gv new file mode 100644 index 0000000..6d20be8 --- /dev/null +++ b/graph2.gv @@ -0,0 +1,21 @@ +graph ostov { + rankdir=LR; + node[shape=circle]; + edge[color=black]; + edge[label=8]; + B -- D; + edge[label=8]; + D -- E; + edge[label=7]; + A -- E; + edge[label=5]; + A -- B; + edge[label=5]; + C -- D; + edge[label=4]; + C -- E; + edge[label=2]; + A -- C; + edge[label=1]; + B -- E; +} \ No newline at end of file diff --git a/graph_and_ostov_1.gv b/graph_and_ostov_1.gv new file mode 100644 index 0000000..709d436 --- /dev/null +++ b/graph_and_ostov_1.gv @@ -0,0 +1,30 @@ +graph ostov { + rankdir=LR; + node[shape=doublecircle]; + edge[color=black]; + edge[label=8]; + B -- D; + edge[label=8]; + D -- E; + edge[label=7]; + A -- E; + edge[label=5]; + A -- B; + edge[label=5]; + C -- D; + edge[label=4]; + C -- E; + edge[label=2]; + A -- C; + edge[label=1]; + B -- E; + edge[color=green]; + edge[label=1]; + B -- E; + edge[label=2]; + A -- C; + edge[label=4]; + C -- E; + edge[label=5]; + C -- D; +} \ No newline at end of file diff --git a/graph_and_ostov_2.gv b/graph_and_ostov_2.gv new file mode 100644 index 0000000..cab6772 --- /dev/null +++ b/graph_and_ostov_2.gv @@ -0,0 +1,30 @@ +graph ostov { + rankdir=LR; + node[shape=doublecircle]; + edge[color=black]; + edge[label=8]; + B -- D; + edge[label=8]; + D -- E; + edge[label=7]; + A -- E; + edge[label=5]; + A -- B; + edge[label=5]; + C -- D; + edge[label=4]; + C -- E; + edge[label=2]; + A -- C; + edge[label=1]; + B -- E; + edge[color=green]; + edge[label=1]; + E -- B; + edge[label=2]; + A -- C; + edge[label=5]; + C -- D; + edge[label=4]; + C -- E; +} \ No newline at end of file diff --git a/images_with_visualization/app.jpg b/images_with_visualization/app.jpg new file mode 100644 index 0000000..e42f9b1 Binary files /dev/null and b/images_with_visualization/app.jpg differ diff --git a/images_with_visualization/graph1.jpg b/images_with_visualization/graph1.jpg new file mode 100644 index 0000000..7386772 Binary files /dev/null and b/images_with_visualization/graph1.jpg differ diff --git a/images_with_visualization/graph2.jpg b/images_with_visualization/graph2.jpg new file mode 100644 index 0000000..0e596bf Binary files /dev/null and b/images_with_visualization/graph2.jpg differ diff --git a/images_with_visualization/graph_and_ostov_1.jpg b/images_with_visualization/graph_and_ostov_1.jpg new file mode 100644 index 0000000..a14921a Binary files /dev/null and b/images_with_visualization/graph_and_ostov_1.jpg differ diff --git a/images_with_visualization/graph_and_ostov_2.jpg b/images_with_visualization/graph_and_ostov_2.jpg new file mode 100644 index 0000000..418510b Binary files /dev/null and b/images_with_visualization/graph_and_ostov_2.jpg differ diff --git a/images_with_visualization/ostov1.jpg b/images_with_visualization/ostov1.jpg new file mode 100644 index 0000000..338f78e Binary files /dev/null and b/images_with_visualization/ostov1.jpg differ diff --git a/images_with_visualization/ostov2.jpg b/images_with_visualization/ostov2.jpg new file mode 100644 index 0000000..d07e4ab Binary files /dev/null and b/images_with_visualization/ostov2.jpg differ diff --git a/include/add.h b/include/add.h deleted file mode 100644 index ebb1c94..0000000 --- a/include/add.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef INCLUDE_ADD_H_ -#define INCLUDE_ADD_H_ - -int add(int x, int y); - -#endif // INCLUDE_ADD_H_ diff --git a/include/d_heap.h b/include/d_heap.h new file mode 100644 index 0000000..785af39 --- /dev/null +++ b/include/d_heap.h @@ -0,0 +1,59 @@ +#ifndef INCLUDE_D_HEAP_H_ +#define INCLUDE_D_HEAP_H_ + +#include +#define MAXsize 1000 + +struct Data { + int priority; +}; + +class D_Heap { + protected: + Data **key; + int d; + int size; + + public: + explicit D_Heap(int d); + D_Heap(const D_Heap &heap); + ~D_Heap(); + + int Child(int i); + int Parent(int i); + int isFull(); + int isEmpty(); + + void insert(Data **i); + void insert_group(Data **keys, int num); + Data* erase(); + Data* erase(int i); + void transposition(int i, int j); + void surfacing(int i); + void immersion(int i); + void hilling(); + + int min_Child(int i); +}; + +/*----------------------------------------------------*/ +/* Приоритетная очередь на 2-куче */ +/*----------------------------------------------------*/ + +class PriorityQueue { + protected: + D_Heap *heap; + public: + explicit PriorityQueue(int d); + PriorityQueue(Data **keys, int num, int d); + ~PriorityQueue(); + int isFull(); + int isEmpty(); + + void add(Data **key); + Data* pop(int i); + Data* pop_min(); + void update(); +}; + +#endif // INCLUDE_D_HEAP_H_ diff --git a/include/disjoint_sets.h b/include/disjoint_sets.h new file mode 100644 index 0000000..77a8cad --- /dev/null +++ b/include/disjoint_sets.h @@ -0,0 +1,18 @@ +#ifndef INCLUDE_DISJOINT_SETS_H_ +#define INCLUDE_DISJOINT_SETS_H_ + +class Disjoint_Sets { + public: + int size; + int *parent; + int *rank; + + explicit Disjoint_Sets(int _size); + ~Disjoint_Sets(); + void make_set(int x); + void union_sets(int x, int y); + int find_set(int x); + void clear(); +}; + +#endif // INCLUDE_DISJOINT_SETS_H_ diff --git a/include/graph.h b/include/graph.h new file mode 100644 index 0000000..313a102 --- /dev/null +++ b/include/graph.h @@ -0,0 +1,31 @@ +#ifndef INCLUDE_GRAPH_H_ +#define INCLUDE_GRAPH_H_ +#include + +const char ASCII[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +const int inf = std::numeric_limits::infinity(); +typedef int *pInt; + +struct edge { + char x; + char y; + int weight; +}; + +struct Graph { + int N; + int edge_N; + edge* edges; +}; + +void make_edge(char, char, int, edge*); +void make_graph(int, int, edge*, Graph*); +Graph Create_graph(char *q); +Graph create_graph(char *q); +void Print(Graph *g); + +void graph_and_ostov_to_gv(Graph* graph, Graph* ostov, char* name); +void graph_to_gv(Graph* graph, char* name); +void ostov_to_gv(Graph* ostov, char* name); + +#endif // INCLUDE_GRAPH_H_ diff --git a/include/kruskal.h b/include/kruskal.h new file mode 100644 index 0000000..f818e6f --- /dev/null +++ b/include/kruskal.h @@ -0,0 +1,7 @@ +#ifndef INCLUDE_KRUSKAL_H_ +#define INCLUDE_KRUSKAL_H_ +#include "graph.h" + +void Kruskal(Graph*, Graph*); + +#endif // INCLUDE_KRUSKAL_H_ diff --git a/include/prim.h b/include/prim.h new file mode 100644 index 0000000..d5edb98 --- /dev/null +++ b/include/prim.h @@ -0,0 +1,19 @@ +#ifndef INCLUDE_PRIM_H_ +#define INCLUDE_PRIM_H_ +#include "graph.h" +#include"d_heap.h" +#include + +const int INF = 10000000; +class Prim_Data : public Data { + public: + int ver; + Prim_Data(int ver, int weight) { + this->ver = ver; + priority = weight; + } +}; + +void Prim(Graph*, Graph*); + +#endif // INCLUDE_PRIM_H_ diff --git a/ostov1.gv b/ostov1.gv new file mode 100644 index 0000000..45ad148 --- /dev/null +++ b/ostov1.gv @@ -0,0 +1,13 @@ +graph ostov { + rankdir=LR; + node[shape=doublecircle]; + edge[color=green]; + edge[label=1]; + B -- E; + edge[label=2]; + A -- C; + edge[label=4]; + C -- E; + edge[label=5]; + C -- D; +} \ No newline at end of file diff --git a/ostov2.gv b/ostov2.gv new file mode 100644 index 0000000..6302f2e --- /dev/null +++ b/ostov2.gv @@ -0,0 +1,13 @@ +graph ostov { + rankdir=LR; + node[shape=doublecircle]; + edge[color=green]; + edge[label=1]; + E -- B; + edge[label=2]; + A -- C; + edge[label=5]; + C -- D; + edge[label=4]; + C -- E; +} \ No newline at end of file diff --git a/otchet/Otchet_lab_5.doc b/otchet/Otchet_lab_5.doc new file mode 100644 index 0000000..eb395eb Binary files /dev/null and b/otchet/Otchet_lab_5.doc differ diff --git a/src/add.cpp b/src/add.cpp deleted file mode 100644 index 35bf82f..0000000 --- a/src/add.cpp +++ /dev/null @@ -1,3 +0,0 @@ -int add(int x, int y) { - return x + y; -} diff --git a/src/d_heap.cpp b/src/d_heap.cpp new file mode 100644 index 0000000..22aa8b9 --- /dev/null +++ b/src/d_heap.cpp @@ -0,0 +1,193 @@ +#include "d_heap.h" +#include + +using std::logic_error; + +/* Конструкторы */ +D_Heap::D_Heap(int d) { + if (d <= 0) + throw logic_error("Input error: invalid d.\n"); + this->d = d; + size = -1; + key = new Data*[MAXsize]; +} + +D_Heap::D_Heap(const D_Heap &heap) { + this->d = heap.d; + key = new Data*[MAXsize]; + for (int i = 0; i <= heap.size; i++) + key[i] = heap.key[i]; + this->size = heap.size; +} + +/* Деструктор */ +D_Heap::~D_Heap() { + delete[] key; +} + +/* Формулы вычисления потомка и родителя */ +int D_Heap::Child(int i) { + return d * i + 1; +} +int D_Heap::Parent(int i) { + return (i - 1) / d; +} + +int D_Heap::isFull() { + return size >= MAXsize - 1; +} + +int D_Heap::isEmpty() { + return size == -1; +} + +/* Вставка элемента в кучу */ +void D_Heap::insert(Data **i) { + if (isFull()) + throw logic_error("Heap is FULL.\n"); + size++; + key[size] = *i; + surfacing(size); +} + +/* Вставка группы элементов в кучу */ +void D_Heap::insert_group(Data **keys, int num) { + if (size + num >= MAXsize) + throw logic_error("Input error: too large set.\n"); + for (int i = 0; i < num; i++) + key[i + size + 1] = keys[i]; + size += num; + hilling(); +} + +/* Стирание */ +Data* D_Heap::erase() { + if (isEmpty()) + throw logic_error("Heap is empty.\n"); + Data* keys = key[size]; + size--; + return keys; +} + +Data* D_Heap::erase(int i) { + if (isEmpty()) + throw logic_error("Heap is empty.\n"); + if ((i < 0) || (i > size)) + throw logic_error("Input error: invalid index.\n"); + Data* keys = key[i]; + if (i == size) { + size--; + return keys; + } + transposition(i, size); + size--; + immersion(i); + return keys; +} + +/* Обмен переданных значений */ +void D_Heap::transposition(int i, int j) { + if ((i < 0) || (j < 0) || (i > size) || (j > size)) + throw logic_error("Input error: invalid indexes.\n"); + Data* tmp = key[i]; + key[i] = key[j]; + key[j] = tmp; +} + +/* Всплытие */ +void D_Heap::surfacing(int i) { + if ((i < 0) || (i > size)) + throw logic_error("Input error: invalid index.\n"); + int p = Parent(i); + while (i > 0) { + if (key[p]->priority < key[i]->priority) + break; + transposition(p, i); + i = p; + p = Parent(i); + } +} + +/* Погружение */ +void D_Heap::immersion(int i) { + if ((i < 0) || (i > size)) + throw logic_error("Input error: invalid index.\n"); + int c = min_Child(i); + while ((c != -1) && (key[c]->priority < key[i]->priority)) { + transposition(i, c); + i = c; + c = min_Child(i); + } +} + +/* Окучивание */ +void D_Heap::hilling() { + for (int i = size; i >= 0; i--) + immersion(i); +} + +/* Поиск минимального потомка */ +int D_Heap::min_Child(int i) { + int ch = Child(i); + if (ch > size) + return -1; + int l; + if (i * d + d > size) { + l = size; + } else { + l = i * d + d; + } + int c; + Data* minKey = key[ch]; + c = ch; + for (int k = ch + 1; k <= l; k++) { + if (minKey->priority > key[k]->priority) { + minKey = key[k]; + c = k; + } + } + return c; +} + +/* Конструкторы */ +PriorityQueue::PriorityQueue(int d) { + heap = new D_Heap(d = 4); +} + +PriorityQueue::PriorityQueue(Data **keys, int num, int d) { + heap = new D_Heap(d = 4); + heap->insert_group(keys, num); +} + +/* Деструктор */ +PriorityQueue ::~PriorityQueue() { + delete heap; +} + +int PriorityQueue::isFull() { + return heap->isFull(); +} + +int PriorityQueue::isEmpty() { + return heap->isEmpty(); +} + +/* Добавление ключа в очередь */ +void PriorityQueue::add(Data **key) { + heap->insert(key); +} + +/* Удаление */ +Data* PriorityQueue::pop(int i) { + return heap->erase(i); +} + +/* Удаление минимального */ +Data* PriorityQueue::pop_min() { + return heap->erase(0); +} + +/* Обновление очереди */ +void PriorityQueue::update() { + heap->hilling(); +} diff --git a/src/disjoint_sets.cpp b/src/disjoint_sets.cpp new file mode 100644 index 0000000..9a1ebe5 --- /dev/null +++ b/src/disjoint_sets.cpp @@ -0,0 +1,75 @@ +#include "disjoint_sets.h" +#include +#include + +using std::logic_error; + +/* Конструктор */ +Disjoint_Sets::Disjoint_Sets(int _size) { + if (_size < 0) + throw logic_error("Input Error: wrong size. Size must be > 0.\n"); + size = _size; + parent = new int[size]; + rank = new int[size]; + for (int i = 0; i < size; i++) { + parent[i] = -1; + rank[i] = -1; + } +} + +/* Деструктор */ +Disjoint_Sets::~Disjoint_Sets() { + delete[]parent; + delete[]rank; +} + +/* Создание для него множество размера 1 из самого себя */ +void Disjoint_Sets::make_set(int x) { + if (x < 0 || x > size) + throw logic_error("Input Error: wrong parameter.\n"); + if (parent[x] != -1) + throw logic_error("Input Error: wrong parameter.\n"); + parent[x] = x; + rank[x] = 0; +} + +/* Поиск множества, которому принадлежит элемент */ +int Disjoint_Sets::find_set(int x) { + if (x < 0 || x > size) + throw logic_error("Input Error: wrong parameter.\n"); + if (parent[x] == -1) + throw logic_error("Input Error: wrong parameter.\n"); + while (parent[x] != x) + x = parent[x]; + return parent[x]; +} + +/* Объединение множеств */ +void Disjoint_Sets::union_sets(int x, int y) { + if (x < 0 || x > size || y < 0 || y > size) + throw logic_error("Input Error: wrong parameter.\n"); + if (parent[x] == -1 || parent[y] == -1) + throw logic_error("Input Error: wrong parameter.\n"); + if (x != y) { + int _x, _y; + _x = find_set(x); + _y = find_set(y); + if (_x != _y) { + if (rank[_x] < rank[_y]) { + parent[_x] = _y; + } else { + parent[_y] = _x; + if (rank[_x] == rank[_y]) + ++rank[_x]; + } + } + } +} + +/* Очистка множества для экспериментов */ +void Disjoint_Sets::clear() { + for (int i = 0; i < size; i++) { + parent[i] = -1; + rank[i] = -1; + } +} diff --git a/src/graph.cpp b/src/graph.cpp new file mode 100644 index 0000000..8ab8051 --- /dev/null +++ b/src/graph.cpp @@ -0,0 +1,208 @@ +#include +#include "graph.h" +#include + +using std::logic_error; + +/* Добавление ребра */ +void make_edge(char _x, char _y, int _weight, edge* r) { + if (_x == _y) + throw logic_error("Error: same verix.\n"); + r->x = _x; + r->y = _y; + r->weight = _weight; +} + +/* Создание графа */ +void make_graph(int node, int edgee, edge* r, Graph *g) { + if (node < 0) + throw logic_error("Error: number of verices can't be < 0.\n"); + if (edgee < 0) + throw logic_error("Error: number of edges can't be < 0.\n"); + g->edge_N = edgee; + g->N = node; + g->edges = new edge[edgee]; + for (int i = 0; i < edgee; i++) + g->edges[i] = r[i]; + for (int i = 0; i < edgee; i++) + for (int j = edgee - 1; j > i; j--) + if (g->edges[j - 1].weight < g->edges[j].weight) { + edge tmp = g->edges[j - 1]; + g->edges[j - 1] = g->edges[j]; + g->edges[j] = tmp; + } +} + +/* Вывод графа */ +void Print(Graph *g) { + for (int i = 0; i < g->edge_N; i++) + std::cout << g->edges[i].x << " - " << g->edges[i].y << "; \n"; +} + +/* Чтение матрицы смежности из файла и создание графа */ +Graph Create_graph(char *q) { + pInt *W; // матрица смежности + Graph g; // граф + FILE *F; + int N = 0, edge_N = 0; + F = fopen(q, "r"); + if (F == NULL) { + throw logic_error("Input error. Can't open this file.\n"); + } + // считывание количества вершин графа + fscanf(F, "%d", &N); + + W = reinterpret_cast(calloc(N, sizeof(pInt))); + for (int i = 0; i < N; i++) + W[i] = reinterpret_cast(calloc(N, sizeof(int))); + + // вывод матрицы смежности + std::cout << "Matrix of adjacency of the graph:" << std::endl << std::endl; + std::cout << " "; + for (int i = 0; i < N; i++) + printf("%4c", ASCII[i]); + std::cout << "" << std::endl; + std::cout << "----"; + for (int i = 0; i < N; i++) + std::cout << "----"; + std::cout << "" << std::endl; + + for (int i = 0; i < N; i++) { + printf("%2c |", ASCII[i]); + for (int j = 0; j < N; j++) { + fscanf(F, "%d", &W[i][j]); + if (W[i][j] <= 0) { + W[i][j] = inf; + std::cout << " -"; + } else { + edge_N++; + printf("%4d", W[i][j]); + } + } + std::cout << "" << std::endl; + } + + edge_N = edge_N / 2; + fclose(F); + + std::cout << "" << std::endl; + int a = 0; + + // создание рёбер по матрице смежности + edge r; + edge* e = new edge[edge_N]; + for (int i = 0; i < N; i++) + for (int j = 0; j < N; j++) + if ((W[i][j] != inf) && (i < j)) { + make_edge(ASCII[i], ASCII[j], W[i][j], &r); + e[a] = r; + a++; + } + // создание графа + make_graph(N, edge_N, e, &g); + return g; +} + +/* Чтение списка смежности из файла и создание графа */ +Graph create_graph(char *q) { + Graph g; // граф + FILE *F; + int N = 0, edge_N = 0; + F = fopen(q, "r"); + if (F == NULL) { + throw logic_error("Input error. Can't open this file.\n"); + } + // считывание количества вершин графа + fscanf(F, "%d", &N); + // считывание количества рёбер графа + fscanf(F, "%d", &edge_N); + + int tmp = 0; + std::cout << "" << std::endl; + + // вывод списка смежности + std::cout << "List of adjacency of the graph:" << std::endl; + int num, ch, a = 0; + edge r; + edge* e = new edge[edge_N]; + for (int i = 0; i < N; i++) { + std::cout << "" << std::endl; + printf("%2c :", ASCII[i]); + fscanf(F, "%d", &num); + for (int j = 0; j < num; j++) { + fscanf(F, "%d", &tmp); + ch = tmp + 65; + printf("%4c", tmp + 65); + fscanf(F, "%d", &tmp); + printf("%4d", tmp); + if ((i + 65) < ch) { + make_edge(ASCII[i], ch, tmp, &r); + e[a] = r; + a++; + } + } + } + std::cout << "" << std::endl << std::endl; + fclose(F); + // создание графа + make_graph(N, edge_N, e, &g); + return g; +} + +/* Визуализация полученных графов и остовов */ +void graph_and_ostov_to_gv(Graph* graph, Graph* ostov, char* name) { + FILE* fp = fopen(name, "w"); + + fprintf(fp, "graph ostov {\n"); + fprintf(fp, "\trankdir=LR;\n"); + fprintf(fp, "\tnode[shape=doublecircle];\n"); + fprintf(fp, "\tedge[color=black];\n"); + + for (int i = 0; i < graph->edge_N; i++) { + fprintf(fp, "\tedge[label=%d];\n", graph->edges[i].weight); + fprintf(fp, "\t%c -- %c;\n", graph->edges[i].x, graph->edges[i].y); + } + fprintf(fp, "\tedge[color=green];\n"); + + for (int i = 0; i < ostov->edge_N; i++) { + fprintf(fp, "\tedge[label=%d];\n", ostov->edges[i].weight); + fprintf(fp, "\t%c -- %c;\n", ostov->edges[i].x, ostov->edges[i].y); + } + + fprintf(fp, "}"); + fclose(fp); +} + +void graph_to_gv(Graph* graph, char* name) { + FILE* fp = fopen(name, "w"); + + fprintf(fp, "graph ostov {\n"); + fprintf(fp, "\trankdir=LR;\n"); + fprintf(fp, "\tnode[shape=circle];\n"); + fprintf(fp, "\tedge[color=black];\n"); + + for (int i = 0; i < graph->edge_N; i++) { + fprintf(fp, "\tedge[label=%d];\n", graph->edges[i].weight); + fprintf(fp, "\t%c -- %c;\n", graph->edges[i].x, graph->edges[i].y); + } + + fprintf(fp, "}"); + fclose(fp); +} + +void ostov_to_gv(Graph* ostov, char* name) { + FILE* fp = fopen(name, "w"); + + fprintf(fp, "graph ostov {\n"); + fprintf(fp, "\trankdir=LR;\n"); + fprintf(fp, "\tnode[shape=doublecircle];\n"); + fprintf(fp, "\tedge[color=green];\n"); + + for (int i = 0; i < ostov->edge_N; i++) { + fprintf(fp, "\tedge[label=%d];\n", ostov->edges[i].weight); + fprintf(fp, "\t%c -- %c;\n", ostov->edges[i].x, ostov->edges[i].y); + } + + fprintf(fp, "}"); + fclose(fp); +} diff --git a/src/kruskal.cpp b/src/kruskal.cpp new file mode 100644 index 0000000..b0a5b87 --- /dev/null +++ b/src/kruskal.cpp @@ -0,0 +1,38 @@ +/* Построение минимального остовного дерева графа */ +/* Алгоритм Краскала */ +/* Вход: граф построенный по списку смежности из файла */ +/* Выход: Пары вершин, составляющих минимальное остовное дерево */ + +#include +#include "kruskal.h" +#include "disjoint_sets.h" +#include + +using std::logic_error; + +void Kruskal(Graph *g, Graph *ostov) { + std::stack st; + Disjoint_Sets s(g->N); + int N = g->N; + if (!N) + throw logic_error("Error: there in not verix in graph.\n"); + if (!g->edge_N) + throw logic_error("Error: there in not edges in graph.\n"); + ostov->N = N; + ostov->edge_N = N - 1; + ostov->edges = new edge[N - 1]; + for (int i = 0; i < N; i++) + s.make_set(i); + for (int i = 0; i < g->edge_N; i++) + st.push(g->edges[i]); + int i = 0; + while ((st.empty() != 1) && (i < N - 1)) { + edge tmp = st.top(); + st.pop(); + if (s.find_set(static_cast(tmp.x-65)) != s.find_set(static_cast(tmp.y-65))) { + ostov->edges[i] = tmp; + i++; + s.union_sets(static_cast(tmp.x - 65), static_cast(tmp.y - 65)); + } + } +} diff --git a/src/prim.cpp b/src/prim.cpp new file mode 100644 index 0000000..be1b186 --- /dev/null +++ b/src/prim.cpp @@ -0,0 +1,76 @@ +/* Построение минимального остовного дерева графа */ +/* Алгоритм Прима */ +/* Вход: граф построенный по матрице смежности из файла */ +/* Выход: Пары вершин, составляющих минимальное остовное дерево */ + +#include "prim.h" +#include + +using std::logic_error; + +void Prim(Graph* graph, Graph* ostov) { + int verices = graph->N; + int edge_N = graph->edge_N; + edge* edges = graph->edges; + if (!verices) + throw logic_error("Error: there in not verix in graph.\n"); + if (!edge_N) + throw logic_error("Error: there in not edges in graph.\n"); + + // подготовка данных для работы алгоритма + ostov->N = verices; + ostov->edge_N = verices - 1; + ostov->edges = new edge[verices - 1]; + Data** keys = new Data*[verices]; + // int* parent = new int[verices]; + for (int i = 0; i < verices; i++) { + // parent[i] = -1; + keys[i] = new Prim_Data(i, INF); + } + PriorityQueue* pq = new PriorityQueue(4); + std::vector inMST(verices, false); + keys[0]->priority = 0; + pq->add(&keys[0]); + + // алгоритм Прима + while (!pq->isEmpty()) { + // находим минимальное ребро вершины + int u = (reinterpret_cast(pq->pop_min()))->ver; + inMST[u] = true; // включаем вершину в остов + + for (int i = 0; i < edge_N; ++i) { + edge p = edges[i]; + edge tmp; + int v1 = static_cast(p.x) - 65; + int v2 = static_cast(p.y) - 65; + int weight = p.weight; + // добавляем рёбра выбранной вершины + if ((v1 == u) || (v2 == u)) { + if ((inMST[v1] == false) && (keys[v1]->priority > weight)) { + keys[v1]->priority = weight; + pq->add(&keys[v1]); + // parent[v1] = u; + tmp.x = u + 65; + tmp.y = v1 + 65; + tmp.weight = weight; + ostov->edges[v1-1] = tmp; + } else { + if ((inMST[v2] == false) && (keys[v2]->priority > weight)) { + keys[v2]->priority = weight; + pq->add(&keys[v2]); + // parent[v2] = u; + tmp.x = u + 65; + tmp.y = v2 + 65; + tmp.weight = weight; + ostov->edges[v2-1] = tmp; + } + } + } + } + } + // вывод рёбер остовного дерева + /*for (int i = 1; i < verices; ++i) + printf("%c - %c\n", (char)(parent[i]+65), (char)(i+65));*/ + /*for (int i = 0; i < verices - 1; ++i) + printf("%c - %c: %d\n", (ostov->edges[i]).x, (ostov->edges[i]).y, (ostov->edges[i]).weight);*/ +} diff --git a/test/test_add.cpp b/test/test_add.cpp deleted file mode 100644 index 66c2df3..0000000 --- a/test/test_add.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include "add.h" - -TEST(Addition, CanAddTwoNumbers) { - EXPECT_EQ(add(2, 2), 4); - EXPECT_EQ(add(-2, 2), 0); -} diff --git a/test/test_d_heap.cpp b/test/test_d_heap.cpp new file mode 100644 index 0000000..66256c4 --- /dev/null +++ b/test/test_d_heap.cpp @@ -0,0 +1,293 @@ +#include +#include "d_heap.h" + +/*TEST(D_HEAP, can_create_d_heap) { + ASSERT_NO_THROW(D_Heap *heap = new D_Heap(4)); +}*/ + +TEST(D_HEAP, can_insert_new_key) { + D_Heap *heap = new D_Heap(4); + Data* key = new Data(); + key->priority = 4; + ASSERT_NO_THROW(heap->insert(&key)); +} + +TEST(D_HEAP, can_insert_group_in_heap) { + Data **g_key = new Data*[4]; + for (int i = 0; i < 4; i++) { + g_key[i] = new Data; + g_key[i]->priority = 4; + } + D_Heap *heap = new D_Heap(2); + ASSERT_NO_THROW(heap->insert_group(g_key, 4)); +} + +TEST(D_HEAP, can_erase_element) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + i->priority = 1; + j->priority = 2; + heap->insert(&i); + heap->insert(&j); + ASSERT_NO_THROW(heap->erase()); +} + +TEST(D_HEAP, can_make_transposition_of_elements) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + i->priority = 1; + j->priority = 2; + heap->insert(&i); + heap->insert(&j); + ASSERT_NO_THROW(heap->transposition(0, 1)); +} + +TEST(D_HEAP, can_surfacing) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + i->priority = 1; + j->priority = 2; + heap->insert(&i); + heap->insert(&j); + ASSERT_NO_THROW(heap->surfacing(0)); +} + +TEST(D_HEAP, can_immersion) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + Data* k = new Data(); + i->priority = 1; + j->priority = 2; + j->priority = 3; + heap->insert(&i); + heap->insert(&j); + heap->insert(&k); + ASSERT_NO_THROW(heap->immersion(1)); +} + +TEST(D_HEAP, correct_work_of_erase) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + j->priority = 1; + j->priority = 2; + heap->insert(&i); + heap->insert(&j); + Data *k = heap->erase(1); + EXPECT_EQ(2, k->priority); +} + +TEST(D_HEAP, correct_work_of_transposition) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + i->priority = 1; + j->priority = 2; + heap->insert(&i); + heap->insert(&j); + heap->transposition(0, 1); + Data* k = heap->erase(1); + Data* p = heap->erase(0); + EXPECT_EQ(k->priority, 1); + EXPECT_EQ(p->priority, 2); +} + +TEST(D_HEAP, immersion_works_correctly) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + Data* k = new Data(); + i->priority = 1; + j->priority = 2; + j->priority = 3; + heap->insert(&i); + heap->insert(&j); + heap->insert(&k); + heap->immersion(1); + EXPECT_EQ(1, heap->erase(2)->priority); +} + +TEST(D_HEAP, can_find_min_child_1) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + Data* k = new Data(); + i->priority = 1; + j->priority = 2; + j->priority = 3; + heap->insert(&i); + heap->insert(&j); + heap->insert(&k); + EXPECT_EQ(heap->min_Child(0), 2); +} + +/*TEST(D_HEAP, throw_when_try_create_heap_with_negative_d) { + ASSERT_ANY_THROW(D_Heap *heap = new D_Heap(-5)); +}*/ + +TEST(D_HEAP, throw_when_try_insert_key_into_full_heap) { + D_Heap *heap = new D_Heap(4); + for (int i = 0; i < MAXsize; i++) { + Data* key = new Data(); + key->priority = 4; + heap->insert(&key); + } + Data *key = new Data(); + key->priority = 4; + ASSERT_ANY_THROW(heap->insert(&key)); +} + +TEST(D_HEAP, throw_when_try_insert_group_in_full_heap) { + D_Heap *heap = new D_Heap(4); + for (int i = 0; i < MAXsize; i++) { + Data *key = new Data(); + key->priority = 4; + heap->insert(&key); + } + Data **g_key = new Data*[4]; + for (int i = 0; i < 4; i++) { + g_key[i] = new Data; + g_key[i]->priority = 4; + } + ASSERT_ANY_THROW(heap->insert_group(g_key, 4)); +} + +TEST(D_HEAP, throw_when_try_erase_element_from_empty_heap) { + D_Heap *heap = new D_Heap(4); + ASSERT_ANY_THROW(heap->erase()); + Data* i = new Data(); + i->priority = 1; + heap->insert(&i); +} + +TEST(D_HEAP, throw_when_try_erase_negative_missing_element) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + i->priority = 1; + j->priority = 2; + heap->insert(&i); + heap->insert(&j); + ASSERT_ANY_THROW(heap->erase(-1)); +} + +TEST(D_HEAP, throw_when_try_erase_missing_element) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + i->priority = 1; + j->priority = 2; + heap->insert(&i); + heap->insert(&j); + ASSERT_ANY_THROW(heap->erase(3)); +} + +TEST(D_HEAP, throw_when_try_make_transposition_elements_with_negative_index) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + i->priority = 1; + j->priority = 2; + heap->insert(&i); + heap->insert(&j); + ASSERT_ANY_THROW(heap->transposition(-1, 0)); +} +TEST(D_HEAP, throw_when_try_make_transposition_elements_with_missing_index) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + i->priority = 1; + j->priority = 2; + heap->insert(&i); + heap->insert(&j); + ASSERT_ANY_THROW(heap->transposition(0, 3)); +} + +TEST(D_HEAP, throw_when_try_surfacing_with_negative_index) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + i->priority = 1; + j->priority = 2; + heap->insert(&i); + heap->insert(&j); + ASSERT_ANY_THROW(heap->surfacing(-1)); +} + +TEST(D_HEAP, throw_when_try_surfacing_with_missing_index) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + i->priority = 1; + j->priority = 2; + heap->insert(&i); + heap->insert(&j); + ASSERT_ANY_THROW(heap->surfacing(3)); +} + +TEST(D_HEAP, throw_when_try_immersion_with_missing_index) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + Data* k = new Data(); + i->priority = 1; + j->priority = 2; + j->priority = 3; + heap->insert(&i); + heap->insert(&j); + heap->insert(&k); + ASSERT_ANY_THROW(heap->immersion(3)); +} + +TEST(D_HEAP, throw_when_try_immersion_with_negative_index) { + D_Heap *heap = new D_Heap(4); + Data* i = new Data(); + Data* j = new Data(); + Data* k = new Data(); + i->priority = 1; + j->priority = 2; + j->priority = 3; + heap->insert(&i); + heap->insert(&j); + heap->insert(&k); + ASSERT_ANY_THROW(heap->immersion(-1)); +} + +TEST(D_HEAP, isFull_work_correctly) { + D_Heap *heap = new D_Heap(4); + for (int i = 0; i < MAXsize; i++) { + Data* j = new Data(); + j->priority = 1; + heap->insert(&j); + } + ASSERT_TRUE(heap->isFull()); +} + +TEST(D_HEAP, isFull_works_correctly_when_heap_not_full) { + D_Heap *heap = new D_Heap(4); + Data* j = new Data(); + j->priority = 1; + heap->insert(&j); + ASSERT_FALSE(heap->isFull()); +} + +TEST(D_HEAP, isEmpty_work_correctly) { + D_Heap *heap = new D_Heap(4); + Data* j = new Data(); + j->priority = 1; + heap->insert(&j); + heap->erase(0); + ASSERT_TRUE(heap->isEmpty()); +} + +TEST(D_HEAP, isEmpty_works_correctly_when_heap_not_empty) { + D_Heap *heap = new D_Heap(4); + Data* j = new Data(); + j->priority = 1; + heap->insert(&j); + ASSERT_FALSE(heap->isEmpty()); +} diff --git a/test/test_disjoint_sets.cpp b/test/test_disjoint_sets.cpp new file mode 100644 index 0000000..2710066 --- /dev/null +++ b/test/test_disjoint_sets.cpp @@ -0,0 +1,122 @@ +#include +#include "disjoint_sets.h" + +/*TEST(DISJOINT_SETS, can_create_set) { + EXPECT_NO_THROW(Disjoint_Sets sets(4)); +}*/ + +TEST(DISJOINT_SETS, can_work_when_try_union_same_sets) { + Disjoint_Sets sets(4); + sets.make_set(1); + sets.make_set(0); + sets.make_set(2); + EXPECT_NO_THROW(sets.union_sets(1, 1)); +} + +TEST(DISJOINT_SETS, can_find_set) { + Disjoint_Sets sets(4); + sets.make_set(1); + sets.make_set(0); + sets.make_set(2); + EXPECT_NO_THROW(sets.find_set(1)); +} + +TEST(DISJOINT_SETS, can_find_union_set) { + Disjoint_Sets sets(4); + sets.make_set(1); + sets.make_set(0); + sets.make_set(2); + sets.union_sets(1, 2); + sets.union_sets(2, 0); + EXPECT_NO_THROW(sets.find_set(1)); +} + +TEST(DISJOINT_SETS, can_clear) { + Disjoint_Sets sets(4); + sets.make_set(1); + sets.make_set(0); + sets.make_set(2); + sets.union_sets(1, 2); + sets.union_sets(2, 0); + EXPECT_NO_THROW(sets.clear()); +} + +TEST(DISJOINT_SETS, throw_when_try_make_set_with_too_large_index) { + Disjoint_Sets sets(4); + sets.make_set(1); + EXPECT_ANY_THROW(sets.make_set(5)); +} + +TEST(DISJOINT_SETS, throw_when_try_make_set_with_negative_index) { + Disjoint_Sets sets(4); + sets.make_set(1); + EXPECT_ANY_THROW(sets.make_set(-2)); +} + +TEST(DISJOINT_SETS, throw_when_try_union_sets_with_too_large_index) { + Disjoint_Sets sets(4); + sets.make_set(1); + sets.make_set(0); + EXPECT_ANY_THROW(sets.union_sets(1, 5)); +} + +TEST(DISJOINT_SETS, throw_when_try_union_sets_with_negative_index) { + Disjoint_Sets sets(4); + sets.make_set(1); + sets.make_set(0); + EXPECT_ANY_THROW(sets.union_sets(-2, 0)); +} + +TEST(DISJOINT_SETS, throw_when_try_union_dont_exict_sets) { + Disjoint_Sets sets(4); + sets.make_set(1); + sets.make_set(0); + EXPECT_ANY_THROW(sets.union_sets(1, 2)); +} + +TEST(DISJOINT_SETS, make_set_correctly) { + Disjoint_Sets sets(4); + sets.make_set(1); + EXPECT_EQ(sets.parent[1], 1); +} + +TEST(DISJOINT_SETS, union_sets_correctly) { + Disjoint_Sets sets(4); + sets.make_set(1); + sets.make_set(0); + sets.make_set(2); + sets.union_sets(2, 1); + sets.union_sets(0, 1); + EXPECT_EQ(sets.parent[0], 2); +} + +TEST(DISJOINT_SETS, find_set_correctly) { + Disjoint_Sets sets(4); + sets.make_set(1); + sets.make_set(0); + sets.make_set(2); + EXPECT_EQ(sets.find_set(0), 0); +} + +TEST(DISJOINT_SETS, find_union_set_correctly) { + Disjoint_Sets sets(4); + sets.make_set(1); + sets.make_set(0); + sets.make_set(2); + sets.union_sets(0, 1); + sets.union_sets(1, 2); + EXPECT_EQ(sets.find_set(2), 0); +} + +TEST(DISJOINT_SETS, clear_correctly) { + Disjoint_Sets sets(4); + sets.make_set(1); + sets.make_set(0); + sets.make_set(2); + sets.union_sets(1, 2); + sets.union_sets(2, 0); + sets.clear(); + EXPECT_EQ(sets.parent[0], -1); + EXPECT_EQ(sets.parent[1], -1); + EXPECT_EQ(sets.parent[2], -1); +} diff --git a/test/test_graph.cpp b/test/test_graph.cpp new file mode 100644 index 0000000..573d256 --- /dev/null +++ b/test/test_graph.cpp @@ -0,0 +1,62 @@ +#include +#include "graph.h" + +TEST(GRAPH, can_make_edge) { + edge e[3]; + edge r; + ASSERT_NO_THROW(make_edge('A', 'B', 3, &r)); + e[0] = r; +} + +TEST(GRAPH, can_make_graph_of_one_vertex) { + Graph g; + int N = 1; + int edge_N = 0; + edge* e = nullptr; + ASSERT_NO_THROW(make_graph(N, edge_N, e, &g)); + make_graph(N, edge_N, e, &g); +} + +TEST(GRAPH, can_make_graph) { + Graph g; + edge r; + int N = 3; + int edge_N = 2; + edge* e = new edge[edge_N]; + for (int i = 0; i < edge_N; i++) { + make_edge(ASCII[i], ASCII[i + 1], (i + 2) * 3, &r); + e[i] = r; + } + ASSERT_NO_THROW(make_graph(N, edge_N, e, &g)); + make_graph(N, edge_N, e, &g); +} + +TEST(GRAPH, throw_when_try_create_graph_with_negative_verix) { + Graph g; + int N = 1; + int edge_N = 0; + edge* e = nullptr; + ASSERT_ANY_THROW(make_graph(-N, edge_N, e, &g)); + make_graph(N, edge_N, e, &g); +} + +TEST(GRAPH, throw_when_try_create_graph_with_negative_edge) { + Graph g; + int N = 1; + int edge_N = 0; + edge* e = nullptr; + ASSERT_ANY_THROW(make_graph(N, edge_N - 1, e, &g)); + make_graph(N, edge_N, e, &g); +} + +TEST(GRAPH, throw_when_try_insert_edge_between_one_verix) { + edge e; + ASSERT_ANY_THROW(make_edge('A', 'A', 5, &e)); + make_edge('A', 'B', 5, &e); +} + +TEST(GRAPH, can_work_when_try_insert_exist_edge) { + edge e; + make_edge('A', 'B', 5, &e); + ASSERT_NO_THROW(make_edge('A', 'B', 5, &e)); +} diff --git a/test/test_kruskal.cpp b/test/test_kruskal.cpp new file mode 100644 index 0000000..3370b64 --- /dev/null +++ b/test/test_kruskal.cpp @@ -0,0 +1,66 @@ +#include +#include "kruskal.h" + +TEST(KRUSKALS_ALG, kruskals_alg_can_work_correctly) { + Graph g; + Graph ostov; + edge r; + edge* e = new edge[8]; + make_edge('A', 'B', 1, &r); + e[0] = r; + make_edge('A', 'C', 3, &r); + e[1] = r; + make_edge('A', 'D', 3, &r); + e[2] = r; + make_edge('C', 'B', 2, &r); + e[3] = r; + make_edge('E', 'B', 8, &r); + e[4] = r; + make_edge('D', 'E', 4, &r); + e[5] = r; + make_edge('C', 'E', 3, &r); + e[6] = r; + make_edge('D', 'C', 1, &r); + e[7] = r; + make_graph(5, 8, e, &g); + int sum = 0; + Kruskal(&g, &ostov); + for (int i = 0; i < 4; ++i) + sum += (ostov.edges[i]).weight; + EXPECT_EQ(sum, 7); + EXPECT_EQ(ostov.edge_N, 4); + EXPECT_EQ(ostov.N, 5); +} + +TEST(KRUSKALS_ALG, kruskals_alg_can_work_with_one_edge) { + Graph g; + Graph ostov; + edge r; + edge* e = new edge[1]; + make_edge('A', 'B', 1, &r); + e[0] = r; + make_graph(2, 1, e, &g); + int sum = 0; + Kruskal(&g, &ostov); + for (int i = 0; i < 1; ++i) + sum += (ostov.edges[i]).weight; + EXPECT_EQ(sum, 1); + EXPECT_EQ(ostov.edge_N, 1); + EXPECT_EQ(ostov.N, 2); +} + +/*TEST(KRUSKALS_ALG, throw_when_try_kruskals_alg_with_wrong_parameters_1) { + Graph g; + Graph ostov; + edge* e; + g.edge_N = 0; + g.N = 2; + g.edges = nullptr; + EXPECT_ANY_THROW(Kruskal(&g, &ostov)); +}*/ + +/*TEST(KRUSKALS_ALG, throw_when_try_kruskals_alg_with_wrong_parameters_2) { + Graph g; + Graph ostov; + EXPECT_ANY_THROW(Kruskal(&g, &ostov)); +}*/ diff --git a/test/test_prim.cpp b/test/test_prim.cpp new file mode 100644 index 0000000..5bf5544 --- /dev/null +++ b/test/test_prim.cpp @@ -0,0 +1,66 @@ +#include +#include "prim.h" + +TEST(PRIMS_ALG, prims_alg_can_work_correctly) { + Graph g; + Graph ostov; + edge r; + edge* e = new edge[8]; + make_edge('A', 'B', 1, &r); + e[0] = r; + make_edge('A', 'C', 3, &r); + e[1] = r; + make_edge('A', 'D', 3, &r); + e[2] = r; + make_edge('C', 'B', 2, &r); + e[3] = r; + make_edge('E', 'B', 8, &r); + e[4] = r; + make_edge('D', 'E', 4, &r); + e[5] = r; + make_edge('C', 'E', 3, &r); + e[6] = r; + make_edge('D', 'C', 1, &r); + e[7] = r; + make_graph(5, 8, e, &g); + int sum = 0; + Prim(&g, &ostov); + for (int i = 0; i < 4; ++i) + sum += (ostov.edges[i]).weight; + EXPECT_EQ(sum, 7); + EXPECT_EQ(ostov.edge_N, 4); + EXPECT_EQ(ostov.N, 5); +} + +TEST(PRIMS_ALG, prims_alg_can_work_with_one_edge) { + Graph g; + Graph ostov; + edge r; + edge* e = new edge[1]; + make_edge('A', 'B', 1, &r); + e[0] = r; + make_graph(2, 1, e, &g); + int sum = 0; + Prim(&g, &ostov); + for (int i = 0; i < 1; ++i) + sum += (ostov.edges[i]).weight; + EXPECT_EQ(sum, 1); + EXPECT_EQ(ostov.edge_N, 1); + EXPECT_EQ(ostov.N, 2); +} + +/*TEST(PRIMS_ALG, throw_when_try_prims_alg_with_wrong_parameters_1) { + Graph g; + Graph ostov; + edge* e; + g.edge_N = 0; + g.N = 2; + g.edges = nullptr; + EXPECT_ANY_THROW(Prim(&g, &ostov)); +}*/ + +/*TEST(PRIMS_ALG, throw_when_try_prims_alg_with_wrong_parameters_2) { + Graph g; + Graph ostov; + EXPECT_ANY_THROW(Prim(&g, &ostov)); +}*/ diff --git a/test/test_priority_queue.cpp b/test/test_priority_queue.cpp new file mode 100644 index 0000000..aae0f92 --- /dev/null +++ b/test/test_priority_queue.cpp @@ -0,0 +1,141 @@ +#include "gtest/gtest.h" +#include "d_heap.h" + +/*TEST(PRIORITY_QUEUE_ON_HEAP, can_create_priority_queue_1) { + ASSERT_NO_THROW(PriorityQueue *q = new PriorityQueue(4)); +}*/ + +/*TEST(PRIORITY_QUEUE_ON_HEAP, can_create_priority_queue_2) { + Data **data = new Data*[3]; + for (int i = 0; i < 3; i++) { + data[i] = new Data; + data[i]->priority = 1; + } + ASSERT_NO_THROW(PriorityQueue *q = new PriorityQueue(data, 3, 4)); +}*/ + +TEST(PRIORITY_QUEUE_ON_HEAP, can_add_element_in_queue) { + PriorityQueue *q = new PriorityQueue(4); + Data *tmp = new Data; + tmp->priority = 1; + ASSERT_NO_THROW(q->add(&tmp)); + q->add(&tmp); +} + +TEST(PRIORITY_QUEUE_ON_HEAP, add_in_queue_works_correctly) { + PriorityQueue *q = new PriorityQueue(4); + Data *tmp = new Data; + tmp->priority = 4; + q->add(&tmp); + EXPECT_EQ(4, q->pop(0)->priority); +} + +TEST(PRIORITY_QUEUE_ON_HEAP, throw_when_try_add_element_into_full_queue) { + Data **data = new Data*[MAXsize]; + for (int i = 0; i < MAXsize; i++) { + data[i] = new Data; + data[i]->priority = i; + } + PriorityQueue *q = new PriorityQueue(data, MAXsize, 4); + Data* tmp = new Data(); + tmp->priority = 1; + ASSERT_ANY_THROW(q->add(&tmp)); + q->pop(0); +} + +TEST(PRIORITY_QUEUE_ON_HEAP, can_pop_element) { + PriorityQueue *q = new PriorityQueue(4); + Data* i = new Data(); + Data* j = new Data(); + i->priority = 1; + j->priority = 2; + q->add(&i); + q->add(&j); + ASSERT_NO_THROW(q->pop(1)); +} + +TEST(PRIORITY_QUEUE_ON_HEAP, pop_works_correctly) { + PriorityQueue *q = new PriorityQueue(4); + Data* i = new Data(); + Data* j = new Data(); + i->priority = 1; + j->priority = 2; + q->add(&i); + q->add(&j); + EXPECT_EQ(1, q->pop(0)->priority); +} + +TEST(PRIORITY_QUEUE_ON_HEAP, throw_when_try_pop_from_empty_queue) { + PriorityQueue *q = new PriorityQueue(4); + ASSERT_ANY_THROW(q->pop(0)); + Data* i = new Data(); + i->priority = 1; + q->add(&i); + q->pop(0); +} + +TEST(PRIORITY_QUEUE_ON_HEAP, can_pop_min_element) { + PriorityQueue *q = new PriorityQueue(4); + Data* i = new Data(); + Data* j = new Data(); + i->priority = 1; + j->priority = 2; + q->add(&i); + q->add(&j); + ASSERT_NO_THROW(q->pop_min()); +} +TEST(PRIORITY_QUEUE_ON_HEAP, pop_min_works_correctly) { + PriorityQueue *q = new PriorityQueue(4); + Data* i = new Data(); + Data* j = new Data(); + i->priority = 1; + j->priority = 2; + q->add(&i); + q->add(&j); + EXPECT_EQ(1, q->pop_min()->priority); +} + +TEST(PRIORITY_QUEUE_ON_HEAP, throw_when_try_pop_min_from_empty_queue) { + PriorityQueue *q = new PriorityQueue(4); + ASSERT_ANY_THROW(q->pop_min()); + Data* i = new Data(); + i->priority = 1; + q->add(&i); + q->pop_min(); +} + +TEST(PRIORITY_QUEUE_ON_HEAP, isFull_work_correctly) { + Data **data = new Data*[MAXsize]; + for (int i = 0; i < MAXsize; i++) { + data[i] = new Data; + data[i]->priority = i; + } + PriorityQueue *q = new PriorityQueue(data, MAXsize, 2); + ASSERT_TRUE(q->isFull()); + q->pop_min(); +} + +TEST(PRIORITY_QUEUE_ON_HEAP, isFull_work_correctly_when_queue_is_not_full) { + PriorityQueue *q = new PriorityQueue(4); + ASSERT_FALSE(q->isFull()); + Data* i = new Data(); + i->priority = 1; + q->add(&i); +} + +TEST(PRIORITY_QUEUE_ON_HEAP, isEmpty_work_correctly) { + PriorityQueue *q = new PriorityQueue(4); + Data* i = new Data(); + i->priority = 1; + q->add(&i); + q->pop(0); + ASSERT_TRUE(q->isEmpty()); +} + +TEST(PRIORITY_QUEUE_ON_HEAP, isEmpty_work_correctly_when_queue_is_not_empty) { + PriorityQueue *q = new PriorityQueue(4); + Data* i = new Data(); + i->priority = 1; + q->add(&i); + ASSERT_FALSE(q->isEmpty()); +}