diff --git a/.gitignore b/.gitignore index 7b4ae92774..3f84bbcefd 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ Release/* .vs/* build/* .vscode/* +.idea +out/* \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index b40c0dd11c..b23e21c29d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,9 +10,13 @@ else() add_compile_options(-Wall -Wextra -Wpedantic -Wno-gnu-empty-struct -Wno-unused-parameter) endif() -add_subdirectory(LibraryC) -add_subdirectory(LibraryCPP) +#add_subdirectory(LibraryC) +#add_subdirectory(LibraryCPP) add_subdirectory(LibraryCPPClass) -add_subdirectory(LibraryCPPTemplate) +#add_subdirectory(LibraryCPPTemplate) -add_subdirectory(Lab1C) +#add_subdirectory(Lab1CPP) +#add_subdirectory(Lab2CPP) +#add_subdirectory(Lab3CPP) +#add_subdirectory(Lab4CPP) +add_subdirectory(Lab5CPP) \ No newline at end of file diff --git a/Lab1C/CMakeLists.txt b/Lab1C/CMakeLists.txt deleted file mode 100644 index f4da4d8372..0000000000 --- a/Lab1C/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -add_executable(Lab1C lab1.c) -target_include_directories(Lab1C PUBLIC ../LibraryC) -target_link_libraries(Lab1C LibraryC) - -add_test(NAME TestLab1C COMMAND Lab1C ${CMAKE_CURRENT_SOURCE_DIR}/input.txt) -set_property(TEST TestLab1C PROPERTY PASS_REGULAR_EXPRESSION "1 2 3 4 5") diff --git a/Lab1C/lab1.c b/Lab1C/lab1.c deleted file mode 100644 index fdf6ed1527..0000000000 --- a/Lab1C/lab1.c +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include "array.h" - -Array *array_create_and_read(FILE *input) -{ - int n; - fscanf(input, "%d", &n); - /* Create array */ - Array *arr = array_create(n, NULL); - /* Read array data */ - for (int i = 0 ; i < n ; ++i) - { - int x; - fscanf(input, "%d", &x); - array_set(arr, i, x); - } - return arr; -} - -void task1(Array *arr) -{ -} - -void task2(Array *arr) -{ -} - -int main(int argc, char **argv) -{ - Array *arr = NULL; - FILE *input = fopen(argv[1], "r"); - arr = array_create_and_read(input); - task1(arr); - array_delete(arr); - /* Create another array here */ - arr = array_create_and_read(input); - task2(arr); - array_delete(arr); - fclose(input); -} diff --git a/Lab1CPP/CMakeLists.txt b/Lab1CPP/CMakeLists.txt new file mode 100644 index 0000000000..d08b8d6b6c --- /dev/null +++ b/Lab1CPP/CMakeLists.txt @@ -0,0 +1,8 @@ +add_executable(Lab1CPP main.cpp) +target_include_directories (Lab1CPP PUBLIC ../LibraryCPPClass) +target_link_libraries(Lab1CPP LibraryCPPClass) + +add_test(NAME Test_1 COMMAND Lab1CPP ${CMAKE_CURRENT_SOURCE_DIR}/input.txt) +set_tests_properties(Test_1 PROPERTIES PASS_REGULAR_EXPRESSION "0 1 2 3 4 5 6 7 8 9.*1 2 3 4") +add_test(NAME Test_2 COMMAND Lab1CPP ${CMAKE_CURRENT_SOURCE_DIR}/input2.txt) +set_tests_properties(Test_2 PROPERTIES PASS_REGULAR_EXPRESSION "22 33 44 88.*3 4") \ No newline at end of file diff --git a/Lab1C/input.txt b/Lab1CPP/input.txt similarity index 100% rename from Lab1C/input.txt rename to Lab1CPP/input.txt diff --git a/Lab1CPP/input2.txt b/Lab1CPP/input2.txt new file mode 100644 index 0000000000..9a3a344518 --- /dev/null +++ b/Lab1CPP/input2.txt @@ -0,0 +1,4 @@ +6 +22 13 33 44 90 88 +6 +11 2 3 4 11 2 \ No newline at end of file diff --git a/Lab1CPP/main.cpp b/Lab1CPP/main.cpp new file mode 100644 index 0000000000..c0c54dfe9d --- /dev/null +++ b/Lab1CPP/main.cpp @@ -0,0 +1,88 @@ +#include "array.h" +#include +#include + +using namespace std; + +bool is_palindrome(int n) { + if (n < 10) return true; + int start = n; + int reversed = 0; + while (n > 0) { + reversed = reversed * 10 + n % 10; + n /= 10; + } + return start == reversed; +} + +int main(int argc, char* argv[]) { + if (argc < 2) { + cout << "Error: File not specified" << endl; + return 1; + } + + std::ifstream file(argv[1]); + + if (!file.is_open()) { + cout << "Error: Cannot open file " << argv[1] << endl; + return 1; + } + + int size1; + file >> size1; + + Array arr1(size1); + size_t num = 0; + for (int i = 0; i < size1; i++) { + int temp; + file >> temp; + if (is_palindrome(temp)) { + arr1.set(num, temp); + num++; + } + } + + for (size_t i = 0; i < num; i++) { + for (size_t j = 0; j < num - i - 1; j++) { + if (arr1.get(j) > arr1.get(j + 1)) { + int a = arr1.get(j); + int b = arr1.get(j + 1); + swap(a, b); + arr1.set(j, a); + arr1.set(j + 1, b); + } + } + } + + for (size_t i = 0; i < num; i++) { + cout << arr1.get(i) << " "; + } + cout << endl; + + int size2; + file >> size2; + + Array arr2(size2); + for (size_t i = 0; i < arr2.size(); i++) { + int val; + file >> val; + arr2.set(i, val); + } + + + for (size_t i = 0; i < arr2.size(); i++) { + int count = 0; + for (size_t j = 0; j < arr2.size(); j++) { + if (arr2.get(i) == arr2.get(j)) count++; + } + if (count == 1) { + cout << arr2.get(i) << " "; + } + } + + file.close(); + + return 0; +} + + diff --git a/Lab2CPP/CMakeLists.txt b/Lab2CPP/CMakeLists.txt new file mode 100644 index 0000000000..00c303e0f1 --- /dev/null +++ b/Lab2CPP/CMakeLists.txt @@ -0,0 +1,14 @@ +add_executable(Lab2CPP main.cpp) +target_include_directories (Lab2CPP PUBLIC ../LibraryCPPClass) +target_link_libraries(Lab2CPP LibraryCPPClass) + +add_test(NAME Test_1 COMMAND Lab2CPP ${CMAKE_CURRENT_SOURCE_DIR}/input1_2.txt) +set_tests_properties(Test_1 PROPERTIES PASS_REGULAR_EXPRESSION "PUSH 1.*PUSH 2.*PUSH 3.*POP A.*POP B.*MUL A, B.*PUSH A.*POP A.*POP B.*ADD A, B.*PUSH A") +add_test(NAME Test_2 COMMAND Lab2CPP ${CMAKE_CURRENT_SOURCE_DIR}/input2_2.txt) +set_tests_properties(Test_2 PROPERTIES PASS_REGULAR_EXPRESSION "PUSH 1.*PUSH 2.*POP A.*POP B.*ADD A, B.*PUSH A.*PUSH 3.*POP A.*POP B.*MUL A, B.*PUSH A") +add_test(NAME Test_3 COMMAND Lab2CPP ${CMAKE_CURRENT_SOURCE_DIR}/input3_2.txt) +set_tests_properties(Test_3 PROPERTIES PASS_REGULAR_EXPRESSION "PUSH 2.*PUSH 3.*POP A.*POP B.*MUL A, B.*PUSH A.*PUSH 4.*PUSH 5.*POP A.*POP B.*MUL A, B.*PUSH A.*POP A.*POP B.*ADD A, B.*PUSH A") +add_test(NAME Test_4 COMMAND Lab2CPP ${CMAKE_CURRENT_SOURCE_DIR}/input4_2.txt) +set_tests_properties(Test_4 PROPERTIES PASS_REGULAR_EXPRESSION "PUSH 5.*PUSH 3.*POP A.*POP B.*ADD A, B.*PUSH A.*PUSH 2.*PUSH 1.*POP A.*POP B.*ADD A, B.*PUSH A.*POP A.*POP B.*MUL A, B.*PUSH A") +add_test(NAME Test_5 COMMAND Lab2CPP ${CMAKE_CURRENT_SOURCE_DIR}/input5_2.txt) +set_tests_properties(Test_5 PROPERTIES PASS_REGULAR_EXPRESSION "PUSH 5.*PUSH 3.*POP A.*POP B.*SUB A, B.*PUSH A.*PUSH 2.*POP A.*POP B.*MUL A, B.*PUSH A.*PUSH 1.*POP A.*POP B.*ADD A, B.*PUSH A") \ No newline at end of file diff --git a/Lab2CPP/input1_2.txt b/Lab2CPP/input1_2.txt new file mode 100644 index 0000000000..9026c72a24 --- /dev/null +++ b/Lab2CPP/input1_2.txt @@ -0,0 +1 @@ +1+2*3 \ No newline at end of file diff --git a/Lab2CPP/input2_2.txt b/Lab2CPP/input2_2.txt new file mode 100644 index 0000000000..255e0a0272 --- /dev/null +++ b/Lab2CPP/input2_2.txt @@ -0,0 +1 @@ +(1+2)*3 \ No newline at end of file diff --git a/Lab2CPP/input3_2.txt b/Lab2CPP/input3_2.txt new file mode 100644 index 0000000000..46c2018115 --- /dev/null +++ b/Lab2CPP/input3_2.txt @@ -0,0 +1 @@ +2*3+4*5 \ No newline at end of file diff --git a/Lab2CPP/input4_2.txt b/Lab2CPP/input4_2.txt new file mode 100644 index 0000000000..a3e229d924 --- /dev/null +++ b/Lab2CPP/input4_2.txt @@ -0,0 +1 @@ +(5+3)*(2+1) \ No newline at end of file diff --git a/Lab2CPP/input5_2.txt b/Lab2CPP/input5_2.txt new file mode 100644 index 0000000000..15b1efc2d3 --- /dev/null +++ b/Lab2CPP/input5_2.txt @@ -0,0 +1 @@ +(5-3)*2+1 \ No newline at end of file diff --git a/Lab2CPP/main.cpp b/Lab2CPP/main.cpp new file mode 100644 index 0000000000..d96b35e5f9 --- /dev/null +++ b/Lab2CPP/main.cpp @@ -0,0 +1,127 @@ +#include +#include +#include +#include +#include +#include +#include "stack.h" + +using namespace std; + +typedef vector str_vector; + +int priority(char op) { + if (op == '*') return 2; + return 1; +} + +str_vector convertToAssembly(const string& expression) { + str_vector assembly; + Stack ops; + string number; + + for (size_t i = 0; i < expression.length(); ++i) { + char c = expression[i]; + + if (isdigit(c)) { + number += c; + } + else { + if (!number.empty()) { + assembly.push_back("PUSH " + number); + number.clear(); + } + + if (c == '(') { + ops.push('('); + } + else if (c == ')') { + while (!ops.empty() && (char)ops.get() != '(') { + char op = (char)ops.get(); + ops.pop(); + + assembly.push_back("POP A"); + assembly.push_back("POP B"); + if (op == '+') { + assembly.push_back("ADD A, B"); + } + else if (op == '-') { + assembly.push_back("SUB A, B"); + } + else { + assembly.push_back("MUL A, B"); + } + assembly.push_back("PUSH A"); + } + if (!ops.empty()) ops.pop(); + } + else if (c == '+' || c == '-' || c == '*') { + while (!ops.empty() && (char)ops.get() != '(' && + priority((char)ops.get()) >= priority(c)) { + char op = (char)ops.get(); + ops.pop(); + + assembly.push_back("POP A"); + assembly.push_back("POP B"); + if (op == '+') { + assembly.push_back("ADD A, B"); + } + else if (op == '-') { + assembly.push_back("SUB A, B"); + } + else { + assembly.push_back("MUL A, B"); + } + assembly.push_back("PUSH A"); + } + ops.push(c); + } + } + } + + if (!number.empty()) { + assembly.push_back("PUSH " + number); + } + + while (!ops.empty()) { + char op = (char)ops.get(); + ops.pop(); + + assembly.push_back("POP A"); + assembly.push_back("POP B"); + if (op == '+') { + assembly.push_back("ADD A, B"); + } + else if (op == '-') { + assembly.push_back("SUB A, B"); + } + else { + assembly.push_back("MUL A, B"); + } + assembly.push_back("PUSH A"); + } + + return assembly; +} + +int main(int argc, char* argv[]) { + try { + if (argc != 2) return 1; + + ifstream input(argv[1]); + if (!input.is_open()) return 1; + + string expression; + getline(input, expression); + + str_vector result = convertToAssembly(expression); + for (size_t i = 0; i < result.size(); ++i) { + cout << result[i] << endl; + } + } + catch (...) { + return 1; + } + + return 0; +} \ No newline at end of file diff --git a/Lab3CPP/CMakeLists.txt b/Lab3CPP/CMakeLists.txt new file mode 100644 index 0000000000..67cb0d968c --- /dev/null +++ b/Lab3CPP/CMakeLists.txt @@ -0,0 +1,14 @@ +add_executable(Lab3CPP main.cpp) +target_include_directories (Lab3CPP PUBLIC ../LibraryCPP) +target_link_libraries(Lab3CPP LibraryCPP) + +add_test(NAME Test_1 COMMAND Lab3CPP ${CMAKE_CURRENT_SOURCE_DIR}/input1_3.txt) +set_tests_properties(Test_1 PROPERTIES PASS_REGULAR_EXPRESSION "######.*#xxxX#.*#x####.*#xxxY#.*######") +add_test(NAME Test_2 COMMAND Lab3CPP ${CMAKE_CURRENT_SOURCE_DIR}/input2_3.txt) +set_tests_properties(Test_2 PROPERTIES PASS_REGULAR_EXPRESSION "IMPOSSIBLE") +add_test(NAME Test_3 COMMAND Lab3CPP ${CMAKE_CURRENT_SOURCE_DIR}/input3_3.txt) +set_tests_properties(Test_3 PROPERTIES PASS_REGULAR_EXPRESSION "######.*#Yxxx#.*####x#.*#Xxxx#.*######") +add_test(NAME Test_4 COMMAND Lab3CPP ${CMAKE_CURRENT_SOURCE_DIR}/input4_3.txt) +set_tests_properties(Test_4 PROPERTIES PASS_REGULAR_EXPRESSION "#######.*#Yxx#.#.*#.#x#.#.*#..x.##.*###x#.#.*#Xxx..#.*#######") +add_test(NAME Test_5 COMMAND Lab3CPP ${CMAKE_CURRENT_SOURCE_DIR}/input5_3.txt) +set_tests_properties(Test_5 PROPERTIES PASS_REGULAR_EXPRESSION "IMPOSSIBLE") \ No newline at end of file diff --git a/Lab3CPP/input1_3.txt b/Lab3CPP/input1_3.txt new file mode 100644 index 0000000000..89de12c809 --- /dev/null +++ b/Lab3CPP/input1_3.txt @@ -0,0 +1,5 @@ +###### +#...X# +#.#### +#...Y# +###### \ No newline at end of file diff --git a/Lab3CPP/input2_3.txt b/Lab3CPP/input2_3.txt new file mode 100644 index 0000000000..66ecea7e54 --- /dev/null +++ b/Lab3CPP/input2_3.txt @@ -0,0 +1,5 @@ +###### +#...X# +###### +#...Y# +###### \ No newline at end of file diff --git a/Lab3CPP/input3_3.txt b/Lab3CPP/input3_3.txt new file mode 100644 index 0000000000..13bc788608 --- /dev/null +++ b/Lab3CPP/input3_3.txt @@ -0,0 +1,5 @@ +###### +#Y...# +####.# +#X...# +###### \ No newline at end of file diff --git a/Lab3CPP/input4_3.txt b/Lab3CPP/input4_3.txt new file mode 100644 index 0000000000..4654646526 --- /dev/null +++ b/Lab3CPP/input4_3.txt @@ -0,0 +1,7 @@ +####### +#Y..#.# +#.#.#.# +#....## +###.#.# +#X....# +####### \ No newline at end of file diff --git a/Lab3CPP/input5_3.txt b/Lab3CPP/input5_3.txt new file mode 100644 index 0000000000..066914cbef --- /dev/null +++ b/Lab3CPP/input5_3.txt @@ -0,0 +1,7 @@ +####### +#Y.##.# +###.#.# +##...## +###.#.# +#X....# +####### \ No newline at end of file diff --git a/Lab3CPP/main.cpp b/Lab3CPP/main.cpp new file mode 100644 index 0000000000..56366ec772 --- /dev/null +++ b/Lab3CPP/main.cpp @@ -0,0 +1,132 @@ +#include +#include +#include +#include +#include "queue.h" + +using namespace std; + +struct Point { + int x, y; + Point(int x = 0, int y = 0) : x(x), y(y) {} +}; + +bool isValid(int x, int y, int rows, int cols) { + return x >= 0 && x < rows && y >= 0 && y < cols; +} + +int encode(int x, int y, int cols) { + return x * cols + y; +} + +void decode(int code, int cols, int& x, int& y) { + x = code / cols; + y = code % cols; +} + +int main(int argc, char* argv[]) { + if (argc < 2) { + cout << "Error: File not specified" << endl; + return 1; + } + + ifstream file(argv[1]); + if (!file.is_open()) { + cout << "Error: Cannot open file " << argv[1] << endl; + return 1; + } + + vector maze; + string line; + while (getline(file, line)) { + maze.push_back(line); + } + file.close(); + + if (maze.empty()) { + cout << "IMPOSSIBLE" << endl; + return 0; + } + + size_t rows = maze.size(); + size_t cols = maze[0].size(); + + Point start(-1, -1), end(-1, -1); + for (size_t i = 0; i < rows; ++i) { + for (size_t j = 0; j < cols; ++j) { + if (maze[i][j] == 'X') { + start = Point((int)i, (int)j); + } + else if (maze[i][j] == 'Y') { + end = Point((int)i, (int)j); + } + } + } + + if (start.x == -1 || end.x == -1) { + cout << "IMPOSSIBLE" << endl; + return 0; + } + + vector> previous(rows, vector(cols, Point(-1, -1))); + + int dx[] = { -1, 0, 1, 0 }; + int dy[] = { 0, 1, 0, -1 }; + + Queue* queue = queue_create(); + + previous[start.x][start.y] = Point(start.x, start.y); + queue_insert(queue, encode(start.x, start.y, (int)cols)); + + bool found = false; + + while (!queue_empty(queue)) { + int current_code = queue_get(queue); + queue_remove(queue); + + int x, y; + decode(current_code, (int)cols, x, y); + + if (x == end.x && y == end.y) { + found = true; + break; + } + + for (int i = 0; i < 4; ++i) { + int nextX = x + dx[i]; + int nextY = y + dy[i]; + + if (isValid(nextX, nextY, (int)rows, (int)cols) && + maze[nextX][nextY] != '#' && + previous[nextX][nextY].x == -1) { + + previous[nextX][nextY] = Point(x, y); + queue_insert(queue, encode(nextX, nextY, (int)cols)); + } + } + } + + queue_delete(queue); + + if (!found) { + cout << "IMPOSSIBLE" << endl; + return 0; + } + + vector result = maze; + Point current = end; + + while (!(current.x == start.x && current.y == start.y)) { + if (!(current.x == end.x && current.y == end.y) && + !(current.x == start.x && current.y == start.y)) { + result[current.x][current.y] = 'x'; + } + current = previous[current.x][current.y]; + } + + for (size_t i = 0; i < rows; ++i) { + cout << result[i] << endl; + } + + return 0; +} \ No newline at end of file diff --git a/Lab4CPP/CMakeLists.txt b/Lab4CPP/CMakeLists.txt new file mode 100644 index 0000000000..e6edbff994 --- /dev/null +++ b/Lab4CPP/CMakeLists.txt @@ -0,0 +1,7 @@ +add_executable(Lab4CPP main.cpp) +target_include_directories (Lab4CPP PUBLIC ../LibraryCPPTemplate) + +add_test(NAME Test_1 COMMAND Lab4CPP ${CMAKE_CURRENT_SOURCE_DIR}/input1_4.txt) +set_tests_properties(Test_1 PROPERTIES PASS_REGULAR_EXPRESSION "11.*A B D E") +add_test(NAME Test_2 COMMAND Lab4CPP ${CMAKE_CURRENT_SOURCE_DIR}/input2_4.txt) +set_tests_properties(Test_2 PROPERTIES PASS_REGULAR_EXPRESSION "No path") \ No newline at end of file diff --git a/Lab4CPP/input1_4.txt b/Lab4CPP/input1_4.txt new file mode 100644 index 0000000000..53e14ff580 --- /dev/null +++ b/Lab4CPP/input1_4.txt @@ -0,0 +1,10 @@ +5 7 +A B C D E +A B 4 +A C 2 +B C 1 +B D 5 +C D 8 +C E 10 +D E 2 +A E \ No newline at end of file diff --git a/Lab4CPP/input2_4.txt b/Lab4CPP/input2_4.txt new file mode 100644 index 0000000000..e8621f6cdb --- /dev/null +++ b/Lab4CPP/input2_4.txt @@ -0,0 +1,5 @@ +4 2 +X Y Z W +X Y 5 +Z W 3 +X W \ No newline at end of file diff --git a/Lab4CPP/main.cpp b/Lab4CPP/main.cpp new file mode 100644 index 0000000000..4764f28e6d --- /dev/null +++ b/Lab4CPP/main.cpp @@ -0,0 +1,215 @@ +#include "graph.h" +#include +#include +#include + +using namespace std; + +struct HeapItem { + int vertex; + int distance; +}; + +struct PriorityQueue { + Vector heap; +}; + +PriorityQueue* pq_create() { + PriorityQueue* pq = new PriorityQueue; + return pq; +} + +void pq_push(PriorityQueue* pq, int vertex, int distance) { + HeapItem item; + item.vertex = vertex; + item.distance = distance; + + pq->heap.resize(pq->heap.size() + 1); + size_t index = pq->heap.size() - 1; + pq->heap.set(index, item); + + while (index > 0) { + size_t parent = (index - 1) / 2; + if (pq->heap.get(parent).distance > pq->heap.get(index).distance) { + HeapItem temp = pq->heap.get(parent); + pq->heap.set(parent, pq->heap.get(index)); + pq->heap.set(index, temp); + index = parent; + } + else { + break; + } + } +} + +int pq_pop(PriorityQueue* pq) { + if (pq->heap.size() == 0) { + return -1; + } + int vertex = pq->heap.get(0).vertex; + + if (pq->heap.size() > 1) { + pq->heap.set(0, pq->heap.get(pq->heap.size() - 1)); + pq->heap.resize(pq->heap.size() - 1); + + size_t index = 0; + size_t heap_size = pq->heap.size(); + while (true) { + size_t left = 2 * index + 1; + size_t right = 2 * index + 2; + size_t smallest = index; + + if (left < heap_size && pq->heap.get(left).distance < pq->heap.get(smallest).distance) { + smallest = left; + } + if (right < heap_size && pq->heap.get(right).distance < pq->heap.get(smallest).distance) { + smallest = right; + } + + if (smallest != index) { + HeapItem temp = pq->heap.get(index); + pq->heap.set(index, pq->heap.get(smallest)); + pq->heap.set(smallest, temp); + index = smallest; + } + else { + break; + } + } + } + else { + pq->heap.resize(0); + } + return vertex; +} + +bool pq_empty(PriorityQueue* pq) { + return pq->heap.size() == 0; +} + +void pq_delete(PriorityQueue* pq) { + delete pq; +} + +size_t find_index(const string* names, size_t n, const string& name) +{ + for (size_t i = 0; i < n; ++i) + { + if (names[i] == name) + return i; + } + return static_cast(-1); +} + +int main(int argc, char* argv[]) { + if (argc < 2) { + cout << "Usage: " << argv[0] << " \n"; + return 1; + } + + ifstream input(argv[1]); + if (!input) { + cout << "Cannot open file\n"; + return 1; + } + + size_t vertex_count, edge_count; + input >> vertex_count >> edge_count; + + Graph graph(vertex_count); + string* vertex_names = new string[vertex_count]; + + for (size_t i = 0; i < vertex_count; ++i) { + input >> vertex_names[i]; + graph.set_vertex_label(i, vertex_names[i]); + } + + for (size_t i = 0; i < edge_count; ++i) { + string from_name, to_name; + int weight; + input >> from_name >> to_name >> weight; + + size_t from_idx = find_index(vertex_names, vertex_count, from_name); + size_t to_idx = find_index(vertex_names, vertex_count, to_name); + + if (from_idx != static_cast(-1) && to_idx != static_cast(-1)) { + graph.add_edge(from_idx, to_idx, weight); + } + } + + string start_name, end_name; + input >> start_name >> end_name; + + size_t start_idx = find_index(vertex_names, vertex_count, start_name); + size_t end_idx = find_index(vertex_names, vertex_count, end_name); + + if (start_idx == static_cast(-1) || end_idx == static_cast(-1)) { + cout << "Start or end vertex not found\n"; + delete[] vertex_names; + return 1; + } + + const int MAX_DIST = 1000000000; + int* distances = new int[vertex_count]; + int* prev_vertex = new int[vertex_count]; + + for (size_t i = 0; i < vertex_count; ++i) { + distances[i] = MAX_DIST; + prev_vertex[i] = -1; + } + distances[start_idx] = 0; + + PriorityQueue* pq = pq_create(); + pq_push(pq, static_cast(start_idx), distances[start_idx]); + + while (!pq_empty(pq)) { + int current = pq_pop(pq); + + auto it = graph.neighbors(static_cast(current)); + while (it.valid()) { + size_t neighbor = it.vertex_id(); + int edge_weight = it.edge_label(); + + if (distances[current] + edge_weight < distances[neighbor]) { + distances[neighbor] = distances[current] + edge_weight; + prev_vertex[neighbor] = current; + pq_push(pq, static_cast(neighbor), distances[neighbor]); + } + + it.next(); + } + } + + if (distances[end_idx] == MAX_DIST) { + cout << "No path\n"; + } + else { + cout << distances[end_idx] << "\n"; + + size_t* path = new size_t[vertex_count]; + size_t path_len = 0; + + size_t current = end_idx; + while (true) { + path[path_len++] = current; + if (current == start_idx) break; + current = static_cast(prev_vertex[current]); + } + + for (size_t i = path_len; i > 0; --i) { + cout << vertex_names[path[i - 1]]; + if (i > 1) + cout << " "; + } + cout << "\n"; + + delete[] path; + } + + pq_delete(pq); + delete[] distances; + delete[] prev_vertex; + delete[] vertex_names; + + return 0; +} \ No newline at end of file diff --git a/Lab5CPP/CMakeLists.txt b/Lab5CPP/CMakeLists.txt new file mode 100644 index 0000000000..8072d3c2ea --- /dev/null +++ b/Lab5CPP/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(Lab5CPP main.cpp) +target_include_directories (Lab5CPP PUBLIC ../LibraryCPPClass) +target_link_libraries(Lab5CPP LibraryCPPClass) + +add_test(NAME Test_1 COMMAND Lab5CPP ${CMAKE_CURRENT_SOURCE_DIR}/input1_5.txt) +set_tests_properties(Test_1 PROPERTIES PASS_REGULAR_EXPRESSION "loaded: 10") \ No newline at end of file diff --git a/Lab5CPP/graphic_5lab.png b/Lab5CPP/graphic_5lab.png new file mode 100644 index 0000000000..06df7e1632 Binary files /dev/null and b/Lab5CPP/graphic_5lab.png differ diff --git a/Lab5CPP/input1_5.txt b/Lab5CPP/input1_5.txt new file mode 100644 index 0000000000..86ee4ed864 --- /dev/null +++ b/Lab5CPP/input1_5.txt @@ -0,0 +1,10 @@ +brand mercedes +model gt63s +country germany +year 2019 +colour grey +transmission auto +drive awd +hp 639 +price 13500000 +range 700 \ No newline at end of file diff --git a/Lab5CPP/main.cpp b/Lab5CPP/main.cpp new file mode 100644 index 0000000000..05e8c32505 --- /dev/null +++ b/Lab5CPP/main.cpp @@ -0,0 +1,159 @@ +#include "RBTree.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +vector> generate_data(int count) { + vector> data; + random_device random_device; + mt19937 random_generator(random_device()); + + for (int i = 0; i < count; i++) { + string key = "user" + to_string(random_generator() % 1000000); + string value = "email" + to_string(i) + "@test.com"; + data.push_back(make_pair(key, value)); + } + return data; +} + +void test() { + RBTree tree; + string value; + + tree.insert("name", "alice"); + tree.insert("age", "25"); + tree.insert("city", "london"); + + if (tree.find("name", value) && value == "alice") cout << "test_get ok" << endl; + + tree.remove("age"); + if (!tree.find("age", value)) cout << "test_remove ok" << endl; + + if (tree.size() == 2) cout << "test_size ok" << endl; +} + +void speed() { + int sizes[] = { 1000, 5000, 10000, 50000, 100000, 250000, 500000, 750000, 1000000 }; + int sizes_count = 9; + + cout << "\nspeed test:" << endl; + cout << "size time" << endl; + + for (int i = 0; i < sizes_count; i++) { + int size = sizes[i]; + vector> data = generate_data(size); + + chrono::high_resolution_clock::time_point start = chrono::high_resolution_clock::now(); + RBTree tree; + for (size_t j = 0; j < data.size(); j++) { + tree.insert(data[j].first, data[j].second); + } + chrono::high_resolution_clock::time_point end = chrono::high_resolution_clock::now(); + long long elapsed_time = chrono::duration_cast(end - start).count(); + + cout << size << " " << elapsed_time << endl; + } +} + +void mapvsrbtree() { + int sizes[] = { 1000, 5000, 10000, 50000, 100000, 250000, 500000, 750000, 1000000 }; + int sizes_count = 9; + + ofstream csv_file("сравнение.csv"); + + cout << "\ncomparison with map:" << endl; + cout << "size rbtree map" << endl; + + csv_file << "size,rbtree,std::map" << endl; + + for (int i = 0; i < sizes_count; i++) { + int size = sizes[i]; + vector> data = generate_data(size); + + chrono::high_resolution_clock::time_point start_rb = chrono::high_resolution_clock::now(); + RBTree tree; + for (size_t j = 0; j < data.size(); j++) { + tree.insert(data[j].first, data[j].second); + } + chrono::high_resolution_clock::time_point end_rb = chrono::high_resolution_clock::now(); + long long time_rb = chrono::duration_cast(end_rb - start_rb).count(); + + chrono::high_resolution_clock::time_point start_map = chrono::high_resolution_clock::now(); + map std_map; + for (size_t j = 0; j < data.size(); j++) { + std_map[data[j].first] = data[j].second; + } + chrono::high_resolution_clock::time_point end_map = chrono::high_resolution_clock::now(); + long long time_map = chrono::duration_cast(end_map - start_map).count(); + + cout << size << " " << time_rb << " " << time_map << endl; + csv_file << size << "," << time_rb << "," << time_map << endl; + } + csv_file.close(); +} + +void stress() { + int sizes[] = { 1000, 2000, 4000, 8000, 16000, 32000 }; + int sizes_count = 6; + + cout << "\nstress test:" << endl; + cout << "size time" << endl; + + for (int i = 0; i < sizes_count; i++) { + int size = sizes[i]; + vector> data = generate_data(size); + + chrono::high_resolution_clock::time_point start = chrono::high_resolution_clock::now(); + RBTree tree; + for (size_t j = 0; j < data.size(); j++) { + tree.insert(data[j].first, data[j].second); + } + chrono::high_resolution_clock::time_point end = chrono::high_resolution_clock::now(); + long long elapsed_time = chrono::duration_cast(end - start).count(); + + cout << size << " " << elapsed_time << endl; + } +} + +int main(int argc, char* argv[]) { + if (argc < 2) { + cout << "Error: File not specified" << endl; + cout << "Usage: " << argv[0] << " " << endl; + return 1; + } + + ifstream input_file(argv[1]); + if (!input_file.is_open()) { + cout << "Error: Cannot open file " << argv[1] << endl; + return 1; + } + + test(); + speed(); + mapvsrbtree(); + stress(); + + RBTree tree; + string line; + int count = 0; + + while (getline(input_file, line)) { + istringstream line_stream(line); + string key, value; + if (line_stream >> key >> value) { + tree.insert(key, value); + count++; + } + } + + cout << "loaded: " << count << endl; + cout << "tree_size: " << tree.size() << endl; + + return 0; +} \ No newline at end of file diff --git a/LibraryCPP/CMakeLists.txt b/LibraryCPP/CMakeLists.txt index dbd7769feb..bfeec79b5a 100644 --- a/LibraryCPP/CMakeLists.txt +++ b/LibraryCPP/CMakeLists.txt @@ -1,3 +1,3 @@ -add_library(LibraryCPP STATIC array.cpp list.cpp queue.cpp stack.cpp vector.cpp) +add_library(LibraryCPP STATIC list.cpp queue.cpp) add_subdirectory(Tests) diff --git a/LibraryCPP/Tests/CMakeLists.txt b/LibraryCPP/Tests/CMakeLists.txt index c903f9d7f3..5bc5febd47 100644 --- a/LibraryCPP/Tests/CMakeLists.txt +++ b/LibraryCPP/Tests/CMakeLists.txt @@ -3,16 +3,16 @@ # target_link_libraries(TestArrayCPP LibraryCPP) # add_test(TestArrayCPP TestArrayCPP) -# add_executable(TestListCPP list.cpp) -# target_include_directories(TestListCPP PUBLIC ..) -# target_link_libraries(TestListCPP LibraryCPP) -# add_test(TestListCPP TestListCPP) +add_executable(TestListCPP list.cpp) +target_include_directories(TestListCPP PUBLIC ..) +target_link_libraries(TestListCPP LibraryCPP) +add_test(TestListCPP TestListCPP) -# add_executable(TestQueueCPP queue.cpp) -# target_include_directories(TestQueueCPP PUBLIC ..) -# target_link_libraries(TestQueueCPP LibraryCPP) -# add_test(TestQueueCPP TestQueueCPP) -# set_tests_properties(TestQueueCPP PROPERTIES TIMEOUT 10) +add_executable(TestQueueCPP queue.cpp) +target_include_directories(TestQueueCPP PUBLIC ..) +target_link_libraries(TestQueueCPP LibraryCPP) +add_test(TestQueueCPP TestQueueCPP) +set_tests_properties(TestQueueCPP PROPERTIES TIMEOUT 10) # add_executable(TestStackCPP stack.cpp) # target_include_directories(TestStackCPP PUBLIC ..) diff --git a/LibraryCPP/Tests/list.cpp b/LibraryCPP/Tests/list.cpp index 26862d4820..4db043d3b6 100644 --- a/LibraryCPP/Tests/list.cpp +++ b/LibraryCPP/Tests/list.cpp @@ -38,9 +38,12 @@ int main() } std::cout << "List: "; - for (ListItem *item = list_first(list) ; item ; item = list_item_next(item)) + for (ListItem *item = list_first(list) , *first = item ; item; item = list_item_next(item)) { std::cout << list_item_data(item) << " "; + if (item == first) { + break; + } } std::cout << "\n"; diff --git a/LibraryCPP/list.cpp b/LibraryCPP/list.cpp index a8946b5793..0cf4aa72d1 100644 --- a/LibraryCPP/list.cpp +++ b/LibraryCPP/list.cpp @@ -3,59 +3,175 @@ struct ListItem { + Data data; + ListItem* next; + ListItem* prev; }; struct List { + ListItem* head; }; List *list_create() { - return new List; + List* list = new List; + list->head = nullptr; + return list; } void list_delete(List *list) { + if (!list) { + return; + } + if (list->head != nullptr) { + ListItem* last = list->head->prev; + last->next = nullptr; + + ListItem* current = list->head; + while (current != nullptr) { + ListItem* next = current->next; + delete current; + current = next; + } + } // TODO: free items delete list; } ListItem *list_first(List *list) { - return NULL; + if (list == nullptr) { + return nullptr; + } + return list->head; } Data list_item_data(const ListItem *item) { - return (Data)0; + if (item == nullptr) { + return 0; + } + return item->data; } ListItem *list_item_next(ListItem *item) { - return NULL; + if(item == nullptr) { + return nullptr; + } + return item->next; } ListItem *list_item_prev(ListItem *item) { - return NULL; + if (item == nullptr) { + return nullptr; + } + return item->prev; } ListItem *list_insert(List *list, Data data) { - return NULL; + if (list == nullptr) { + return nullptr; + } + + ListItem* item = new ListItem; + item->data = data; + + if (list->head == nullptr) { + item->next = item; + item->prev = item; + list->head = item; + } + else { + ListItem* first = list->head; + ListItem* last = first->prev; + + item->next = first; + item->prev = last; + + first->prev = item; + last->next = item; + + list->head = item; + } + return item; } ListItem *list_insert_after(List *list, ListItem *item, Data data) { - return NULL; + if (list == nullptr) { + return nullptr; + } + + if (item == nullptr) { + return list_insert(list, data); + } + + ListItem* new_item = new ListItem; + new_item->data = data; + + ListItem* next = item->next; + new_item->next = next; + new_item->prev = item; + + item->next = new_item; + next->prev = new_item; + + return new_item; } ListItem *list_erase_first(List *list) { - return NULL; + if (list == nullptr || !list->head) { + return nullptr; + } + + ListItem* next = list->head->next; + ListItem* prev = list->head->prev; + ListItem* to_delete = list->head; + + if (next == to_delete) { + list->head = nullptr; + } + else { + list->head = next; + next->prev = prev; + prev->next = next; + } + + delete to_delete; + return list->head; + } ListItem *list_erase_next(List *list, ListItem *item) { - return NULL; + if (list == nullptr) { + return nullptr; + } + + if (item == nullptr) { + return list_erase_first(list); + } + + ListItem* to_delete = item->next; + if (to_delete == nullptr || to_delete == item) { + return nullptr; + } + + ListItem* next = to_delete->next; + + item->next = next; + next->prev = item; + + if (to_delete == list->head) { + list->head = next; + } + + delete to_delete; + return next; } diff --git a/LibraryCPP/queue.cpp b/LibraryCPP/queue.cpp index a9b4730488..72b5811692 100644 --- a/LibraryCPP/queue.cpp +++ b/LibraryCPP/queue.cpp @@ -1,34 +1,54 @@ #include "queue.h" +#include "list.h" struct Queue { + List* list; }; Queue *queue_create() { - return new Queue; + Queue* queue = new Queue; + queue->list = list_create(); + return queue; } void queue_delete(Queue *queue) { + list_delete(queue->list); // TODO: free queue items delete queue; } void queue_insert(Queue *queue, Data data) { + if (queue_empty(queue)) { + list_insert(queue->list, data); + } + else { + ListItem* first = list_first(queue->list); + ListItem* last = list_item_prev(first); + list_insert_after(queue->list, last, data); + } } Data queue_get(const Queue *queue) { - return (Data)0; + if (queue_empty(queue)) { + return 0; + } + ListItem* first = list_first(queue->list); + return list_item_data(first); } void queue_remove(Queue *queue) { + if (!queue_empty(queue)) { + list_erase_first(queue->list); + } } bool queue_empty(const Queue *queue) { - return true; + return list_first(queue->list) == nullptr; } diff --git a/LibraryCPPClass/CMakeLists.txt b/LibraryCPPClass/CMakeLists.txt index 0ddd51cba2..2c331b3c83 100644 --- a/LibraryCPPClass/CMakeLists.txt +++ b/LibraryCPPClass/CMakeLists.txt @@ -1,3 +1,2 @@ -add_library(LibraryCPPClass STATIC array.cpp list.cpp queue.cpp stack.cpp vector.cpp) - +add_library(LibraryCPPClass STATIC RBTree.cpp) add_subdirectory(Tests) diff --git a/LibraryCPPClass/RBTree.cpp b/LibraryCPPClass/RBTree.cpp new file mode 100644 index 0000000000..e03cc547c6 --- /dev/null +++ b/LibraryCPPClass/RBTree.cpp @@ -0,0 +1,324 @@ +#include "RBTree.h" +#include + +RBTree::Node::Node(const string& k, const string& v) + : key(k), value(v), red(true), left(0), right(0), parent(0) {} + +RBTree::RBTree() : root(0), treeSize(0) {} + +RBTree::~RBTree() { + clear(root); +} + +void RBTree::clear(Node* n) { + if (n) { + clear(n->left); + clear(n->right); + delete n; + } +} + +void RBTree::leftRotate(Node* x) { + Node* y = x->right; + x->right = y->left; + + if (y->left) + y->left->parent = x; + + y->parent = x->parent; + + if (x->parent == 0) + root = y; + else if (x == x->parent->left) + x->parent->left = y; + else + x->parent->right = y; + + y->left = x; + x->parent = y; +} + +void RBTree::rightRotate(Node* x) { + Node* y = x->left; + x->left = y->right; + + if (y->right) + y->right->parent = x; + + y->parent = x->parent; + + if (x->parent == 0) + root = y; + else if (x == x->parent->right) + x->parent->right = y; + else + x->parent->left = y; + + y->right = x; + x->parent = y; +} + +void RBTree::insert(const string& k, const string& v) { + Node* n = new Node(k, v); + + if (root == 0) { + root = n; + root->red = false; + treeSize++; + return; + } + + Node* cur = root; + Node* par = 0; + + while (cur) { + par = cur; + + if (k < cur->key) + cur = cur->left; + else if (k > cur->key) + cur = cur->right; + else { + cur->value = v; + delete n; + return; + } + } + + n->parent = par; + + if (k < par->key) + par->left = n; + else + par->right = n; + + treeSize++; + fixAdd(n); +} + +void RBTree::fixAdd(Node* k) { + while (k->parent && k->parent->red) { + if (k->parent == k->parent->parent->left) { + Node* u = k->parent->parent->right; + + if (u && u->red) { + k->parent->red = false; + u->red = false; + k->parent->parent->red = true; + k = k->parent->parent; + } + else { + if (k == k->parent->right) { + k = k->parent; + leftRotate(k); + } + + k->parent->red = false; + k->parent->parent->red = true; + rightRotate(k->parent->parent); + } + } + else { + Node* u = k->parent->parent->left; + + if (u && u->red) { + k->parent->red = false; + u->red = false; + k->parent->parent->red = true; + k = k->parent->parent; + } + else { + if (k == k->parent->left) { + k = k->parent; + rightRotate(k); + } + + k->parent->red = false; + k->parent->parent->red = true; + leftRotate(k->parent->parent); + } + } + + if (k == root) break; + } + + root->red = false; +} + +RBTree::Node* RBTree::find(const string& k) { + Node* cur = root; + + while (cur) { + if (k < cur->key) + cur = cur->left; + else if (k > cur->key) + cur = cur->right; + else + return cur; + } + + return 0; +} + +bool RBTree::find(const string& k, string& v) { + Node* n = find(k); + + if (n) { + v = n->value; + return true; + } + + return false; +} + +void RBTree::replace(Node* u, Node* v) { + if (u->parent == 0) + root = v; + else if (u == u->parent->left) + u->parent->left = v; + else + u->parent->right = v; + + if (v) + v->parent = u->parent; +} + +RBTree::Node* RBTree::minNode(Node* n) { + while (n && n->left) + n = n->left; + + return n; +} + +void RBTree::remove(const string& k) { + Node* z = find(k); + if (z == 0) return; + + Node* y = z; + Node* x = 0; + bool yRed = y->red; + + if (z->left == 0) { + x = z->right; + replace(z, z->right); + } + else if (z->right == 0) { + x = z->left; + replace(z, z->left); + } + else { + y = minNode(z->right); + yRed = y->red; + x = y->right; + + if (y->parent == z) { + if (x) + x->parent = y; + } + else { + replace(y, y->right); + y->right = z->right; + + if (y->right) + y->right->parent = y; + } + + replace(z, y); + y->left = z->left; + + if (y->left) + y->left->parent = y; + + y->red = z->red; + } + + delete z; + treeSize--; + + if (yRed == false && x) + fixDel(x); +} + +void RBTree::fixDel(Node* x) { + while (x != root && x && x->red == false) { + if (x == x->parent->left) { + Node* s = x->parent->right; + + if (s && s->red) { + s->red = false; + x->parent->red = true; + leftRotate(x->parent); + s = x->parent->right; + } + + if (s && (s->left == 0 || s->left->red == false) && (s->right == 0 || s->right->red == false)) { + s->red = true; + x = x->parent; + } + else { + if (s && (s->right == 0 || s->right->red == false)) { + if (s->left) + s->left->red = false; + + s->red = true; + rightRotate(s); + s = x->parent->right; + } + + if (s) { + s->red = x->parent->red; + + if (s->right) + s->right->red = false; + } + + x->parent->red = false; + leftRotate(x->parent); + x = root; + } + } + else { + Node* s = x->parent->left; + + if (s && s->red) { + s->red = false; + x->parent->red = true; + rightRotate(x->parent); + s = x->parent->left; + } + + if (s && (s->right == 0 || s->right->red == false) && (s->left == 0 || s->left->red == false)) { + s->red = true; + x = x->parent; + } + else { + if (s && (s->left == 0 || s->left->red == false)) { + if (s->right) + s->right->red = false; + + s->red = true; + leftRotate(s); + s = x->parent->left; + } + + if (s) { + s->red = x->parent->red; + + if (s->left) + s->left->red = false; + } + + x->parent->red = false; + rightRotate(x->parent); + x = root; + } + } + } + + if (x) + x->red = false; +} + +int RBTree::size() const { + return treeSize; +} \ No newline at end of file diff --git a/LibraryCPPClass/RBTree.h b/LibraryCPPClass/RBTree.h new file mode 100644 index 0000000000..cc4bae30bb --- /dev/null +++ b/LibraryCPPClass/RBTree.h @@ -0,0 +1,43 @@ +#ifndef RBTREE_H +#define RBTREE_H + +#include + +using namespace std; + +class RBTree { +private: + struct Node { + string key; + string value; + bool red; + Node* left; + Node* right; + Node* parent; + + Node(const string& k, const string& v); + }; + + Node* root; + int treeSize; + + void clear(Node* n); + void leftRotate(Node* x); + void rightRotate(Node* x); + void fixAdd(Node* k); + void fixDel(Node* x); + Node* find(const string& k); + Node* minNode(Node* n); + void replace(Node* u, Node* v); + +public: + RBTree(); + ~RBTree(); + + void insert(const string& k, const string& v); + bool find(const string& k, string& v); + void remove(const string& k); + int size() const; +}; + +#endif \ No newline at end of file diff --git a/LibraryCPPClass/Tests/CMakeLists.txt b/LibraryCPPClass/Tests/CMakeLists.txt index 748ae652cc..dfa3e72941 100644 --- a/LibraryCPPClass/Tests/CMakeLists.txt +++ b/LibraryCPPClass/Tests/CMakeLists.txt @@ -1,7 +1,7 @@ -# add_executable(TestArrayCPPClass array.cpp) -# target_include_directories(TestArrayCPPClass PUBLIC ..) -# target_link_libraries(TestArrayCPPClass LibraryCPPClass) -# add_test(TestArrayCPPClass TestArrayCPPClass) +#add_executable(TestArrayCPPClass array.cpp) +#target_include_directories(TestArrayCPPClass PUBLIC ..) +#target_link_libraries(TestArrayCPPClass LibraryCPPClass) +#add_test(TestArrayCPPClass TestArrayCPPClass) # add_executable(TestListCPPClass list.cpp) # target_include_directories(TestListCPPClass PUBLIC ..) @@ -14,13 +14,18 @@ # add_test(TestQueueCPPClass TestQueueCPPClass) # set_tests_properties(TestQueueCPPClass PROPERTIES TIMEOUT 10) -# add_executable(TestStackCPPClass stack.cpp) -# target_include_directories(TestStackCPPClass PUBLIC ..) -# target_link_libraries(TestStackCPPClass LibraryCPPClass) -# add_test(TestStackCPPClass TestStackCPPClass) +#add_executable(TestStackCPPClass stack.cpp) +#target_include_directories(TestStackCPPClass PUBLIC ..) +#target_link_libraries(TestStackCPPClass LibraryCPPClass) +#add_test(TestStackCPPClass TestStackCPPClass) -# add_executable(TestVectorCPPClass vector.cpp) -# target_include_directories(TestVectorCPPClass PUBLIC ..) -# target_link_libraries(TestVectorCPPClass LibraryCPPClass) -# add_test(TestVectorCPPClass TestVectorCPPClass) -# set_tests_properties(TestVectorCPPClass PROPERTIES TIMEOUT 10) +#add_executable(TestVectorCPPClass vector.cpp) +#target_include_directories(TestVectorCPPClass PUBLIC ..) +#target_link_libraries(TestVectorCPPClass LibraryCPPClass) +#add_test(TestVectorCPPClass TestVectorCPPClass) +#set_tests_properties(TestVectorCPPClass PROPERTIES TIMEOUT 10) + +add_executable(TestRBTreeCPPClass RBTree.cpp) +target_include_directories(TestRBTreeCPPClass PUBLIC ..) +target_link_libraries(TestRBTreeCPPClass LibraryCPPClass) +add_test(TestRBTreeCPPClass TestRBTreeCPPClass) \ No newline at end of file diff --git a/LibraryCPPClass/Tests/RBTree.cpp b/LibraryCPPClass/Tests/RBTree.cpp new file mode 100644 index 0000000000..22480ccfa1 --- /dev/null +++ b/LibraryCPPClass/Tests/RBTree.cpp @@ -0,0 +1,170 @@ +#include "RBTree.h" +#include +#include + +using namespace std; + +void check(bool condition, const string& message) { + if (condition == false) { + cout << "Test failed: " << message << endl; + exit(1); + } +} + +void test_basic() { + RBTree t; + string value; + + t.insert("key1", "value1"); + check(t.find("key1", value), "find key1"); + check(value == "value1", "value1 correct"); + check(t.size() == 1, "size after insert"); + + t.remove("key1"); + check(!t.find("key1", value), "key1 removed"); + check(t.size() == 0, "size after remove"); + + cout << "Basic tests passed" << endl; +} + +void test_1000() { + RBTree t; + string value; + + for (int i = 0; i < 1000; i++) { + t.insert("key" + to_string(i), "value" + to_string(i)); + } + check(t.size() == 1000, "size 1000"); + + for (int i = 0; i < 1000; i++) { + check(t.find("key" + to_string(i), value), "find key" + to_string(i)); + check(value == "value" + to_string(i), "value" + to_string(i) + " correct"); + } + + for (int i = 0; i < 1000; i++) { + t.remove("key" + to_string(i)); + } + check(t.size() == 0, "empty after remove all"); + + cout << "1000 elements test passed" << endl; +} + +void test_10000() { + RBTree t; + string value; + + for (int i = 0; i < 10000; i++) { + t.insert("k" + to_string(i), "v" + to_string(i)); + } + check(t.size() == 10000, "size 10000"); + + for (int i = 0; i < 10000; i = i + 100) { + check(t.find("k" + to_string(i), value), "find k" + to_string(i)); + check(value == "v" + to_string(i), "v" + to_string(i) + " correct"); + } + + for (int i = 0; i < 10000; i++) { + t.remove("k" + to_string(i)); + } + check(t.size() == 0, "empty after remove 10000"); + + cout << "10000 elements test passed" << endl; +} + +void test_100000() { + RBTree t; + string value; + + for (int i = 0; i < 100000; i++) { + t.insert("key_" + to_string(i), "val_" + to_string(i)); + } + check(t.size() == 100000, "size 100000"); + + for (int i = 0; i < 100000; i = i + 1000) { + check(t.find("key_" + to_string(i), value), "find key_" + to_string(i)); + check(value == "val_" + to_string(i), "val_" + to_string(i) + " correct"); + } + + for (int i = 0; i < 100000; i++) { + t.remove("key_" + to_string(i)); + } + check(t.size() == 0, "empty after remove 100000"); + + cout << "100000 elements test passed" << endl; +} + +void test_1000000() { + RBTree t; + string value; + + for (int i = 0; i < 1000000; i++) { + t.insert("m" + to_string(i), "value" + to_string(i)); + } + check(t.size() == 1000000, "size 1000000"); + + for (int i = 0; i < 1000; i++) { + check(t.find("m" + to_string(i * 1000), value), "find m" + to_string(i * 1000)); + check(value == "value" + to_string(i * 1000), "value" + to_string(i * 1000) + " correct"); + } + + for (int i = 0; i < 1000000; i++) { + t.remove("m" + to_string(i)); + } + check(t.size() == 0, "empty after remove 1000000"); + + cout << "1000000 elements test passed" << endl; +} + +void test_updates() { + RBTree t; + string value; + + t.insert("key", "value1"); + t.insert("key", "value2"); + + check(t.find("key", value), "find after update"); + check(value == "value2", "updated value correct"); + check(t.size() == 1, "size stays 1 after update"); + + cout << "Update test passed" << endl; +} + +void test_mixed() { + RBTree t; + string value; + + for (int i = 0; i < 500; i++) { + t.insert("mixed" + to_string(i), "data" + to_string(i)); + } + + for (int i = 0; i < 500; i = i + 2) { + t.remove("mixed" + to_string(i)); + } + + for (int i = 1; i < 500; i = i + 2) { + check(t.find("mixed" + to_string(i), value), "find mixed" + to_string(i)); + } + + for (int i = 0; i < 500; i = i + 2) { + check(!t.find("mixed" + to_string(i), value), "mixed" + to_string(i) + " removed"); + } + + check(t.size() == 250, "size after mixed operations"); + + cout << "Mixed operations test passed" << endl; +} + +int main() { + cout << "Starting RBTree tests..." << endl; + + test_basic(); + test_updates(); + test_1000(); + test_10000(); + test_100000(); + test_1000000(); + test_mixed(); + + cout << "\nAll tests passed!" << endl; + return 0; +} \ No newline at end of file diff --git a/LibraryCPPClass/array.cpp b/LibraryCPPClass/array.cpp index 5f9679d07f..e94339195c 100644 --- a/LibraryCPPClass/array.cpp +++ b/LibraryCPPClass/array.cpp @@ -1,32 +1,67 @@ #include "array.h" +#include -Array::Array(size_t size) +Array::Array(size_t size) : size_arr(size), data_arr(new Data[size]) { + for (size_t i = 0; i < size_arr; i++) + { + data_arr[i] = Data(0); + } } -Array::Array(const Array &a) +Array::Array(const Array& other) : size_arr(other.size_arr) { + data_arr = new Data[size_arr]; + for (size_t i = 0; i < size_arr; i++) + { + data_arr[i] = other.data_arr[i]; + } } -Array &Array::operator=(const Array &a) +Array& Array::operator=(const Array& other) { + if (this != &other) { + delete[] data_arr; + size_arr = other.size_arr; + data_arr = new Data[size_arr]; + + for (size_t i = 0; i < size_arr; i++) { + data_arr[i] = other.data_arr[i]; + } + } return *this; } Array::~Array() { + delete[] data_arr; } Data Array::get(size_t index) const { - return Data(0); + if ((index >= size_arr)) + { + throw std::out_of_range("ERROR: index out of range"); + } + else + { + return data_arr[index]; + } } void Array::set(size_t index, Data value) { + if ((index >= size_arr)) + { + throw std::out_of_range("ERROR: index out of range"); + } + else + { + data_arr[index] = value; + } } size_t Array::size() const { - return 0; + return size_arr; } diff --git a/LibraryCPPClass/array.h b/LibraryCPPClass/array.h index 7ebd54f7a1..7f06d1eb8c 100644 --- a/LibraryCPPClass/array.h +++ b/LibraryCPPClass/array.h @@ -32,6 +32,8 @@ class Array private: // private data should be here + size_t size_arr; + Data* data_arr; }; #endif diff --git a/LibraryCPPClass/stack.cpp b/LibraryCPPClass/stack.cpp index 0dc91d6c29..c9822070ca 100644 --- a/LibraryCPPClass/stack.cpp +++ b/LibraryCPPClass/stack.cpp @@ -1,10 +1,11 @@ #include "stack.h" +#include Stack::Stack() { } -Stack::Stack(const Stack &a) +Stack::Stack(const Stack &a) : stack_data(a.stack_data) { // implement or disable this function } @@ -12,6 +13,9 @@ Stack::Stack(const Stack &a) Stack &Stack::operator=(const Stack &a) { // implement or disable this function + if (this != &a) { + stack_data = a.stack_data; + } return *this; } @@ -21,18 +25,28 @@ Stack::~Stack() void Stack::push(Data data) { + size_t old_size = stack_data.size(); + stack_data.resize(old_size + 1); + stack_data.set(old_size, data); } Data Stack::get() const { - return Data(); + if (stack_data.size() == 0) { + throw std::runtime_error("Stack is empty"); + } + return stack_data.get(stack_data.size() - 1); } void Stack::pop() { + if (stack_data.size() == 0) { + throw std::runtime_error("Stack is empty"); + } + stack_data.resize(stack_data.size() - 1); } bool Stack::empty() const { - return true; + return stack_data.size() == 0; } diff --git a/LibraryCPPClass/stack.h b/LibraryCPPClass/stack.h index 740c4c3e64..cd7921006a 100644 --- a/LibraryCPPClass/stack.h +++ b/LibraryCPPClass/stack.h @@ -2,9 +2,10 @@ #define STACK_H #include +#include "vector.h" // Change it to desired type -typedef int Data; +typedef size_t Data; class Stack { @@ -37,6 +38,7 @@ class Stack private: // private data should be here + Vector stack_data; }; #endif diff --git a/LibraryCPPClass/vector.cpp b/LibraryCPPClass/vector.cpp index 5bab7f34be..7178869d34 100644 --- a/LibraryCPPClass/vector.cpp +++ b/LibraryCPPClass/vector.cpp @@ -1,36 +1,69 @@ #include "vector.h" +#include -Vector::Vector() -{ +Vector::Vector() : elements(nullptr), capacity_value(0), size_value(0) { } -Vector::Vector(const Vector &a) -{ +void Vector::copyFunc(const Vector& a) { + elements = new Data[capacity_value]; + for (size_t i = 0; i < size_value; ++i) { + elements[i] = a.elements[i]; + } } -Vector &Vector::operator=(const Vector &a) -{ - return *this; +Vector::Vector(const Vector& a) : capacity_value(a.capacity_value), size_value(a.size_value) { + copyFunc(a); } -Vector::~Vector() -{ +Vector& Vector::operator=(const Vector& a) { + if (this != &a) { + delete[] elements; + capacity_value = a.capacity_value; + size_value = a.size_value; + copyFunc(a); + } + return *this; } -Data Vector::get(size_t index) const -{ - return Data(); +Vector::~Vector() { + delete[] elements; } -void Vector::set(size_t index, Data value) -{ +Data Vector::get(size_t index) const { + if (index >= size_value) { + throw std::out_of_range("Index out of range"); + } + return elements[index]; } -size_t Vector::size() const -{ - return 0; +void Vector::set(size_t index, Data value) { + if (index >= size_value) { + throw std::out_of_range("Index out of range"); + } + elements[index] = value; } -void Vector::resize(size_t size) -{ +size_t Vector::size() const { + return size_value; } + +void Vector::resize(size_t size) { + if (size > capacity_value) { + size_t new_capacity = 1; + if (capacity_value != 0) { + new_capacity = capacity_value; + } + while (new_capacity < size) { + new_capacity *= 2; + } + + Data* new_data = new Data[new_capacity]; + for (size_t i = 0; i < size_value; ++i) { + new_data[i] = elements[i]; + } + delete[] elements; + elements = new_data; + capacity_value = new_capacity; + } + size_value = size; +} \ No newline at end of file diff --git a/LibraryCPPClass/vector.h b/LibraryCPPClass/vector.h index 1d1d656da6..7569d55895 100644 --- a/LibraryCPPClass/vector.h +++ b/LibraryCPPClass/vector.h @@ -4,7 +4,7 @@ #include // Change it to desired type -typedef int Data; +typedef size_t Data; class Vector { @@ -36,6 +36,10 @@ class Vector private: // private data should be here + Data* elements; + size_t capacity_value; + size_t size_value; + void copyFunc(const Vector& a); }; #endif diff --git a/LibraryCPPTemplate/Tests/CMakeLists.txt b/LibraryCPPTemplate/Tests/CMakeLists.txt index cbee1c72d5..a85120b3ff 100644 --- a/LibraryCPPTemplate/Tests/CMakeLists.txt +++ b/LibraryCPPTemplate/Tests/CMakeLists.txt @@ -15,7 +15,11 @@ # target_include_directories(TestStackCPPTemplate PUBLIC ..) # add_test(TestStackCPPTemplate TestStackCPPTemplate) -# add_executable(TestVectorCPPTemplate vector.cpp) -# target_include_directories(TestVectorCPPTemplate PUBLIC ..) -# add_test(TestVectorCPPTemplate TestVectorCPPTemplate) -# set_tests_properties(TestVectorCPPTemplate PROPERTIES TIMEOUT 10) +add_executable(TestVectorCPPTemplate vector.cpp) +target_include_directories(TestVectorCPPTemplate PUBLIC ..) +add_test(TestVectorCPPTemplate TestVectorCPPTemplate) +set_tests_properties(TestVectorCPPTemplate PROPERTIES TIMEOUT 10) + +add_executable(TestGraphCPPTemplate graph.cpp) +target_include_directories(TestGraphCPPTemplate PUBLIC ..) +add_test(TestGraphCPPTemplate TestGraphCPPTemplate) diff --git a/LibraryCPPTemplate/Tests/graph.cpp b/LibraryCPPTemplate/Tests/graph.cpp new file mode 100644 index 0000000000..47ae0d570b --- /dev/null +++ b/LibraryCPPTemplate/Tests/graph.cpp @@ -0,0 +1,140 @@ +#include +#include "graph.h" + +int main() +{ + Graph mygraph(4); + + if (mygraph.get_vertex_count() != 4) + { + std::cout << "graph_vertex_count error\n"; + return 1; + } + + mygraph.set_vertex_label(0, 25); + mygraph.set_vertex_label(1, 50); + mygraph.set_vertex_label(2, 75); + mygraph.set_vertex_label(3, 100); + + if (mygraph.get_vertex_label(0) != 25 || + mygraph.get_vertex_label(1) != 50 || + mygraph.get_vertex_label(2) != 75 || + mygraph.get_vertex_label(3) != 100) + { + std::cout << "graph_vertex_label error\n"; + return 1; + } + + mygraph.add_edge(0, 1, 8); + mygraph.add_edge(0, 2, 12); + mygraph.add_edge(1, 2, 6); + mygraph.add_edge(2, 3, 9); + mygraph.add_edge(3, 0, 15); + + if (!mygraph.has_edge(0, 1) || !mygraph.has_edge(0, 2) || + !mygraph.has_edge(1, 2) || !mygraph.has_edge(2, 3) || + !mygraph.has_edge(3, 0)) + { + std::cout << "graph_add_edge error\n"; + return 1; + } + + if (mygraph.get_edge_label(0, 1) != 8 || + mygraph.get_edge_label(2, 3) != 9 || + mygraph.get_edge_label(3, 0) != 15) + { + std::cout << "graph_edge_label error\n"; + return 1; + } + + { + Graph::NeighborIterator it = mygraph.neighbors(0); + int count1 = 0; + int count2 = 0; + + while (it.valid()) + { + size_t v = it.vertex_id(); + if (v == 1) count1++; + if (v == 2) count2++; + it.next(); + } + + if (count1 != 1 || count2 != 1) + { + std::cout << "graph_neighbor_iterator error\n"; + return 1; + } + } + + mygraph.remove_edge(0, 2); + if (mygraph.has_edge(0, 2)) + { + std::cout << "graph_remove_edge error\n"; + return 1; + } + + Graph copygraph(mygraph); + if (copygraph.get_vertex_count() != mygraph.get_vertex_count() || + !copygraph.has_edge(0, 1) || !copygraph.has_edge(1, 2)) + { + std::cout << "graph_copy_ctor error\n"; + return 1; + } + + Graph othergraph(1); + othergraph = copygraph; + if (othergraph.get_vertex_count() != copygraph.get_vertex_count() || + !othergraph.has_edge(0, 1) || !othergraph.has_edge(2, 3)) + { + std::cout << "graph_assignment error\n"; + return 1; + } + + mygraph.remove_vertex(2); + if (mygraph.has_edge(0, 2) || mygraph.has_edge(1, 2)) + { + std::cout << "graph_remove_vertex error\n"; + return 1; + } + + size_t newid = mygraph.add_vertex(200); + if (newid != 4 || mygraph.get_vertex_count() != 5) + { + std::cout << "graph_add_vertex error\n"; + return 1; + } + + if (mygraph.get_vertex_label(newid) != 200) + { + std::cout << "graph_new_vertex_label error\n"; + return 1; + } + + mygraph.add_edge(newid, 0, 30); + mygraph.add_edge(1, newid, 40); + + if (!mygraph.has_edge(newid, 0) || mygraph.get_edge_label(newid, 0) != 30 || + !mygraph.has_edge(1, newid) || mygraph.get_edge_label(1, newid) != 40) + { + std::cout << "graph_edges_to_new_vertex error\n"; + return 1; + } + + Vector all_labels = mygraph.get_all_vertex_labels(); + if (all_labels.size() != 5) + { + std::cout << "graph_get_all_labels error\n"; + return 1; + } + + mygraph.set_edge_label(0, 1, 20); + if (mygraph.get_edge_label(0, 1) != 20) + { + std::cout << "graph_set_edge_label error\n"; + return 1; + } + + std::cout << "Graph tests passed\n"; + return 0; +} \ No newline at end of file diff --git a/LibraryCPPTemplate/Tests/vector.cpp b/LibraryCPPTemplate/Tests/vector.cpp index 7e549cacce..0752cb260f 100644 --- a/LibraryCPPTemplate/Tests/vector.cpp +++ b/LibraryCPPTemplate/Tests/vector.cpp @@ -15,7 +15,7 @@ int main() } for (size_t i = 0 ; i < vector.size() ; ++i) - vector.set(i, i); + vector.set(i, (int)i); vector = vector; diff --git a/LibraryCPPTemplate/graph.h b/LibraryCPPTemplate/graph.h new file mode 100644 index 0000000000..8fa90af0e8 --- /dev/null +++ b/LibraryCPPTemplate/graph.h @@ -0,0 +1,229 @@ +#ifndef GRAPH_TEMPLATE_H +#define GRAPH_TEMPLATE_H + +#include "vector.h" +#include + +template +class Graph { +public: + Graph(size_t count) { + vertex_count = count; + vertex_labels.resize(count); + exists.resize(count); + edges.resize(count); + + for (size_t i = 0; i < count; ++i) { + exists.set(i, true); + Vector& row = edges.get(i); + row.resize(count); + for (size_t j = 0; j < count; ++j) { + row.set(j, EdgeLabel()); + } + } + } + + Graph(const Graph& g) { + vertex_count = g.vertex_count; + vertex_labels = g.vertex_labels; + exists = g.exists; + edges = g.edges; + } + + Graph& operator=(const Graph& g) { + if (this != &g) { + vertex_count = g.vertex_count; + vertex_labels = g.vertex_labels; + exists = g.exists; + edges = g.edges; + } + return *this; + } + + size_t get_vertex_count() const { + return vertex_count; + } + + size_t add_vertex(VertexLabel value) { + size_t new_index = vertex_count; + vertex_count++; + + vertex_labels.resize(vertex_count); + vertex_labels.set(new_index, value); + + exists.resize(vertex_count); + exists.set(new_index, true); + + edges.resize(vertex_count); + + for (size_t i = 0; i < vertex_count - 1; ++i) { + Vector& row = edges.get(i); + row.resize(vertex_count); + } + + Vector& new_row = edges.get(new_index); + new_row.resize(vertex_count); + for (size_t j = 0; j < vertex_count; ++j) { + new_row.set(j, EdgeLabel()); + } + + return new_index; + } + + void remove_vertex(size_t vertex_id) { + if (vertex_id >= vertex_count || !exists.get(vertex_id)) { + return; + } + + exists.set(vertex_id, false); + vertex_labels.set(vertex_id, VertexLabel()); + + for (size_t i = 0; i < vertex_count; ++i) { + Vector& row = edges.get(vertex_id); + row.set(i, EdgeLabel()); + + Vector& new_row = edges.get(i); + new_row.set(vertex_id, EdgeLabel()); + } + } + + void set_vertex_label(size_t vertex_id, VertexLabel value) { + if (vertex_id < vertex_count && exists.get(vertex_id)) { + vertex_labels.set(vertex_id, value); + } + } + + VertexLabel get_vertex_label(size_t vertex_id) const { + if (vertex_id < vertex_count && exists.get(vertex_id)) { + return vertex_labels.get(vertex_id); + } + return VertexLabel(); + } + + Vector get_all_vertex_labels() const { + Vector result; + result.resize(vertex_count); + for (size_t i = 0; i < vertex_count; ++i) { + result.set(i, vertex_labels.get(i)); + } + return result; + } + + void add_edge(size_t from, size_t to, EdgeLabel value) { + if (from < vertex_count && to < vertex_count && + exists.get(from) && exists.get(to)) { + Vector& row = edges.get(from); + row.set(to, value); + } + } + + void remove_edge(size_t from, size_t to) { + if (from < vertex_count && to < vertex_count && + exists.get(from) && exists.get(to)) { + Vector& row = edges.get(from); + row.set(to, EdgeLabel()); + } + } + + bool has_edge(size_t from, size_t to) const { + if (from < vertex_count && to < vertex_count && + exists.get(from) && exists.get(to)) { + Vector row = edges.get(from); + EdgeLabel value = row.get(to); + EdgeLabel default_value = EdgeLabel(); + return !(value == default_value); + } + return false; + } + + void set_edge_label(size_t from, size_t to, EdgeLabel value) { + if (from < vertex_count && to < vertex_count && + exists.get(from) && exists.get(to) && has_edge(from, to)) { + Vector& row = edges.get(from); + row.set(to, value); + } + } + + EdgeLabel get_edge_label(size_t from, size_t to) const { + if (from < vertex_count && to < vertex_count && + exists.get(from) && exists.get(to) && has_edge(from, to)) { + Vector row = edges.get(from); + return row.get(to); + } + return EdgeLabel(); + } + + class NeighborIterator { + public: + NeighborIterator() { + graph = 0; + current = 0; + from_vertex = 0; + } + + bool valid() const { + return graph != 0 && current < graph->vertex_count; + } + + void next() { + if (graph == 0) return; + + current++; + while (current < graph->vertex_count) { + if (current != from_vertex && + graph->exists.get(from_vertex) && + graph->exists.get(current) && + graph->has_edge(from_vertex, current)) { + break; + } + current++; + } + } + + size_t vertex_id() const { + return current; + } + + EdgeLabel edge_label() const { + if (valid()) { + return graph->get_edge_label(from_vertex, current); + } + return EdgeLabel(); + } + + private: + const Graph* graph; + size_t current; + size_t from_vertex; + + NeighborIterator(const Graph* g, size_t from) { + graph = g; + from_vertex = from; + current = 0; + + while (current < graph->vertex_count) { + if (current != from_vertex && + graph->exists.get(from_vertex) && + graph->exists.get(current) && + graph->has_edge(from_vertex, current)) { + break; + } + current++; + } + } + + friend class Graph; + }; + + NeighborIterator neighbors(size_t from) const { + return NeighborIterator(this, from); + } + +private: + size_t vertex_count; + Vector vertex_labels; + Vector exists; + Vector> edges; +}; + +#endif \ No newline at end of file diff --git a/LibraryCPPTemplate/vector.h b/LibraryCPPTemplate/vector.h index f4872259e1..0e70220bd9 100644 --- a/LibraryCPPTemplate/vector.h +++ b/LibraryCPPTemplate/vector.h @@ -2,56 +2,112 @@ #define VECTOR_TEMPLATE_H #include +#include template class Vector { public: // Creates vector - Vector() + Vector() : elements(nullptr), capacity_value(0), size_value(0) { } // copy constructor - Vector(const Vector &a) + Vector(const Vector &a) : capacity_value(a.capacity_value), size_value(a.size_value) { + copyFunc(a); } // assignment operator Vector &operator=(const Vector &a) { + if (this != &a) { + delete[] elements; + capacity_value = a.capacity_value; + size_value = a.size_value; + copyFunc(a); + } return *this; } // Deletes vector structure and internal data ~Vector() { + delete[] elements; } // Retrieves vector element with the specified index - Data get(size_t index) const + Data& get(size_t index) { - return Data(); + if (index >= size_value) { + throw std::out_of_range("Index out of range"); + } + return elements[index]; + } + const Data& get(size_t index) const + { + if (index >= size_value) { + throw std::out_of_range("Index out of range"); + } + return elements[index]; } // Sets vector element with the specified index void set(size_t index, Data value) { + if (index >= size_value) { + throw std::out_of_range("Index out of range"); + } + elements[index] = value; } // Retrieves current vector size size_t size() const { - return 0; + return size_value; } // Changes the vector size (may increase or decrease) // Should be O(1) on average void resize(size_t size) { + if (size > capacity_value) { + size_t new_capacity = 1; + if (capacity_value != 0) { + new_capacity = capacity_value; + } + while (new_capacity < size) { + new_capacity *= 2; + } + + Data* new_data = new Data[new_capacity]; + for (size_t i = 0; i < size_value; ++i) { + new_data[i] = elements[i]; + } + delete[] elements; + elements = new_data; + capacity_value = new_capacity; + } + size_value = size; } private: // private data should be here + void copyFunc(const Vector& a) + { + if (capacity_value > 0) { + elements = new Data[capacity_value]; + for (size_t i = 0; i < size_value; ++i) { + elements[i] = a.elements[i]; + } + } + else { + elements = nullptr; + } + } + Data* elements; + size_t capacity_value; + size_t size_value; }; #endif diff --git a/Trachuk Lev 4093 b/Trachuk Lev 4093 new file mode 100644 index 0000000000..1cceae7c83 --- /dev/null +++ b/Trachuk Lev 4093 @@ -0,0 +1 @@ +Trachuk Lev 4093