diff --git a/app/main.cpp b/app/main.cpp index 4485790..229c233 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -1,6 +1,59 @@ -#include "add.h" -#include +#include "Dijkstra.h" +#include "graph.h" int main() { - std::cout << "2 + 2 = " << add(2, 2) << std::endl; + Graph *graph = new Graph(8, 12); + + graph->insert_edge(0, 1, 3); + graph->insert_edge(1, 2, 1); + graph->insert_edge(1, 3, 4); + graph->insert_edge(1, 4, 4); + graph->insert_edge(2, 5, 10); + graph->insert_edge(3, 4, 1); + graph->insert_edge(3, 6, 1); + graph->insert_edge(4, 5, 1); + graph->insert_edge(4, 6, 8); + graph->insert_edge(4, 7, 4); + graph->insert_edge(5, 7, 6); + graph->insert_edge(6, 7, 1); + + int min_1 = HeapDijkstra(&graph, 0); + std::cout << " Min way from start position to end - " << min_1 << std::endl; + + std::vector < std::vector < std::pair > > g(8); + g[0] = std::vector< std::pair>(1); + g[0][0].first = 1; + g[0][0].second = 3; + g[1] = std::vector< std::pair>(3); + g[1][0].first = 2; + g[1][0].second = 1; + g[1][1].first = 3; + g[1][1].second = 4; + g[1][2].first = 4; + g[1][2].second = 4; + g[2] = std::vector< std::pair>(1); + g[2][0].first = 5; + g[2][0].second = 10; + g[3] = std::vector< std::pair>(2); + g[3][0].first = 4; + g[3][0].second = 1; + g[3][1].first = 6; + g[3][1].second = 1; + g[4] = std::vector< std::pair>(3); + g[4][0].first = 5; + g[4][0].second = 1; + g[4][1].first = 6; + g[4][1].second = 8; + g[4][2].first = 7; + g[4][2].second = 4; + g[5] = std::vector< std::pair>(1); + g[5][0].first = 7; + g[5][0].second = 6; + g[6] = std::vector< std::pair>(1); + g[6][0].first = 7; + g[6][0].second = 1; + + int min_2 = TreeDijkstra(g, 0); + std::cout << " Min way from start position to end - " << min_2 << std::endl; + return 0; } diff --git a/include/Dijkstra.h b/include/Dijkstra.h new file mode 100644 index 0000000..f7c5cd3 --- /dev/null +++ b/include/Dijkstra.h @@ -0,0 +1,23 @@ +#ifndef INCLUDE_DIJKSTRA_H_ +#define INCLUDE_DIJKSTRA_H_ + +#include "graph.h" +#include "d_heap.h" +#include "priority_queue.h" +#include "RBtree.h" + +const int INF = 10000000; + +class Dijkstra_Data: public Data { + public: + int num; + Dijkstra_Data(int num, int p) { + this->num = num; + priority = p; + } +}; + +int HeapDijkstra(Graph ** _graph, int start); +int TreeDijkstra(std::vector < std::vector < std::pair > > g, int start); + +#endif // INCLUDE_DIJKSTRA_H_ diff --git a/include/RBtree.h b/include/RBtree.h new file mode 100644 index 0000000..2d44903 --- /dev/null +++ b/include/RBtree.h @@ -0,0 +1,331 @@ +#ifndef INCLUDE_RBTREE_H_ +#define INCLUDE_RBTREE_H_ + +#include "RBtreeNode.h" +#include + +template +class RBTree { + RBtreeNode* root; + + void left_rotate(RBtreeNode *node); + void right_rotate(RBtreeNode *node); + void fixup_after_insert(RBtreeNode *node); + void fixup_after_delete(RBtreeNode *node); + public: + RBTree(); + explicit RBTree(T _val); + ~RBTree(void); + RBtreeNode* get_root(); + + void RB_insert(T _val); + void RB_delete(T _val); + RBtreeNode* RB_find(T _val); + RBtreeNode* get_min(); +}; + +/* Конструкторы */ +template +RBTree::RBTree() { + root = reinterpret_cast*>(NullNode); +} + +template +RBTree::RBTree(T _val) { + root = new RBtreeNode; + root->value = _val; + root->color = COLOR_BLACK; + root->left = root->right = reinterpret_cast*>(NullNode); + root->parent = 0; +} + +/* Деструктор */ +template +RBTree::~RBTree(void) { + while (root != reinterpret_cast*>(NullNode)) + RB_delete(root->value); +} + +template +RBtreeNode* RBTree::get_root() { + return root; +} + +/* Левый поворот */ +template +void RBTree::left_rotate(RBtreeNode *node) { + RBtreeNode *right = node->right; + node->right = right->left; + + if (right->left != reinterpret_cast*>(NullNode)) + right->left->parent = node; + right->parent = node->parent; + + if (node->parent != 0) { + if (node == node->parent->left) { + node->parent->left = right; + } else { + node->parent->right = right; + } + } else { + root = right; + } + right->left = node; + node->parent = right; +} + +/* Правый поворот */ +template +void RBTree::right_rotate(RBtreeNode *node) { + RBtreeNode *left = node->left; + node->left = left->right; + + if (left->right != reinterpret_cast*>(NullNode)) + left->right->parent = node; + left->parent = node->parent; + + if (node->parent != 0) { + if (node == node->parent->left) { + node->parent->left = left; + } else { + node->parent->right = left; + } + } else { + root = left; + } + left->right = node; + node->parent = left; +} + +/* Восстановление свойств после добавления */ +template +void RBTree::fixup_after_insert(RBtreeNode *node) { + while ((node != root) && (node->parent->color == COLOR_RED)) { + // узел в левом поддереве grandfather + if (node->parent == node->parent->parent->left) { + RBtreeNode *uncle = node->parent->parent->right; + if (uncle->color == COLOR_RED) { + // случай 1 - uncle RED + node->parent->color = COLOR_BLACK; + uncle->color = COLOR_BLACK; + node->parent->parent->color = COLOR_RED; + node = node->parent->parent; + } else { + // случаи 2 и 3 - uncle BLACK + if (node == node->parent->right) { + // сведение случая 2 к случаю 3 + node = node->parent; + left_rotate(node); + } + // случай 3 + node->parent->color = COLOR_BLACK; + node->parent->parent->color = COLOR_RED; + right_rotate(node->parent->parent); + } + } else { + // узел в правом поддереве grandfather + RBtreeNode *y = node->parent->parent->left; + if (y->color == COLOR_RED) { + // случай 4 - uncle RED + node->parent->color = COLOR_BLACK; + y->color = COLOR_BLACK; + node->parent->parent->color = COLOR_RED; + node = node->parent->parent; + } else { + // случаи 5 и 6 - uncle BLACK + if (node == node->parent->left) { + // сведение случая 5 к случаю 6 + node = node->parent; + right_rotate(node); + } + // случай 6 + node->parent->color = COLOR_BLACK; + node->parent->parent->color = COLOR_RED; + left_rotate(node->parent->parent); + } + } + } + root->color = COLOR_BLACK; +} + +/* Добавление узла */ +template +void RBTree::RB_insert(T _val) { + RBtreeNode *node = root, *parent = 0, *newnode = 0; + + // поиск листа для нового элемента + while (node != reinterpret_cast*>(NullNode)) { + if (node->value == _val) + throw std::logic_error("Input error: such value alreade exist.\n"); + parent = node; + if (_val < node->value) { + node = node->left; + } else { + node = node->right; + } + } + newnode = new RBtreeNode; + newnode->value = _val; + newnode->color = COLOR_RED; + newnode->left = reinterpret_cast*>(NullNode); + newnode->right = reinterpret_cast*>(NullNode); + newnode->parent = parent; + + if (parent == 0) { + root = newnode; + } else { + if (_val < parent->value) { + parent->left = newnode; + } else { + parent->right = newnode; + } + } + fixup_after_insert(newnode); +} + +/* Восстановление свойств после удаления */ +template +void RBTree::fixup_after_delete(RBtreeNode *node) { + while ((node != root) && (node->color == COLOR_BLACK)) { + // узел в левом поддереве grandfather + if (node == node->parent->left) { + RBtreeNode *uncle = node->parent->right; + if (uncle->color == COLOR_RED) { + // случай 1 - uncle RED + uncle->color = COLOR_BLACK; + node->parent->color = COLOR_RED; + left_rotate(node->parent); + uncle = node->parent->right; + } + if ((uncle->left->color == COLOR_BLACK) && + (uncle->right->color == COLOR_BLACK)) { + // случаи 2 и 3 - uncle BLACK + uncle->color = COLOR_RED; + node = node->parent; + } else { + // случай 3 + if (uncle->right->color == COLOR_BLACK) { + uncle->left->color = COLOR_BLACK; + uncle->color = COLOR_RED; + right_rotate(uncle); + uncle = node->parent->right; + } + // случай 4 + uncle->color = node->parent->color; + node->parent->color = COLOR_BLACK; + uncle->right->color = COLOR_BLACK; + left_rotate(node->parent); + node = root; + } + } else { + // узел в левом поддереве grandfather + RBtreeNode *uncle = node->parent->left; + if (uncle->color == COLOR_RED) { + uncle->color = COLOR_BLACK; + node->parent->color = COLOR_RED; + right_rotate(node->parent); + uncle = node->parent->left; + } + if ((uncle->right->color == COLOR_BLACK) && + (uncle->left->color == COLOR_BLACK)) { + // случаи 6 и 7 - uncle BLACK + uncle->color = COLOR_RED; + node = node->parent; + } else { + // случай 7 + if (uncle->left->color == COLOR_BLACK) { + uncle->right->color = COLOR_BLACK; + uncle->color = COLOR_RED; + left_rotate(uncle); + uncle = node->parent->left; + } + // случай 8 + uncle->color = node->parent->color; + node->parent->color = COLOR_BLACK; + uncle->left->color = COLOR_BLACK; + right_rotate(node->parent); + node = root; + } + } + } + node->color = COLOR_BLACK; +} + +/* Удаление узла */ +template +void RBTree::RB_delete(T _val) { + RBtreeNode *node, *parent, *_node; + + _node = root; + while (_node != reinterpret_cast*>(NullNode)) { + if (_node->value == _val) { + break; + } else { + if (_val < _node->value) { + _node = _node->left; + } else { + _node = _node->right; + } + } + } + + if (_node == reinterpret_cast*>(NullNode)) + throw std::logic_error("Input error: value doesn't exist.\n"); + if ((_node->left == reinterpret_cast*>(NullNode)) || + (_node->right == reinterpret_cast*>(NullNode))) { + parent = _node; + } else { + parent = _node->right; + while (parent->left != reinterpret_cast*>(NullNode)) + parent = parent->left; + } + if (parent->left != reinterpret_cast*>(NullNode)) { + node = parent->left; + } else { + node = parent->right; + } + node->parent = parent->parent; + if (parent->parent != 0) { + if (parent == parent->parent->left) { + parent->parent->left = node; + } else { + parent->parent->right = node; + } + } else { + root = node; + } + if (parent != _node) + _node->value = parent->value; + if (parent->color == COLOR_BLACK) + fixup_after_delete(node); + delete parent; +} + +/* Поиск по значению */ +template +RBtreeNode* RBTree::RB_find(T _val) { + RBtreeNode *cur = root; + while (cur != 0) { + if (_val == cur->value) { + return cur; + } else { + if (_val < cur->value) { + cur = cur->left; + } else { + cur = cur->right; + } + } + } + throw std::logic_error("Don't found.\n"); +} + +template +RBtreeNode* RBTree::get_min() { + RBtreeNode* node = root; + while (node->left != reinterpret_cast*>(NullNode)) { + node = node->left; + } + return node; +} + +#endif // INCLUDE_RBTREE_H_ diff --git a/include/RBtreeNode.h b/include/RBtreeNode.h new file mode 100644 index 0000000..2805087 --- /dev/null +++ b/include/RBtreeNode.h @@ -0,0 +1,19 @@ +#ifndef INCLUDE_RBTREENODE_H_ +#define INCLUDE_RBTREENODE_H_ + +#define COLOR_RED 1 +#define COLOR_BLACK 0 +#define NullNode &EmptyNode + +template +struct RBtreeNode { + T value; + int color; + RBtreeNode *left; + RBtreeNode *right; + RBtreeNode *parent; +}; + +extern RBtreeNode EmptyNode; + +#endif // INCLUDE_RBTREENODE_H_ 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..0f3203d --- /dev/null +++ b/include/d_heap.h @@ -0,0 +1,39 @@ +#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); +}; + +#endif // INCLUDE_D_HEAP_H_ diff --git a/include/graph.h b/include/graph.h new file mode 100644 index 0000000..782535a --- /dev/null +++ b/include/graph.h @@ -0,0 +1,54 @@ +#ifndef INCLUDE_GRAPH_H_ +#define INCLUDE_GRAPH_H_ +#include +#include +#include +#define MAXver 1000 + +/* Рёбра графа */ +class Edges { + public: + int x; + int y; + int weight; + Edges(int _x, int _y, int _w) { + this->x = _x; + this->y = _y; + this->weight = _w; + } +}; + +class Graph { + private: + int verices; + int edge; + int size; + int* ver_mas; + Edges** edge_mas; + + public: + explicit Graph(int _ver); + Graph(int _ver, int _edge); + ~Graph(); + + int get_ver(); + int get_edge_num(); + int get_size(); + int get_weight(int _x, int _y); + Edges* get_edge(int i); + Edges** get_edge_mas(); + + int isFull(); + int isEmpty(); + + void create_ver(int *x, int *y); + void create_graph(int min_w, int max_w); + void insert_edge(int _x, int _y, int _w); + void delete_edge(int _x, int _y); + int find_edge_num(int _x, int _y); +}; + +std::vector < std::vector < std::pair > > make_graph(char filename[]); +Graph create_graph(char *q); + +#endif // INCLUDE_GRAPH_H_ diff --git a/include/priority_queue.h b/include/priority_queue.h new file mode 100644 index 0000000..46611ee --- /dev/null +++ b/include/priority_queue.h @@ -0,0 +1,76 @@ +#ifndef INCLUDE_PRIORITY_QUEUE_H_ +#define INCLUDE_PRIORITY_QUEUE_H_ +#include "d_heap.h" +#include "RBtree.h" + +/*----------------------------------------------------*/ +/* Приоритетная очередь на 2-куче */ +/*----------------------------------------------------*/ + +class PriorityQueueHeap { + protected: + D_Heap *heap; + public: + explicit PriorityQueueHeap(int d); + PriorityQueueHeap(Data **keys, int num, int d); + ~PriorityQueueHeap(); + int isFull(); + int isEmpty(); + + void add(Data **key); + Data* pop(int i); + Data* pop_min(); + void update(); +}; + +/*----------------------------------------------------*/ +/* Приоритетная очередь на красно-черных деревьях */ +/*----------------------------------------------------*/ + +template +class PriorityQueueRBtree { + RBTree tree; + + public: + int isEmpty(); + + void add(T _val); + void pop(T _val); + RBtreeNode* find(T _val); + RBtreeNode* min(); +}; + +/*----------------------------------------------------*/ +/* Приоритетная очередь на красно-черных деревьях */ +/*----------------------------------------------------*/ + +/* Поиск */ +template +RBtreeNode* PriorityQueueRBtree::find(T _val) { + return tree.RB_find(_val); +} + +/* Минимальный */ +template +RBtreeNode* PriorityQueueRBtree::min() { + return tree.get_min(); +} + +/* Вставка */ +template +void PriorityQueueRBtree::add(T _val) { + tree.RB_insert(_val); +} + +/* удаление */ +template +void PriorityQueueRBtree::pop(T _val) { + tree.RB_delete(_val); +} + +template +int PriorityQueueRBtree::isEmpty() { + return (tree.get_root() == reinterpret_cast*>(NullNode)); +} + +#endif // INCLUDE_PRIORITY_QUEUE_H_ diff --git a/otchet/Otchet_lab_4.doc b/otchet/Otchet_lab_4.doc new file mode 100644 index 0000000..90ee1fd Binary files /dev/null and b/otchet/Otchet_lab_4.doc differ diff --git a/src/Dijkstra.cpp b/src/Dijkstra.cpp new file mode 100644 index 0000000..fdaec49 --- /dev/null +++ b/src/Dijkstra.cpp @@ -0,0 +1,125 @@ +#include "Dijkstra.h" +#include +#include + +/* Алгортм Дейкстры */ +/* на д-куче */ + +int HeapDijkstra(Graph **_graph, int start) { + std::cout << "DIJKSTRA ALGORITHM ON HEAP" << std::endl; + // проверка корректности входных данных + int verices = (*_graph)->get_ver(); + if (!verices) + throw std::logic_error("Error: there in not verix in graph.\n"); + if (start < 0 || start > verices) + throw std::logic_error("Input error: wrong start verix.\n"); + + // подготовка данных для работы алгоритма + int edge_ = (*_graph)->get_size(); + Data** dist = new Data*[verices]; + int* p = new int[verices]; + + for (int i = 0; i < verices; i++) { + p[i] = 0; + dist[i] = new Dijkstra_Data(i, INF); + } + dist[start]->priority = 0; + PriorityQueueHeap* q = new PriorityQueueHeap(dist, verices, 2); + Edges** edges = (*_graph)->get_edge_mas(); + + // алгоритм Дейкстры + while (!q->isEmpty()) { + int current = (reinterpret_cast(q->pop(0)))->num; + int d; + for (int i = 0; i < edge_; i++) { + if (current == edges[i]->x) { + d = dist[edges[i]->y]->priority; + if (d > dist[edges[i]->x]->priority + (*_graph)->get_weight(edges[i]->x, edges[i]->y)) { + dist[edges[i]->y]->priority = dist[edges[i]->x]->priority + + (*_graph)->get_weight(edges[i]->x, edges[i]->y); + p[edges[i]->y] = edges[i]->x; + q->update(); + } + } + if (current == edges[i]->y) { + d = dist[edges[i]->x]->priority; + if (d > dist[edges[i]->y]->priority + (*_graph)->get_weight(edges[i]->x, edges[i]->y)) { + dist[edges[i]->x]->priority = dist[edges[i]->y]->priority + + (*_graph)->get_weight(edges[i]->x, edges[i]->y); + p[edges[i]->x] = edges[i]->y; + q->update(); + } + } + } + } + + // вывод и удаление (можно было реализовать воврат полученного dist) + int min; + std::cout << std::endl; + std::cout << "Process of search shortest way: " << std::endl; + for (int i = 1; i < verices; i++) { + std::cout << " -> " << p[i]; + } + std::cout << " -> " << verices - 1; + std::cout << std::endl; + for (int i = 0; i < verices; i++) { + if (i == start) { + std::cout << "Start position: " << start << std::endl; + continue; + } + std::cout << start << " -> " << i << " " << dist[i]->priority << std::endl; + min = dist[i]->priority; + delete dist[i]; + } + delete[]dist; + delete q; + return min; +} + +/* Алгортм Дейкстры */ +/* на красно-чёрных деревьях */ + +int TreeDijkstra(std::vector < std::vector < std::pair > > g, int start) { + std::cout << std::endl; + std::cout << "DIJKSTRA ALGORITHM ON RB TREE" << std::endl; + // проверка корректности входных данных + if (g.empty() || (start < 0) || (start > static_cast(g.size()))) + throw std::logic_error("Input error: graph is empty or wrong start virtex.\n"); + + // подготовка данных для работы алгоритма + std::vector dist(g.size(), INF); + int v; + dist[start] = 0; + PriorityQueueRBtree < std::pair > pq; + pq.add(std::pair(0, start)); + + // алгоритм Дейкстры + while (!pq.isEmpty()) { + std::pair current = pq.min()->value; + pq.pop(current); + v = current.second; + for (int i = 0; i < static_cast(g[v].size()); ++i) { + if (dist[v] + g[v][i].second < dist[g[v][i].first]) { + if (dist[g[v][i].first] != INF) + pq.pop(std::pair(dist[g[v][i].first], + g[v][i].first)); + dist[g[v][i].first] = dist[v] + g[v][i].second; + pq.add(std::pair(dist[g[v][i].first], g[v][i].first)); + } + } + } + + // вывод (можно было реализовать воврат полученного d) + std::cout << std::endl; + int size = dist.size(); + for (int i = 0; i < size; i++) { + if (i == start) { + std::cout << "Start position: " << start << std::endl; + continue; + } + std::cout << start << " -> " << i << " " << dist[i] << std::endl; + } + int min = dist[size - 1]; + return min; +} + diff --git a/src/RB_tree.cpp b/src/RB_tree.cpp new file mode 100644 index 0000000..c6d3e76 --- /dev/null +++ b/src/RB_tree.cpp @@ -0,0 +1,3 @@ +#include "RBtreeNode.h" + +RBtreeNode EmptyNode = { 0, 0, 0, 0, 0 }; 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..0676a32 --- /dev/null +++ b/src/d_heap.cpp @@ -0,0 +1,147 @@ +#include "d_heap.h" + +/* Конструкторы */ +D_Heap::D_Heap(int d) { + if (d <= 0) + throw std::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 std::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 std::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 std::logic_error("Heap is empty.\n"); + Data* keys = key[size]; + size--; + return keys; +} + +Data* D_Heap::erase(int i) { + if (isEmpty()) + throw std::logic_error("Heap is empty.\n"); + if ((i < 0) || (i > size)) + throw std::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 std::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 std::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 std::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; +} diff --git a/src/graph.cpp b/src/graph.cpp new file mode 100644 index 0000000..6baaad4 --- /dev/null +++ b/src/graph.cpp @@ -0,0 +1,179 @@ +#include "graph.h" +#include +#include +#include +#include +#include + +/* Конструкторы */ +Graph::Graph(int _ver) { + if (_ver < 0 || _ver > MAXver) + throw std::logic_error("Input error: wrong vertices number.\n"); + this->verices = _ver; + this->edge = _ver*(_ver - 1) / 2; + size = 0; + ver_mas = new int[_ver]; + edge_mas = new Edges*[edge]; +} + +Graph::Graph(int _ver, int _edge) { + if (_ver < 0 || _ver > MAXver) + throw std::logic_error("Input error: wrong vertices number.\n"); + if (_edge < 0 || _edge > _ver * (_ver - 1) / 2) + throw std::logic_error("Input error: wrong edges number.\n"); + this->verices = _ver; + this->edge = _edge; + size = 0; + ver_mas = new int[_ver]; + edge_mas = new Edges*[_edge]; +} + +/* Деструктор */ +Graph::~Graph() { + for (int i = 0; i < size; i++) + delete edge_mas[i]; + delete[]edge_mas; + delete[]ver_mas; +} + +/* Функции возврата параметров графа*/ + +/* Количество вершин */ +int Graph::get_ver() { + return verices; +} + +/* Число рёбер графа */ +int Graph::get_edge_num() { + return edge; +} + +/* Размер графа */ +int Graph::get_size() { + return size; +} + +/* Расстояние между двумя вершинами */ +int Graph::get_weight(int _x, int _y) { + int i = find_edge_num(_x, _y); + return edge_mas[i]->weight; +} + +/* Ребро */ +Edges* Graph::get_edge(int i) { + return edge_mas[i]; +} + +/* Массив рёбер */ +Edges** Graph::get_edge_mas() { + if (size == 0) + return nullptr; + return edge_mas; +} + +int Graph::isFull() { + return edge == size; +} + +int Graph::isEmpty() { + return size == 0; +} + +/* Создание вершины */ +void Graph::create_ver(int *x, int *y) { + *x = rand() % verices; + *y = rand() % verices; + if (x == y || find_edge_num(*x, *y) != -1) + create_ver(x, y); +} + +/* Создание графа */ +void Graph::create_graph(int min_w, int max_w) { + if (min_w > max_w) + throw std::logic_error("Input error: min must be < max.\n"); + int x_, y_, w_; + for (int i = 0; i < edge; i++) { + time_t timet; + time(&timet); + srand(static_cast(timet)); + create_ver(&x_, &y_); + w_ = rand() % static_cast(max_w - min_w + 1) + min_w; + edge_mas[i] = new Edges(x_, y_, w_); + size++; + } +} + +/* Добавление ребра */ +void Graph::insert_edge(int _x, int _y, int _w) { + if (isFull()) + throw std::logic_error("Graph is FULL.\n"); + if (find_edge_num(_x, _y) != -1) + throw std::logic_error("Edge already exist.\n"); + if (_x == _y) + throw std::logic_error("Input error: x = y.\n"); + edge_mas[size] = new Edges(_x, _y, _w); + size++; +} + +/* Удаление ребра */ +void Graph::delete_edge(int _x, int _y) { + int i = find_edge_num(_x, _y); + if (i == -1) + throw std::logic_error("Edge doesn't exist.\n"); + delete edge_mas[i]; + edge_mas[i] = edge_mas[size - 1]; + size--; +} + +/* Номер ребра между вершинами в массиве рёбер */ +int Graph::find_edge_num(int _x, int _y) { + for (int i = 0; i < size; i++) { + if ((edge_mas[i]->x == _x && edge_mas[i]->y == _y) || + (edge_mas[i]->x == _y && edge_mas[i]->y == _x)) + return i; + } + return -1; +} + +/* Чтение из файла для графа на встроенных структурах*/ +std::vector < std::vector < std::pair > > make_graph(char filename[]) { + std::ifstream file(filename); + int N, n; + // считываем число вершин + file >> N; + std::vector < std::vector < std::pair > > g(N); + // считываем рёбра + for (int i = 0; i < N; ++i) { + file >> n; + g[i] = std::vector< std::pair>(n); + for (int j = 0; j < n; ++j) { + file >> g[i][j].first >> g[i][j].second; + } + } + return g; +} + +/* Чтение из файла для реализованного графа*/ +Graph create_graph(char *q) { + FILE *F; + int N = 0; + F = fopen(q, "r"); + if (F == NULL) { + throw std::logic_error("Input error. Can't open this file.\n"); + } + // считывание количества вершин графа + fscanf(F, "%d", &N); + Graph g(N); // граф + + int tmp, num, w; + for (int i = 0; i < N; i++) { + fscanf(F, "%d", &num); + for (int j = 0; j < num; j++) { + fscanf(F, "%d", &tmp); + fscanf(F, "%d", &w); + g.insert_edge(i, tmp, w); + } + } + fclose(F); + return g; +} diff --git a/src/priority_queue.cpp b/src/priority_queue.cpp new file mode 100644 index 0000000..3f7e0f0 --- /dev/null +++ b/src/priority_queue.cpp @@ -0,0 +1,49 @@ +#include "priority_queue.h" +#include "RBtree.h" + +/*----------------------------------------------------*/ +/* Приоритетная очередь на 2-куче */ +/*----------------------------------------------------*/ + +/* Конструкторы */ +PriorityQueueHeap::PriorityQueueHeap(int d) { + heap = new D_Heap(d = 2); +} + +PriorityQueueHeap::PriorityQueueHeap(Data **keys, int num, int d) { + heap = new D_Heap(d = 2); + heap->insert_group(keys, num); +} + +/* Деструктор */ +PriorityQueueHeap ::~PriorityQueueHeap() { + delete heap; +} + +int PriorityQueueHeap::isFull() { + return heap->isFull(); +} + +int PriorityQueueHeap::isEmpty() { + return heap->isEmpty(); +} + +/* Добавление ключа в очередь */ +void PriorityQueueHeap::add(Data **key) { + heap->insert(key); +} + +/* Удаление */ +Data* PriorityQueueHeap::pop(int i) { + return heap->erase(i); +} + +/* Удаление минимального */ +Data* PriorityQueueHeap::pop_min() { + return heap->erase(); +} + +/* Обновление очереди */ +void PriorityQueueHeap::update() { + heap->hilling(); +} diff --git a/test/test_Dijkstra.cpp b/test/test_Dijkstra.cpp new file mode 100644 index 0000000..e06ebfe --- /dev/null +++ b/test/test_Dijkstra.cpp @@ -0,0 +1,78 @@ +#include "gtest/gtest.h" +#include "Dijkstra.h" +#include + +/*TEST(DIJKSTRA, throw_when_try_work_without_vertices) { + Graph *graph = new Graph(0); + ASSERT_ANY_THROW(HeapDijkstra(&graph, 0)); +}*/ + +TEST(DIJKSTRA, throw_when_try_work_with_wrong_start_vertex) { + Graph *graph = new Graph(4); + graph->insert_edge(0, 1, 2); + ASSERT_ANY_THROW(HeapDijkstra(&graph, 9)); +} + +TEST(DIJKSTRA, experiment_1) { + Graph *graph = new Graph(4); + graph->insert_edge(0, 1, 1); + graph->insert_edge(1, 2, 2); + graph->insert_edge(2, 3, 2); + graph->insert_edge(3, 0, 8); + EXPECT_EQ(2, HeapDijkstra(&graph, 2)); + EXPECT_EQ(5, HeapDijkstra(&graph, 0)); +} + +TEST(DIJKSTRA, experiment_2) { + Graph *graph = new Graph(4, 6); + graph->insert_edge(0, 1, 1); + graph->insert_edge(0, 2, 1); + graph->insert_edge(0, 3, 8); + graph->insert_edge(1, 2, 4); + graph->insert_edge(1, 3, 6); + graph->insert_edge(2, 3, 5); + EXPECT_EQ(5, HeapDijkstra(&graph, 2)); + EXPECT_EQ(6, HeapDijkstra(&graph, 0)); +} + +TEST(DIJKSTRA, experiment_3) { + Graph *graph = new Graph(8, 13); + graph->insert_edge(0, 1, 3); + graph->insert_edge(1, 2, 2); + graph->insert_edge(1, 3, 4); + graph->insert_edge(1, 4, 1); + graph->insert_edge(2, 4, 3); + graph->insert_edge(2, 5, 10); + graph->insert_edge(3, 4, 2); + graph->insert_edge(3, 6, 5); + graph->insert_edge(4, 5, 7); + graph->insert_edge(4, 6, 8); + graph->insert_edge(4, 7, 4); + graph->insert_edge(5, 7, 6); + graph->insert_edge(6, 7, 1); + EXPECT_EQ(8, HeapDijkstra(&graph, 0)); +} + +TEST(DIJKSTRA, experiment_4) { + Graph *graph = new Graph(8, 13); + graph->insert_edge(0, 1, 3); + graph->insert_edge(1, 2, 1); + graph->insert_edge(1, 3, 4); + graph->insert_edge(1, 4, 1); + graph->insert_edge(2, 4, 1); + graph->insert_edge(2, 5, 10); + graph->insert_edge(3, 4, 1); + graph->insert_edge(3, 6, 1); + graph->insert_edge(4, 5, 7); + graph->insert_edge(4, 6, 8); + graph->insert_edge(4, 7, 4); + graph->insert_edge(5, 7, 6); + graph->insert_edge(6, 7, 1); + EXPECT_EQ(7, HeapDijkstra(&graph, 0)); +} + +TEST(DIJKSTRA, work_right_with_one_virtex) { + std::vector < std::vector < std::pair > > graph(1); + int res = TreeDijkstra(graph, 0); + EXPECT_EQ(res, 0); +} diff --git a/test/test_RBtree.cpp b/test/test_RBtree.cpp new file mode 100644 index 0000000..7c039c5 --- /dev/null +++ b/test/test_RBtree.cpp @@ -0,0 +1,88 @@ +#include +#include "RBtree.h" + +/*TEST(RBTree, can_create_empty_tree) { + ASSERT_NO_THROW(RBTree a()); + RBTree b; + EXPECT_EQ(b.get_root(), NullNode); +}*/ + +/*TEST(RB_TREE, can_create_tree) { + ASSERT_NO_THROW(RBTree tree(5)); +}*/ + +TEST(RB_TREE, create_tree_correctly) { + RBTree tree(5); + int res = tree.get_root()->value; + EXPECT_EQ(res , 5); +} + +/*TEST(RB_TREE, can_insert) { + RBTree tree(5); + ASSERT_NO_THROW(tree.RB_insert(3)); +}*/ + +/*TEST(RB_TREE, can_insert_node_in_empty_tree) { + RBTree tree; + ASSERT_NO_THROW(tree.RB_insert(1)); +}*/ + +/*TEST(RB_TREE, throw_when_try_insert_exist_node) { + RBTree tree(5); + ASSERT_ANY_THROW(tree.RB_insert(5)); +}*/ + +TEST(RB_TREE, can_find_node) { + RBTree tree(5); + tree.RB_insert(1); + ASSERT_NO_THROW(tree.RB_find(1)); +} + +TEST(RB_TREE, find_node_correctly) { + RBTree tree(5); + tree.RB_insert(4); + RBtreeNode *result = tree.RB_find(4); + EXPECT_EQ(result->value, 4); +} + +TEST(RB_TREE, throw_when_try_find_dont_exist_node) { + RBTree tree(5); + tree.RB_insert(1); + ASSERT_ANY_THROW(tree.RB_find(3)); +} + +TEST(RB_TREE, can_insert_2) { + RBTree tree(8); + tree.RB_insert(7); + ASSERT_NO_THROW(tree.RB_insert(2)); + ASSERT_NO_THROW(tree.RB_insert(5)); + ASSERT_NO_THROW(tree.RB_insert(1)); + ASSERT_NO_THROW(tree.RB_insert(3)); + ASSERT_NO_THROW(tree.RB_insert(4)); + ASSERT_NO_THROW(tree.RB_insert(9)); + ASSERT_NO_THROW(tree.RB_find(4)); +} + +TEST(RB_TREE, throw_when_try_delete_dont_exist_node) { + RBTree tree(5); + tree.RB_insert(2); + ASSERT_ANY_THROW(tree.RB_delete(3)); +} + +TEST(RB_TREE, can_delete_node_with_no_childs) { + RBTree tree(5); + tree.RB_insert(2); + ASSERT_NO_THROW(tree.RB_delete(2)); +} + +TEST(RB_TREE, can_delete_node_with_child) { + RBTree tree(6); + tree.RB_insert(3); + ASSERT_NO_THROW(tree.RB_insert(5)); + ASSERT_NO_THROW(tree.RB_insert(1)); + ASSERT_NO_THROW(tree.RB_insert(4)); + ASSERT_NO_THROW(tree.RB_insert(2)); + ASSERT_NO_THROW(tree.RB_find(5)); + ASSERT_NO_THROW(tree.RB_delete(5)); + ASSERT_ANY_THROW(tree.RB_find(5)); +} 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..5bb15b0 --- /dev/null +++ b/test/test_d_heap.cpp @@ -0,0 +1,290 @@ +#include +#include "d_heap.h" + +/*TEST(D_HEAP, can_create_d_heap) { + ASSERT_NO_THROW(D_Heap *heap = new D_Heap(2)); +}*/ + +TEST(D_HEAP, can_insert_new_key) { + D_Heap *heap = new D_Heap(2); + 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(2); + 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(2); + 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(2); + 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(2); + 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(2); + 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(2); + 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(2); + 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(2); + 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(2); + 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(2); + 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(2); + ASSERT_ANY_THROW(heap->erase()); +}*/ + +TEST(D_HEAP, throw_when_try_erase_negative_missing_element) { + D_Heap *heap = new D_Heap(2); + 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(2); + 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(2); + 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(2); + 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(2); + 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(2); + 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(2); + 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(2); + 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(2); + 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(2); + 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(2); + 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(2); + Data* j = new Data(); + j->priority = 1; + heap->insert(&j); + ASSERT_FALSE(heap->isEmpty()); +} diff --git a/test/test_graph.cpp b/test/test_graph.cpp new file mode 100644 index 0000000..ff6708a --- /dev/null +++ b/test/test_graph.cpp @@ -0,0 +1,109 @@ +#include +#include "graph.h" + +/*TEST(GRAPH, can_create_graph_1) { + Graph *graph; + ASSERT_NO_THROW(graph = new Graph(2)); +}*/ + +/*TEST(GRAPH, can_create_graph_2) { + Graph *graph; + ASSERT_NO_THROW(graph = new Graph(2, 1)); +}*/ + +/*TEST(GRAPH, can_create_graph) { + Graph *graph = new Graph(2); + ASSERT_NO_THROW(graph->create_graph(3, 7)); +}*/ + +/*TEST(GRAPH, can_insert_edge) { + Graph *graph = new Graph(2); + ASSERT_NO_THROW(graph->insert_edge(0, 1, 2)); +}*/ + +TEST(GRAPH, can_delete_edge) { + Graph *graph = new Graph(2); + graph->insert_edge(0, 1, 2); + ASSERT_NO_THROW(graph->delete_edge(0, 1)); +} + +TEST(GRAPH, can_find_edge_num) { + Graph *graph = new Graph(3); + graph->insert_edge(0, 1, 2); + graph->insert_edge(1, 2, 3); + graph->insert_edge(2, 0, 4); + ASSERT_NO_THROW(graph->find_edge_num(1, 2)); +} + + +TEST(GRAPH, find_edge_num_work_correctly) { + Graph *graph = new Graph(3); + graph->insert_edge(0, 1, 2); + graph->insert_edge(1, 2, 3); + graph->insert_edge(2, 0, 4); + EXPECT_EQ(1, graph->find_edge_num(1, 2)); +} + +/*TEST(GRAPH, get_ver_work_correctly) { + Graph *graph = new Graph(2); + EXPECT_EQ(2, graph->get_ver()); +}*/ + +/*TEST(GRAPH, get_edge_num_work_correctly) { + Graph *graph = new Graph(2); + EXPECT_EQ(1, graph->get_edge_num()); +}*/ + +TEST(GRAPH, get_size_work_correctly) { + Graph *graph = new Graph(2); + graph->insert_edge(0, 1, 2); + EXPECT_EQ(1, graph->get_size()); +} + +TEST(GRAPH, get_weight_work_correctly) { + Graph *graph = new Graph(2); + graph->insert_edge(0, 1, 4); + EXPECT_EQ(4, graph->get_weight(0, 1)); +} + +/*TEST(GRAPH, throw_when_try_create_graph_with_negative_verix) { + Graph *graph; + ASSERT_ANY_THROW(graph = new Graph(-2)); +}*/ + +/*TEST(GRAPH, throw_when_try_create_graph_with_too_large_verix) { + Graph *graph; + ASSERT_ANY_THROW(graph = new Graph(MAXver + 1)); +}*/ + +/*TEST(GRAPH, throw_when_try_create_graph_with_negative_edge) { + Graph *graph; + ASSERT_ANY_THROW(graph = new Graph(2, -1)); +}*/ + +/*TEST(GRAPH, throw_when_try_create_graph_with_too_large_edge) { + Graph *graph; + ASSERT_ANY_THROW(graph = new Graph(2, 2)); +}*/ + +/*TEST(GRAPH, throw_when_try_create_graph_with_wrong_weight_limitations) { + Graph *graph = new Graph(2); + ASSERT_ANY_THROW(graph->create_graph(5, 0)); +}*/ + + +/*TEST(GRAPH, throw_when_try_insert_edge_between_one_verix) { + Graph *graph = new Graph(2); + ASSERT_ANY_THROW(graph->insert_edge(1, 1, 2)); +}*/ + +TEST(GRAPH, throw_when_try_insert_exist_edge) { + Graph *graph = new Graph(2); + graph->insert_edge(0, 1, 2); + ASSERT_ANY_THROW(graph->insert_edge(0, 1, 2)); +} + +/*TEST(GRAPH, throw_when_try_delete_doesnt_exist_edge) { + Graph *graph = new Graph(3); + ASSERT_ANY_THROW(graph->delete_edge(0, 1)); +}*/ diff --git a/test/test_priority_queue.cpp b/test/test_priority_queue.cpp new file mode 100644 index 0000000..33f3c0e --- /dev/null +++ b/test/test_priority_queue.cpp @@ -0,0 +1,126 @@ +#include "gtest/gtest.h" +#include "priority_queue.h" + +/*TEST(PRIORITY_QUEUE_ON_HEAP, can_create_priority_queue_1) { + ASSERT_NO_THROW(PriorityQueueHeap *q = new PriorityQueueHeap(2)); +}*/ + +/*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(PriorityQueueHeap *q = new PriorityQueueHeap(data, 3, 2)); +}*/ + +TEST(PRIORITY_QUEUE_ON_HEAP, can_add_element_in_queue) { + PriorityQueueHeap *q = new PriorityQueueHeap(2); + Data *tmp = new Data; + tmp->priority = 1; + ASSERT_NO_THROW(q->add(&tmp)); +} +TEST(PRIORITY_QUEUE_ON_HEAP, add_in_queue_works_correctly) { + PriorityQueueHeap *q = new PriorityQueueHeap(2); + 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; + } + PriorityQueueHeap *q = new PriorityQueueHeap(data, MAXsize, 2); + Data* tmp = new Data(); + tmp->priority = 1; + ASSERT_ANY_THROW(q->add(&tmp)); +}*/ + +TEST(PRIORITY_QUEUE_ON_HEAP, can_pop_element) { + PriorityQueueHeap*q = new PriorityQueueHeap(2); + 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) { + PriorityQueueHeap*q = new PriorityQueueHeap(2); + 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) { + PriorityQueueHeap *q = new PriorityQueueHeap(2); + ASSERT_ANY_THROW(q->pop(0)); +}*/ + +TEST(PRIORITY_QUEUE_ON_HEAP, can_pop_min_element) { + PriorityQueueHeap*q = new PriorityQueueHeap(2); + 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) { + PriorityQueueHeap*q = new PriorityQueueHeap(2); + Data* i = new Data(); + Data* j = new Data(); + i->priority = 1; + j->priority = 2; + q->add(&i); + q->add(&j); + EXPECT_EQ(2, q->pop_min()->priority); +} + +/*TEST(PRIORITY_QUEUE_ON_HEAP, throw_when_try_pop_min_from_empty_queue) { + PriorityQueueHeap *q = new PriorityQueueHeap(2); + ASSERT_ANY_THROW(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; + } + PriorityQueueHeap *q = new PriorityQueueHeap(data, MAXsize, 2); + ASSERT_TRUE(q->isFull()); +}*/ + +/*TEST(PRIORITY_QUEUE_ON_HEAP, isFull_work_correctly_when_queue_is_not_full) { + PriorityQueueHeap *q = new PriorityQueueHeap(2); + ASSERT_FALSE(q->isFull()); +}*/ + +TEST(PRIORITY_QUEUE_ON_HEAP, isEmpty_work_correctly) { + PriorityQueueHeap *q = new PriorityQueueHeap(2); + 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) { + PriorityQueueHeap *q = new PriorityQueueHeap(2); + Data* i = new Data(); + i->priority = 1; + q->add(&i); + ASSERT_FALSE(q->isEmpty()); +}