diff --git a/CMakeLists.txt b/CMakeLists.txt index 06c6f26a..84e1c1a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/additional_tasks) file(GLOB_RECURSE tasks_dirs LIST_DIRECTORIES true ".") + foreach(dir ${tasks_dirs}) IF(IS_DIRECTORY ${dir}) IF(${dir} MATCHES "task_0[0-9]$" AND NOT ${dir} MATCHES "build") diff --git a/THEORY/theory.md b/THEORY/theory.md new file mode 100644 index 00000000..3eae8177 --- /dev/null +++ b/THEORY/theory.md @@ -0,0 +1,97 @@ +# Стеки, Очереди, Деки (C++) + +## Стек + +### Определение + +Стеком (англ. stack) называется хранилище данных, в котором можно работать только с одним элементом: тем, который был добавлен в стек последним. Стек должен поддерживать следующие операции: + +- `push`: Добавить (положить) в конец стека новый элемент. +- `pop`: Извлечь из стека последний элемент. +- `back`: Узнать значение последнего элемента (не удаляя его). +- `size`: Узнать количество элементов в стеке. +- `clear`: Очистить стек (удалить из него все элементы). + +### Структура данных Stack + +- stack(); // Конструктор +- ~stack(); // Деструктор +- void push(int d); // Добавить в стек новый элемент +- int pop(); // Удалить из стека последний элемент и вернуть его значение +- int back(); // Вернуть значение последнего элемента +- int size(); // Вернуть количество элементов в стеке +- void clear(); // Очистить стек + + +## Очередь + +### Определение + +Очередью (англ. queue) называется структура данных, в которой элементы кладутся в конец, а извлекаются из начала. Первым из очереди будет извлечен тот элемент, который будет добавлен раньше других. + +### Структура данных Queue + +- queue(); // Конструктор +- ~queue(); // Деструктор +- void push(int d); // Добавить в очередь новый элемент +- int pop(); // Удалить из очереди первый элемент и вернуть его значение +- int front(); // Вернуть значение первого элемента +- int size(); // Вернуть количество элементов в очереди +- void clear(); // Очистить очередь + +## Дек + +### Определение + +Деком (англ. deque – аббревиатура от double-ended queue, двухсторонняя очередь) называется структура данных, в которую можно удалять и добавлять элементы как в начало, так и в конец. + +### Структура данных Deque + +- push_front Добавить (положить) в начало дека новый элемент +- push_back Добавить (положить) в конец дека новый элемент +- pop_front Извлечь из дека первый элемент +- pop_back Извлечь из дека последний элемент +- front Узнать значение первого элемента (не удаляя его) +- back Узнать значение последнего элемента (не удаляя его) +- size Узнать количество элементов в деке +- clear Очистить дек (удалить из него все элементы) + + +## Упражнения + +### Упражнение A - Простой стек + +- Реализуйте структуру данных "стек", реализовав все указанные методы. +- Напишите программу (функцию main), содержащую описание стека и моделирующую работу стека. + +### Упражнение B - Стек с обработкой ошибок + +- Аналогично предыдущему заданию, только снимается ограничение на корректность вызовов методов back и pop. + +### Упражнение C - Стек без ограничения на размер + +- Реализуйте стек динамического размера, то есть ограниченный только объемом свободной оперативной памяти. + +### Упражнение D - Простая очередь + +- Реализуйте простейшую очередь, размер которой не превосходит 100 элементов. + +### Упражнение E - Очередь с обработкой ошибок + +- Аналогично заданию B, но для очереди. + +### Упражнение F - Очередь без ограничений на размер + +- Аналогично заданию C, но для очереди. + +### Упражнение G - Простой дек + +- Аналогично заданиям A и D, но для дека. + +### Упражнение H - Дек с обработкой ошибок + +- Аналогично заданиям B и E, но для дека. + +### Упражнение I - Дек неограниченного размера + +- Аналогично заданию C и F, но для дека. diff --git a/task_03/src/test.cpp b/task_03/src/test.cpp index ef5a86ae..9d605f11 100644 --- a/task_03/src/test.cpp +++ b/task_03/src/test.cpp @@ -3,6 +3,24 @@ #include "topology_sort.hpp" -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(DaysBeforeWarming, Simple) { + std::vector temperatures = {1, 2, 3, 4, 5}; + std::vector correct_answer = {1, 1, 1, 1, 0}; + ASSERT_EQ(DaysBeforeWarming(temperatures), correct_answer); + + temperatures = {1}; + correct_answer = {0}; + ASSERT_EQ(DaysBeforeWarming(temperatures), correct_answer); + + temperatures = {0, 0, 0, 0, 0, 5}; + correct_answer = {5, 4, 3, 2, 1, 0}; + ASSERT_EQ(DaysBeforeWarming(temperatures), correct_answer); + + temperatures = {0, 0, 0, 0, 0, 0}; + correct_answer = {0, 0, 0, 0, 0, 0}; + ASSERT_EQ(DaysBeforeWarming(temperatures), correct_answer); + + temperatures = {3, 12, 4, 4, 6, 2, 1, 9, 2}; + correct_answer = {1, 0, 2, 1, 3, 2, 1, 0, 0}; + ASSERT_EQ(DaysBeforeWarming(temperatures), correct_answer); } diff --git a/task_03/src/topology_sort.cpp b/task_03/src/topology_sort.cpp index e53f670c..9f290da9 100644 --- a/task_03/src/topology_sort.cpp +++ b/task_03/src/topology_sort.cpp @@ -1 +1,27 @@ #include "topology_sort.hpp" + +std::vector DaysBeforeWarming(std::vector temperatures) { + std::vector answer(temperatures.size()); + for (int i = 0; i < temperatures.size(); i++) { + answer[i] = 1; + bool was_warmer_found = false; + for (int j = i + 1; j < temperatures.size() and not was_warmer_found; j++) { + if (temperatures[i] >= + temperatures[j]) { // skip days, when tempreture is lower + answer[i] += 1; + } else if ((temperatures[i] < temperatures[j]) & + (j == i + 1)) { // case, when warmer day is rigth next + answer[i] = 1; + was_warmer_found = true; + } else if ((temperatures[i] < temperatures[j]) & + (j != i + 1)) { // case, when warmer day is rigth next + was_warmer_found = true; + } + } + + if (not was_warmer_found) { + answer[i] = 0; + } + } + return answer; +} \ No newline at end of file diff --git a/task_03/src/topology_sort.hpp b/task_03/src/topology_sort.hpp index 6f70f09b..a67dac26 100644 --- a/task_03/src/topology_sort.hpp +++ b/task_03/src/topology_sort.hpp @@ -1 +1,4 @@ #pragma once +#include + +std::vector DaysBeforeWarming(std::vector temperatures); \ No newline at end of file diff --git a/task_04/src/heap.cpp b/task_04/src/heap.cpp new file mode 100644 index 00000000..604c6353 --- /dev/null +++ b/task_04/src/heap.cpp @@ -0,0 +1,51 @@ +#include "heap.hpp" + +int Heap::PopMin() { + if (data_.size() != 0) { + int minimum = data_[0]; + std::swap(data_[0], data_[data_.size() - 1]); + data_.pop_back(); // min is already at last position + + // Sift Down (O(logn)) + int current_index = 0; + int left_child_index = 1; + int right_child_index = 2; + + while ((left_child_index + data_[left_child_index]) || + (right_child_index + data_[right_child_index])) { + if (right_child_index < data_.size() & + data_[right_child_index] < data_[left_child_index]) { + std::swap(data_[right_child_index], data_[current_index]); + current_index = right_child_index; + left_child_index = 2 * current_index + 1; + right_child_index = 2 * current_index + 2; + } else { + std::swap(data_[left_child_index], data_[current_index]); + current_index = left_child_index; + left_child_index = 2 * current_index + 1; + right_child_index = 2 * current_index + 2; + } + } + + return minimum; + } else { + std::cout << "empty heap"; + return {}; + } +} + +void Heap::Insert(int x) { + data_.push_back(x); + + // Sift Up (O(logn)) + int current_index = data_.size() - 1; + int parent_index = (current_index - 1) / 2; + + while (data_[current_index] 0) { + std::swap(data_[current_index], data_[parent_index]); + current_index = (current_index - 1) / 2; + parent_index = (current_index - 1) / 2; + } +} diff --git a/task_04/src/heap.hpp b/task_04/src/heap.hpp new file mode 100644 index 00000000..7dc7ffda --- /dev/null +++ b/task_04/src/heap.hpp @@ -0,0 +1,15 @@ +#pragma once +#include +#include + +class Heap { + public: + Heap() { data_ = {}; } + int PopMin(); + void Insert(int x); + std::vector GetData() { return data_; } + void CleanHeap() { data_ = {}; } + + private: + std::vector data_; +}; \ No newline at end of file diff --git a/task_04/src/test.cpp b/task_04/src/test.cpp index 5e11617e..541b2d49 100644 --- a/task_04/src/test.cpp +++ b/task_04/src/test.cpp @@ -1,6 +1,32 @@ #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include + +#include "heap.hpp" + +TEST(HeapTest, Simple) { + Heap heap; + std::vector answer = {}; + heap.PopMin(); + ASSERT_EQ(heap.GetData(), answer); // pop from empty heap + + heap.Insert(1); + heap.Insert(2); + heap.Insert(3); + heap.Insert(4); + heap.Insert(5); + heap.Insert(6); + + heap.Insert(0); + answer = {0, 2, 1, 4, 5, 6, 3}; + ASSERT_EQ(heap.GetData(), answer); // insert key, smaller than its parent + + heap.PopMin(); + answer = {1, 2, 3, 4, 5, 6}; + ASSERT_EQ(heap.GetData(), answer); // pop from full heap + + heap.Insert(100); + answer = {1, 2, 3, 4, 5, 6, 100}; + ASSERT_EQ(heap.GetData(), answer); // insert key, smaller than its parent } diff --git a/task_05/src/bogo_sort.cpp b/task_05/src/bogo_sort.cpp new file mode 100644 index 00000000..d8a9f072 --- /dev/null +++ b/task_05/src/bogo_sort.cpp @@ -0,0 +1,61 @@ +#include "bogo_sort.hpp" + +int Search(std::vector massive, int num) { + for (int i = 0; i < massive.size(); i++) { + if (massive[i] == num) { + return i; + } + } + return -1; +} + +std::vector ShuffleIndexes(int n) { + std::vector random_nums(n); + for (int i = 0; i < n; i) { + int rand_num = std::experimental::randint(1, n); + if (Search(random_nums, rand_num) == -1) { + random_nums[i] = rand_num; + i++; + } + } + for (int i = 0; i < n; i++) { + random_nums[i]--; + } + + return random_nums; +} + +std::vector ShuffleMassive(std::vector massive) { + std::vector random_indexes = ShuffleIndexes(massive.size()); + std::vector new_massive(massive.size()); + + for (int i = 0; i < massive.size(); i++) { + new_massive[i] = massive[random_indexes[i]]; + } + return new_massive; +} + +bool IsSorted(std::vector massive) { + for (int i = 0; i < massive.size() - 1; i++) { + if (massive[i] > massive[i + 1]) { + return false; + } + } + return true; +} + +// O(n!) +std::vector BogoSort(std::vector massive) { + if (massive.size() == 0) { + return massive; + } + if (IsSorted(massive)) { + return massive; + } else { + std::vector new_massive = ShuffleMassive(massive); + while (not IsSorted(new_massive)) { + new_massive = ShuffleMassive(massive); + } + return new_massive; + } +} diff --git a/task_05/src/bogo_sort.hpp b/task_05/src/bogo_sort.hpp new file mode 100644 index 00000000..00bbf2c6 --- /dev/null +++ b/task_05/src/bogo_sort.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +int Search(std::vector massive, int num); +bool IsSorted(std::vector massive); + +std::vector ShuffleIndexes(int n); +std::vector ShuffleMassive(std::vector massive); + +// O(n!) +std::vector BogoSort(std::vector massive); \ No newline at end of file diff --git a/task_05/src/bubble_sort.cpp b/task_05/src/bubble_sort.cpp new file mode 100644 index 00000000..c913c567 --- /dev/null +++ b/task_05/src/bubble_sort.cpp @@ -0,0 +1,15 @@ +#include "bubble_sort.hpp" + +// O(n^2) +std::vector BubbleSort(std::vector massive) { + for (int i = 0; i < massive.size(); i++) { + for (int j = 0; j < massive.size() - i - 1; j++) { + if (massive[j] > massive[j + 1]) { + int temporary = massive[j]; + massive[j] = massive[j + 1]; + massive[j + 1] = temporary; + } + } + } + return massive; +} \ No newline at end of file diff --git a/task_05/src/bubble_sort.hpp b/task_05/src/bubble_sort.hpp new file mode 100644 index 00000000..6e032793 --- /dev/null +++ b/task_05/src/bubble_sort.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +std::vector BubbleSort(std::vector massive); diff --git a/task_05/src/insertion_sort.cpp b/task_05/src/insertion_sort.cpp new file mode 100644 index 00000000..190a89e8 --- /dev/null +++ b/task_05/src/insertion_sort.cpp @@ -0,0 +1,42 @@ +#include "insertion_sort.hpp" + +std::vector Insert(std::vector massive, int num) { + std::vector new_massive; + if (num <= massive[0]) { + new_massive.push_back(num); + for (int i = 0; i < massive.size(); i++) { + new_massive.push_back(massive[i]); + } + return new_massive; + } + + else if (num >= massive[massive.size() - 1]) { + massive.push_back(num); + return massive; + } + + int position = 0; + for (int i = 0; num >= massive[i]; i++) { + new_massive.push_back(massive[i]); + position = i; + } + new_massive.push_back(num); + + for (int i = position + 1; i < massive.size(); i++) { + new_massive.push_back(massive[i]); + } + return new_massive; +} + +// O(n^2)y +std::vector InsertionSort(std::vector massive) { + if (massive.size() == 0) { + return massive; + } + std::vector new_massive; + new_massive.push_back(massive[0]); + for (int i = 1; i < massive.size(); i++) { + new_massive = Insert(new_massive, massive[i]); + } + return new_massive; +} \ No newline at end of file diff --git a/task_05/src/insertion_sort.hpp b/task_05/src/insertion_sort.hpp new file mode 100644 index 00000000..7b5083bf --- /dev/null +++ b/task_05/src/insertion_sort.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +std::vector Insert(std::vector massive, int num); + +// O(n^2) +std::vector InsertionSort(std::vector massive); \ No newline at end of file diff --git a/task_05/src/merge_sort.cpp b/task_05/src/merge_sort.cpp new file mode 100644 index 00000000..df5b7dc4 --- /dev/null +++ b/task_05/src/merge_sort.cpp @@ -0,0 +1,86 @@ +#include "merge_sort.hpp" + +std::vector Merge(std::vector part1, std::vector part2) { + std::vector result; + int index1 = 0; + int index2 = 0; + + while (index1 < part1.size() && + index2 < part2.size()) { // Add elements while each part is not empty + if (part1[index1] <= part2[index2]) { + result.push_back(part1[index1]); + index1++; + } else if (part2[index2] < part1[index1]) { + result.push_back(part2[index2]); + index2++; + } + } + if (index1 < part1.size()) { // Some elements left in part1 + while (index1 < part1.size()) { + result.push_back(part1[index1]); + index1++; + } + } else if (index2 < part2.size()) { // Some elements left in part2 + while (index2 < part2.size()) { + result.push_back(part2[index2]); + index2++; + } + } + return result; +} + +// O(NlogN) +std::vector MergeSortTopBottom(std::vector massive) { + if (massive.size() == 0) { + return massive; + } + std::vector part1; + std::vector part2; + if (massive.size() != 1) { + if (massive.size() % 2 == 0) { + part1 = + std::vector(massive.begin(), massive.end() - massive.size() / 2); + part2 = std::vector(massive.begin() + (massive.size()) / 2, + massive.end()); + } else { + part1 = + std::vector(massive.begin(), massive.end() - massive.size() / 2); + part2 = std::vector(massive.begin() + (massive.size() + 1) / 2, + massive.end()); + } + } + + else { + return massive; + } + part1 = MergeSortTopBottom(part1); + part2 = MergeSortTopBottom(part2); + + std::vector result = Merge(part1, part2); + + return result; +} + +// O(NlogN) +std::vector MergeSortBottomUp(std::vector massive) { + if (massive.size() == 0) { + return massive; + } + std::vector> parts; + for (int i = 0; i < massive.size(); i++) { + parts.push_back(std::vector{massive[i]}); + } + std::vector> new_parts; + while (parts.size() > 1) { + for (int i = 0; i < parts.size() - 1; i) { + new_parts.push_back(Merge(parts[i], parts[i + 1])); + i += 2; + } + if (parts.size() % 2 != 0) { + new_parts.push_back(parts[parts.size() - 1]); + } + parts = new_parts; + new_parts.clear(); + } + return parts[0]; +} \ No newline at end of file diff --git a/task_05/src/merge_sort.hpp b/task_05/src/merge_sort.hpp new file mode 100644 index 00000000..7b52ce8c --- /dev/null +++ b/task_05/src/merge_sort.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +std::vector Merge(std::vector part1, std::vector part2); + +// O(NlogN) +std::vector MergeSortTopBottom(std::vector massive); +// O(NlogN) +std::vector MergeSortBottomUp(std::vector massive); \ No newline at end of file diff --git a/task_05/src/quick_sort.cpp b/task_05/src/quick_sort.cpp new file mode 100644 index 00000000..2b54dc8f --- /dev/null +++ b/task_05/src/quick_sort.cpp @@ -0,0 +1,41 @@ +#include "quick_sort.hpp" + +#include + +// O*(NlogN) (but upper limit is O(n^2) if pivat is always bad) +std::vector QuickSort(std::vector massive) { + if (massive.empty()) return std::vector{}; + int pivat_index = massive.size() / 2; + int pivat = massive[pivat_index]; + + std::vector smaller_part; + std::vector bigger_part; + + if (massive.size() > 1) { + for (int i = 0; i < massive.size(); i++) { + if (i != pivat_index) { + if (massive[i] <= pivat) { + smaller_part.push_back(massive[i]); + } else { + bigger_part.push_back(massive[i]); + } + } + } + } else { + return massive; + } + if (smaller_part.size() > 1) { + smaller_part = QuickSort(smaller_part); + } + + if (bigger_part.size() > 1) { + bigger_part = QuickSort(bigger_part); + } + + std::vector result = smaller_part; + result.push_back(pivat); + for (int i = 0; i < bigger_part.size(); i++) { + result.push_back(bigger_part[i]); + } + return result; +} \ No newline at end of file diff --git a/task_05/src/quick_sort.hpp b/task_05/src/quick_sort.hpp new file mode 100644 index 00000000..71465909 --- /dev/null +++ b/task_05/src/quick_sort.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +// O*(NlogN) (but upper limit is O(n^2) if pivat is bad) +std::vector QuickSort(std::vector massive); \ No newline at end of file diff --git a/task_05/src/selection_sort.cpp b/task_05/src/selection_sort.cpp new file mode 100644 index 00000000..f00360c2 --- /dev/null +++ b/task_05/src/selection_sort.cpp @@ -0,0 +1,24 @@ +#include "selection_sort.hpp" + +int SearchMin(std::vector massive) { + int min = massive[0]; + int index = 0; + for (int i = 0; i < massive.size(); i++) { + if (massive[i] < min) { + min = massive[i]; + index = i; + } + } + return index; +} + +// O(n^2) +std::vector SelectionSort(std::vector massive) { + for (int i = 0; i < massive.size(); i++) { + std::vector cutted_massive = + std::vector(massive.begin() + i, massive.end()); + int min_element_index = SearchMin(cutted_massive) + i; + std::swap(massive[i], massive[min_element_index]); + } + return massive; +} \ No newline at end of file diff --git a/task_05/src/selection_sort.hpp b/task_05/src/selection_sort.hpp new file mode 100644 index 00000000..68719da1 --- /dev/null +++ b/task_05/src/selection_sort.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +int SearchMin(std::vector massive); + +// O(n^2) +std::vector SelectionSort(std::vector massive); \ No newline at end of file diff --git a/task_05/src/test.cpp b/task_05/src/test.cpp index 5e11617e..d07c216a 100644 --- a/task_05/src/test.cpp +++ b/task_05/src/test.cpp @@ -1,6 +1,443 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include + +#include "bogo_sort.hpp" +#include "bubble_sort.hpp" +#include "insertion_sort.hpp" +#include "merge_sort.hpp" +#include "quick_sort.hpp" +#include "selection_sort.hpp" + +// tests for quick sort +TEST(Quick_Sort, Simple) { + std::vector vec1{9, 8, 7, 6, 5, 4, 2, 3, 1, 0}; + ASSERT_EQ(QuickSort(vec1), (std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + std::vector vec2{10, 90, 30, 80, 60, 50}; + ASSERT_EQ(QuickSort(vec2), (std::vector{10, 30, 50, 60, 80, 90})); + std::vector vec3{12, 43, 15, 26, -1233, 346, 1325, + -56, -12, 78, 0, 3345, -34}; + ASSERT_EQ(QuickSort(vec3), (std::vector{-1233, -56, -34, -12, 0, 12, 15, + 26, 43, 78, 346, 1325, 3345})); + vec3.push_back(-10); + vec3.push_back(1000); + vec3.push_back(5); + ASSERT_EQ(QuickSort(vec3), + (std::vector{-1233, -56, -34, -12, -10, 0, 5, 12, 15, 26, 43, + 78, 346, 1000, 1325, 3345})); +} + +TEST(Quick_Sort, EmptyVector) { + std::vector vec; + ASSERT_EQ(QuickSort(vec), (std::vector{})); +} + +TEST(Quick_Sort, SingleElement) { + std::vector vec{1}; + ASSERT_EQ(QuickSort(vec), (std::vector{1})); +} + +TEST(Quick_Sort, RepeatedElements) { + std::vector vec{5, 5, 5, 5}; + ASSERT_EQ(QuickSort(vec), (std::vector{5, 5, 5, 5})); +} + +TEST(Quick_Sort, MixedNumbers) { + std::vector vec{-1, 3, -2, 5, 4, -3}; + ASSERT_EQ(QuickSort(vec), (std::vector{-3, -2, -1, 3, 4, 5})); +} + +TEST(Quick_Sort, AlreadySorted) { + std::vector vec{1, 2, 3, 4, 5}; + ASSERT_EQ(QuickSort(vec), (std::vector{1, 2, 3, 4, 5})); +} + +TEST(Quick_Sort, ReverseOrder) { + std::vector vec{5, 4, 3, 2, 1}; + ASSERT_EQ(QuickSort(vec), (std::vector{1, 2, 3, 4, 5})); +} + +TEST(Quick_Sort, ZerosAndNegatives) { + std::vector vec{0, -1, 0, -2, 0, -3}; + ASSERT_EQ(QuickSort(vec), (std::vector{-3, -2, -1, 0, 0, 0})); +} + +TEST(Quick_Sort, LargeArray) { + std::vector vec(1000); + std::iota(vec.begin(), vec.end(), -500); + std::random_shuffle(vec.begin(), vec.end()); + std::vector sorted_vec(vec); + std::sort(sorted_vec.begin(), sorted_vec.end()); + ASSERT_EQ(QuickSort(vec), sorted_vec); +} + +// tests for bogo sort +TEST(Bogo_Sort, Simple) { + std::vector vec1{5, 4, 2, 3, 1, 0}; + + ASSERT_EQ(BogoSort(vec1), (std::vector{0, 1, 2, 3, 4, 5})); +} + +TEST(Bogo_Sort, EmptyVector) { + std::vector vec; + ASSERT_EQ(BogoSort(vec), (std::vector{})); +} + +TEST(Bogo_Sort, SingleElement) { + std::vector vec{1}; + ASSERT_EQ(BogoSort(vec), (std::vector{1})); +} + +TEST(Bogo_Sort, RepeatedElements) { + std::vector vec{5, 5, 5, 5}; + ASSERT_EQ(BogoSort(vec), (std::vector{5, 5, 5, 5})); +} + +TEST(Bogo_Sort, MixedNumbers) { + std::vector vec{-1, 3, -2, 5, 4, -3}; + ASSERT_EQ(BogoSort(vec), (std::vector{-3, -2, -1, 3, 4, 5})); +} + +TEST(Bogo_Sort, AlreadySorted) { + std::vector vec{1, 2, 3, 4, 5}; + ASSERT_EQ(BogoSort(vec), (std::vector{1, 2, 3, 4, 5})); +} + +TEST(Bogo_Sort, ReverseOrder) { + std::vector vec{5, 4, 3, 2, 1}; + ASSERT_EQ(BogoSort(vec), (std::vector{1, 2, 3, 4, 5})); +} + +TEST(Bogo_Sort, ZerosAndNegatives) { + std::vector vec{0, -1, 0, -2, 0, -3}; + ASSERT_EQ(BogoSort(vec), (std::vector{-3, -2, -1, 0, 0, 0})); +} + +// TEST(Bogo_Sort, LargeArray) { +// std::vector vec(1000); +// std::iota(vec.begin(), vec.end(), -500); +// std::random_shuffle(vec.begin(), vec.end()); +// std::vector sorted_vec(vec); +// std::sort(sorted_vec.begin(), sorted_vec.end()); +// ASSERT_EQ(BogoSort(vec), sorted_vec); +// } + +// tests for bubble sort +TEST(Bubble_Sort, Simple) { + std::vector vec1{9, 8, 7, 6, 5, 4, 2, 3, 1, 0}; + ASSERT_EQ(BubbleSort(vec1), (std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + std::vector vec2{10, 90, 30, 80, 60, 50}; + ASSERT_EQ(BubbleSort(vec2), (std::vector{10, 30, 50, 60, 80, 90})); + std::vector vec3{12, 43, 15, 26, -1233, 346, 1325, + -56, -12, 78, 0, 3345, -34}; + ASSERT_EQ(BubbleSort(vec3), (std::vector{-1233, -56, -34, -12, 0, 12, 15, + 26, 43, 78, 346, 1325, 3345})); + vec3.push_back(-10); + vec3.push_back(1000); + vec3.push_back(5); + ASSERT_EQ(BubbleSort(vec3), + (std::vector{-1233, -56, -34, -12, -10, 0, 5, 12, 15, 26, 43, + 78, 346, 1000, 1325, 3345})); +} + +TEST(Bubble_Sort, EmptyVector) { + std::vector vec; + ASSERT_EQ(BubbleSort(vec), (std::vector{})); +} + +TEST(Bubble_Sort, SingleElement) { + std::vector vec{1}; + ASSERT_EQ(BubbleSort(vec), (std::vector{1})); +} + +TEST(Bubble_Sort, RepeatedElements) { + std::vector vec{5, 5, 5, 5}; + ASSERT_EQ(BubbleSort(vec), (std::vector{5, 5, 5, 5})); +} + +TEST(Bubble_Sort, MixedNumbers) { + std::vector vec{-1, 3, -2, 5, 4, -3}; + ASSERT_EQ(BubbleSort(vec), (std::vector{-3, -2, -1, 3, 4, 5})); +} + +TEST(Bubble_Sort, AlreadySorted) { + std::vector vec{1, 2, 3, 4, 5}; + ASSERT_EQ(BubbleSort(vec), (std::vector{1, 2, 3, 4, 5})); +} + +TEST(Bubble_Sort, ReverseOrder) { + std::vector vec{5, 4, 3, 2, 1}; + ASSERT_EQ(BubbleSort(vec), (std::vector{1, 2, 3, 4, 5})); +} + +TEST(Bubble_Sort, ZerosAndNegatives) { + std::vector vec{0, -1, 0, -2, 0, -3}; + ASSERT_EQ(BubbleSort(vec), (std::vector{-3, -2, -1, 0, 0, 0})); +} + +TEST(Bubble_Sort, LargeArray) { + std::vector vec(1000); + std::iota(vec.begin(), vec.end(), -500); + std::random_shuffle(vec.begin(), vec.end()); + std::vector sorted_vec(vec); + std::sort(sorted_vec.begin(), sorted_vec.end()); + ASSERT_EQ(BubbleSort(vec), sorted_vec); +} + +// tests for insertion sort +TEST(Insertion_Sort, Simple) { + std::vector vec1{9, 8, 7, 6, 5, 4, 2, 3, 1, 0}; + ASSERT_EQ(InsertionSort(vec1), + (std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + std::vector vec2{10, 90, 30, 80, 60, 50}; + ASSERT_EQ(InsertionSort(vec2), (std::vector{10, 30, 50, 60, 80, 90})); + std::vector vec3{12, 43, 15, 26, -1233, 346, 1325, + -56, -12, 78, 0, 3345, -34}; + ASSERT_EQ(InsertionSort(vec3), + (std::vector{-1233, -56, -34, -12, 0, 12, 15, 26, 43, 78, 346, + 1325, 3345})); + vec3.push_back(-10); + vec3.push_back(1000); + vec3.push_back(5); + ASSERT_EQ(InsertionSort(vec3), + (std::vector{-1233, -56, -34, -12, -10, 0, 5, 12, 15, 26, 43, + 78, 346, 1000, 1325, 3345})); +} + +TEST(Insertion_Sort, EmptyVector) { + std::vector vec; + ASSERT_EQ(InsertionSort(vec), (std::vector{})); +} + +TEST(Insertion_Sort, SingleElement) { + std::vector vec{1}; + ASSERT_EQ(InsertionSort(vec), (std::vector{1})); +} + +TEST(Insertion_Sort, RepeatedElements) { + std::vector vec{5, 5, 5, 5}; + ASSERT_EQ(InsertionSort(vec), (std::vector{5, 5, 5, 5})); +} + +TEST(Insertion_Sort, MixedNumbers) { + std::vector vec{-1, 3, -2, 5, 4, -3}; + ASSERT_EQ(InsertionSort(vec), (std::vector{-3, -2, -1, 3, 4, 5})); +} + +TEST(Insertion_Sort, AlreadySorted) { + std::vector vec{1, 2, 3, 4, 5}; + ASSERT_EQ(InsertionSort(vec), (std::vector{1, 2, 3, 4, 5})); +} + +TEST(Insertion_Sort, ReverseOrder) { + std::vector vec{5, 4, 3, 2, 1}; + ASSERT_EQ(InsertionSort(vec), (std::vector{1, 2, 3, 4, 5})); +} + +TEST(Insertion_Sort, ZerosAndNegatives) { + std::vector vec{0, -1, 0, -2, 0, -3}; + ASSERT_EQ(InsertionSort(vec), (std::vector{-3, -2, -1, 0, 0, 0})); +} + +TEST(Insertion_Sort, LargeArray) { + std::vector vec(1000); + std::iota(vec.begin(), vec.end(), -500); + std::random_shuffle(vec.begin(), vec.end()); + std::vector sorted_vec(vec); + std::sort(sorted_vec.begin(), sorted_vec.end()); + ASSERT_EQ(InsertionSort(vec), sorted_vec); +} + +// tests for selection sort +TEST(Selection_Sort, Simple) { + std::vector vec1{9, 8, 7, 6, 5, 4, 2, 3, 1, 0}; + ASSERT_EQ(SelectionSort(vec1), + (std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + std::vector vec2{10, 90, 30, 80, 60, 50}; + ASSERT_EQ(SelectionSort(vec2), (std::vector{10, 30, 50, 60, 80, 90})); + std::vector vec3{12, 43, 15, 26, -1233, 346, 1325, + -56, -12, 78, 0, 3345, -34}; + ASSERT_EQ(SelectionSort(vec3), + (std::vector{-1233, -56, -34, -12, 0, 12, 15, 26, 43, 78, 346, + 1325, 3345})); + vec3.push_back(-10); + vec3.push_back(1000); + vec3.push_back(5); + ASSERT_EQ(SelectionSort(vec3), + (std::vector{-1233, -56, -34, -12, -10, 0, 5, 12, 15, 26, 43, + 78, 346, 1000, 1325, 3345})); +} + +TEST(Selection_Sort, EmptyVector) { + std::vector vec; + ASSERT_EQ(SelectionSort(vec), (std::vector{})); +} + +TEST(Selection_Sort, SingleElement) { + std::vector vec{1}; + ASSERT_EQ(SelectionSort(vec), (std::vector{1})); +} + +TEST(Selection_Sort, RepeatedElements) { + std::vector vec{5, 5, 5, 5}; + ASSERT_EQ(SelectionSort(vec), (std::vector{5, 5, 5, 5})); +} + +TEST(Selection_Sort, MixedNumbers) { + std::vector vec{-1, 3, -2, 5, 4, -3}; + ASSERT_EQ(SelectionSort(vec), (std::vector{-3, -2, -1, 3, 4, 5})); +} + +TEST(Selection_Sort, AlreadySorted) { + std::vector vec{1, 2, 3, 4, 5}; + ASSERT_EQ(SelectionSort(vec), (std::vector{1, 2, 3, 4, 5})); +} + +TEST(Selection_Sort, ReverseOrder) { + std::vector vec{5, 4, 3, 2, 1}; + ASSERT_EQ(SelectionSort(vec), (std::vector{1, 2, 3, 4, 5})); +} + +TEST(Selection_Sort, ZerosAndNegatives) { + std::vector vec{0, -1, 0, -2, 0, -3}; + ASSERT_EQ(SelectionSort(vec), (std::vector{-3, -2, -1, 0, 0, 0})); +} + +TEST(Selection_Sort, LargeArray) { + std::vector vec(1000); + std::iota(vec.begin(), vec.end(), -500); + std::random_shuffle(vec.begin(), vec.end()); + std::vector sorted_vec(vec); + std::sort(sorted_vec.begin(), sorted_vec.end()); + ASSERT_EQ(SelectionSort(vec), sorted_vec); +} + +// tests for merge sort top buttom +TEST(Merge_Sort_Top_Buttom, Simple) { + std::vector vec1{9, 8, 7, 6, 5, 4, 2, 3, 1, 0}; + ASSERT_EQ(MergeSortTopBottom(vec1), + (std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + std::vector vec2{10, 90, 30, 80, 60, 50}; + ASSERT_EQ(MergeSortTopBottom(vec2), + (std::vector{10, 30, 50, 60, 80, 90})); + std::vector vec3{12, 43, 15, 26, -1233, 346, 1325, + -56, -12, 78, 0, 3345, -34}; + ASSERT_EQ(MergeSortTopBottom(vec3), + (std::vector{-1233, -56, -34, -12, 0, 12, 15, 26, 43, 78, 346, + 1325, 3345})); + vec3.push_back(-10); + vec3.push_back(1000); + vec3.push_back(5); + ASSERT_EQ(MergeSortTopBottom(vec3), + (std::vector{-1233, -56, -34, -12, -10, 0, 5, 12, 15, 26, 43, + 78, 346, 1000, 1325, 3345})); +} + +TEST(Merge_Sort_Top_Buttom, EmptyVector) { + std::vector vec; + ASSERT_EQ(MergeSortTopBottom(vec), (std::vector{})); +} + +TEST(Merge_Sort_Top_Buttom, SingleElement) { + std::vector vec{1}; + ASSERT_EQ(MergeSortTopBottom(vec), (std::vector{1})); +} + +TEST(Merge_Sort_Top_Buttom, RepeatedElements) { + std::vector vec{5, 5, 5, 5}; + ASSERT_EQ(MergeSortTopBottom(vec), (std::vector{5, 5, 5, 5})); +} + +TEST(Merge_Sort_Top_Buttom, MixedNumbers) { + std::vector vec{-1, 3, -2, 5, 4, -3}; + ASSERT_EQ(MergeSortTopBottom(vec), (std::vector{-3, -2, -1, 3, 4, 5})); +} + +TEST(Merge_Sort_Top_Buttom, AlreadySorted) { + std::vector vec{1, 2, 3, 4, 5}; + ASSERT_EQ(MergeSortTopBottom(vec), (std::vector{1, 2, 3, 4, 5})); +} + +TEST(Merge_Sort_Top_Buttom, ReverseOrder) { + std::vector vec{5, 4, 3, 2, 1}; + ASSERT_EQ(MergeSortTopBottom(vec), (std::vector{1, 2, 3, 4, 5})); +} + +TEST(Merge_Sort_Top_Buttom, ZerosAndNegatives) { + std::vector vec{0, -1, 0, -2, 0, -3}; + ASSERT_EQ(MergeSortTopBottom(vec), (std::vector{-3, -2, -1, 0, 0, 0})); +} + +TEST(Merge_Sort_Top_Buttom, LargeArray) { + std::vector vec(1000); + std::iota(vec.begin(), vec.end(), -500); + std::random_shuffle(vec.begin(), vec.end()); + std::vector sorted_vec(vec); + std::sort(sorted_vec.begin(), sorted_vec.end()); + ASSERT_EQ(MergeSortTopBottom(vec), sorted_vec); +} + +// tests for merge sort buttom up +TEST(Merge_Sort_Buttom_Up, Simple) { + std::vector vec1{9, 8, 7, 6, 5, 4, 2, 3, 1, 0}; + ASSERT_EQ(MergeSortBottomUp(vec1), + (std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); + std::vector vec2{10, 90, 30, 80, 60, 50}; + ASSERT_EQ(MergeSortBottomUp(vec2), + (std::vector{10, 30, 50, 60, 80, 90})); + std::vector vec3{12, 43, 15, 26, -1233, 346, 1325, + -56, -12, 78, 0, 3345, -34}; + ASSERT_EQ(MergeSortBottomUp(vec3), + (std::vector{-1233, -56, -34, -12, 0, 12, 15, 26, 43, 78, 346, + 1325, 3345})); + vec3.push_back(-10); + vec3.push_back(1000); + vec3.push_back(5); + ASSERT_EQ(MergeSortBottomUp(vec3), + (std::vector{-1233, -56, -34, -12, -10, 0, 5, 12, 15, 26, 43, + 78, 346, 1000, 1325, 3345})); +} + +TEST(Merge_Sort_Buttom_Up, EmptyVector) { + std::vector vec; + ASSERT_EQ(MergeSortBottomUp(vec), (std::vector{})); +} + +TEST(Merge_Sort_Buttom_Up, SingleElement) { + std::vector vec{1}; + ASSERT_EQ(MergeSortBottomUp(vec), (std::vector{1})); +} + +TEST(Merge_Sort_Buttom_Up, RepeatedElements) { + std::vector vec{5, 5, 5, 5}; + ASSERT_EQ(MergeSortBottomUp(vec), (std::vector{5, 5, 5, 5})); +} + +TEST(Merge_Sort_Buttom_Up, MixedNumbers) { + std::vector vec{-1, 3, -2, 5, 4, -3}; + ASSERT_EQ(MergeSortBottomUp(vec), (std::vector{-3, -2, -1, 3, 4, 5})); +} + +TEST(Merge_Sort_Buttom_Up, AlreadySorted) { + std::vector vec{1, 2, 3, 4, 5}; + ASSERT_EQ(MergeSortBottomUp(vec), (std::vector{1, 2, 3, 4, 5})); +} + +TEST(Merge_Sort_Buttom_Up, ReverseOrder) { + std::vector vec{5, 4, 3, 2, 1}; + ASSERT_EQ(MergeSortBottomUp(vec), (std::vector{1, 2, 3, 4, 5})); +} + +TEST(Merge_Sort_Buttom_Up, ZerosAndNegatives) { + std::vector vec{0, -1, 0, -2, 0, -3}; + ASSERT_EQ(MergeSortBottomUp(vec), (std::vector{-3, -2, -1, 0, 0, 0})); +} + +TEST(Merge_Sort_Buttom_Up, LargeArray) { + std::vector vec(1000); + std::iota(vec.begin(), vec.end(), -500); + std::random_shuffle(vec.begin(), vec.end()); + std::vector sorted_vec(vec); + std::sort(sorted_vec.begin(), sorted_vec.end()); + ASSERT_EQ(MergeSortBottomUp(vec), sorted_vec); } diff --git a/task_06/src/find_order_statistic.cpp b/task_06/src/find_order_statistic.cpp new file mode 100644 index 00000000..48da9b47 --- /dev/null +++ b/task_06/src/find_order_statistic.cpp @@ -0,0 +1,42 @@ +#include "find_order_statistic.hpp" + +#include + +// what element has index k in sorted massive +int FindOrderStatistic(std::vector massive, int k) { + // empty massive + if (massive.size() == 0) { + return -1; + } + + // k out of range + if (k >= massive.size() or k < 0) { + return -1; + } + + if (massive.size() == 1) { + return massive[0]; + } + + int pivat = massive[0 + (rand() % (massive.size()))]; // random int from 0 to + // massive.size()-1 + std::vector smaller_part; + std::vector bigger_part; + for (int i = 0; i < massive.size(); i++) { + if (massive[i] < pivat) { + smaller_part.push_back(massive[i]); + } else { + bigger_part.push_back(massive[i]); + } + } + int middle_index = smaller_part.size(); + int answer; + if (k >= middle_index) { + answer = FindOrderStatistic(bigger_part, k - middle_index); + + } else if (k < middle_index) { + answer = FindOrderStatistic(smaller_part, k); + } + + return answer; +} \ No newline at end of file diff --git a/task_06/src/find_order_statistic.hpp b/task_06/src/find_order_statistic.hpp new file mode 100644 index 00000000..f13d55a3 --- /dev/null +++ b/task_06/src/find_order_statistic.hpp @@ -0,0 +1,4 @@ +#pragma once +#include + +int FindOrderStatistic(std::vector massive, int k); diff --git a/task_06/src/test.cpp b/task_06/src/test.cpp index 5e11617e..a6dbb341 100644 --- a/task_06/src/test.cpp +++ b/task_06/src/test.cpp @@ -1,6 +1,38 @@ #include +#include "find_order_statistic.hpp" + TEST(TopologySort, Simple) { ASSERT_EQ(1, 1); // Stack [] } + +TEST(k_ordinal_statistics, empty_array) { + std::vector vector1 = {}; + ASSERT_EQ(FindOrderStatistic(vector1, 0), -1); +} + +TEST(k_ordinal_statistics, wrong_n) { + std::vector vector1 = {1, 2, 3}; + ASSERT_EQ(FindOrderStatistic(vector1, 3), -1); +} + +TEST(k_ordinal_statistics, already_sorted) { + std::vector vector2 = {69, 228, 420, 1488}; + ASSERT_EQ(69, FindOrderStatistic(vector2, 0)); + ASSERT_EQ(420, FindOrderStatistic(vector2, 2)); + ASSERT_EQ(1488, FindOrderStatistic(vector2, 3)); +} + +TEST(k_ordinal_statistics, simple_1) { + std::vector vector3 = {45, 13, 5, 100, 120, 46, 10}; + ASSERT_EQ(46, FindOrderStatistic(vector3, 4)); + ASSERT_EQ(120, FindOrderStatistic(vector3, 6)); + ASSERT_EQ(5, FindOrderStatistic(vector3, 0)); +} + +TEST(k_ordinal_statistics, simple_2) { + std::vector vector4 = {24, 10, -1, -2, -3, -69, -420}; + ASSERT_EQ(-1, FindOrderStatistic(vector4, 4)); + ASSERT_EQ(-420, FindOrderStatistic(vector4, 0)); +} \ No newline at end of file diff --git a/task_07/src/avl_tree.cpp b/task_07/src/avl_tree.cpp new file mode 100644 index 00000000..0c7e3c31 --- /dev/null +++ b/task_07/src/avl_tree.cpp @@ -0,0 +1,104 @@ +#include "avl_tree.hpp"> + +#include + +AVLTree::~AVLTree() { Clear(root); } + +void AVLTree::Clear(TreeNode *node) { + if (node == nullptr) return; + Clear(node->left); + Clear(node->right); + delete node; +} + +int AVLTree::Height(TreeNode *node) const { return node ? node->height : 0; } + +int AVLTree::BalanceFactor(TreeNode *node) const { + return Height(node->left) - Height(node->right); +} + +void AVLTree::Update(TreeNode *node) { + if (node) + node->height = std::max(Height(node->left), Height(node->right)) + 1; +} + +TreeNode *AVLTree::RotateRight(TreeNode *old_node) { + TreeNode *new_node = old_node->left; + old_node->left = new_node->right; + new_node->right = old_node; + + Update(old_node); + Update(new_node); + + return new_node; +} + +TreeNode *AVLTree::RotateLeft(TreeNode *old_node) { + TreeNode *new_node = old_node->right; + old_node->right = new_node->left; + new_node->left = old_node; + + Update(old_node); + Update(new_node); + + return new_node; +} + +TreeNode *AVLTree::ReBalance(TreeNode *node) { + int balance = BalanceFactor(node); + if (balance > 1) { + if (BalanceFactor(node->left) < 0) node->left = RotateLeft(node); + return RotateRight(node); + } + if (balance < -1) { + if (BalanceFactor(node->right) > 0) node->right = RotateRight(node); + return RotateLeft(node); + } + return node; +} + +TreeNode *AVLTree::SearchMin(TreeNode *node) { + if (!node->left) return node; + return SearchMin(node->left); +} + +TreeNode *AVLTree::Insert(int value, TreeNode *&node) { + if (!node) return new TreeNode(value); + if (value < node->value) + node->left = Insert(value, node->left); + else if (value > node->value) + node->right = Insert(value, node->right); + else + return node; + Update(node); + return ReBalance(node); +} +bool AVLTree::Find(int value, const TreeNode *node) const { + if (!node) return false; + if (value < node->value) return Find(value, node->left); + if (value > node->value) return Find(value, node->right); + return true; +} + +TreeNode *AVLTree::Remove(int value, TreeNode *&node) { + if (!node) return nullptr; + if (value < node->value) + node->left = Remove(value, node->left); + else if (value > node->value) + node->right = Remove(value, node->right); + else { + if (!node->left) return node->right; + if (!node->right) return node->left; + TreeNode *min_node = SearchMin(node->right); + node->value = min_node->value; + node->right = Remove(min_node->value, node->right); + } + Update(node); + return ReBalance(node); +} + +void AVLTree::Insert(int value) { root = Insert(value, root); } + +void AVLTree::Remove(int value) { root = Remove(value, root); } + +bool AVLTree::Find(int value) const { return Find(value, root); } diff --git a/task_07/src/avl_tree.hpp b/task_07/src/avl_tree.hpp new file mode 100644 index 00000000..3376db13 --- /dev/null +++ b/task_07/src/avl_tree.hpp @@ -0,0 +1,48 @@ +#pragma once +struct TreeNode { + int value; + int height; + TreeNode *left; + TreeNode *right; + + explicit TreeNode(int value) + : value(value), left(nullptr), right(nullptr), height(1) {} +}; + +class AVLTree { + public: + AVLTree() : root(nullptr) {} + + ~AVLTree(); + + void Insert(int value); + + [[nodiscard]] bool Find(int value) const; + + void Remove(int value); + + private: + TreeNode *root; + + int Height(TreeNode *node) const; + + int BalanceFactor(TreeNode *node) const; + + void Update(TreeNode *node); + + TreeNode *RotateRight(TreeNode *old_node); + + TreeNode *RotateLeft(TreeNode *old_node); + + TreeNode *ReBalance(TreeNode *node); + + TreeNode *SearchMin(TreeNode *node); + + TreeNode *Insert(int value, TreeNode *&node); + + TreeNode *Remove(int value, TreeNode *&node); + + bool Find(int value, const TreeNode *node) const; + + void Clear(TreeNode *node); +}; \ No newline at end of file diff --git a/task_08/src/hash_table.cpp b/task_08/src/hash_table.cpp new file mode 100644 index 00000000..e83de8dc --- /dev/null +++ b/task_08/src/hash_table.cpp @@ -0,0 +1,102 @@ +#include "hash_table.hpp" + +#include + +#include +#include + +size_t HashTable::Size() { return size_; } + +size_t HashTable::Hash(int key) { + if constexpr (std::is_arithmetic::value) { + return floor(table_size_ * + ((key * hashCoefficient) - floor(key * hashCoefficient))); + } + throw std::invalid_argument( + "Hash table cannot cannot work with it with an arithmetic data type"); +} + +void HashTable::Clear() { + used_elements_ = 0; + size_ = 0; + for (auto &cell : elements_conditions_) { + cell = Condition::Empty; + } +} + +void HashTable::ReSize() { + table_size_ *= 2; + table_container_.resize(table_size_); + elements_conditions_.resize(table_size_); +} + +void HashTable::ReHash() { + std::vector used_elem; + for (int i = 0; i < table_size_; ++i) { + if (elements_conditions_[i] == Condition::Fill) { + used_elem.push_back(table_container_[i]); + } + } + + ReSize(); + Clear(); + + for (auto &elem : used_elem) { + Insert(elem); + } +} + +bool HashTable::Contains(int value) { + size_t hash = Hash(value) % table_size_; + int cnt_attemts = 0; + while (elements_conditions_[hash] != Condition::Empty) { + if (table_container_[hash] == value && + elements_conditions_[hash] == Condition::Fill) { + return true; + } + cnt_attemts++; + hash = (Hash(value) + cnt_attemts * Hash(value)) % table_size_; + } + return false; +} + +void HashTable::Insert(int value) { + size_t hash = Hash(value) % table_size_; + int cnt_attempts = 0; + while (elements_conditions_[hash] == Condition::Fill) { + if (table_container_[hash] == value) { + return; + } + cnt_attempts++; + hash = (Hash(value) + cnt_attempts * Hash(value)) % table_size_; + } + + table_container_[hash] = value; + elements_conditions_[hash] = Condition::Fill; + used_elements_++; + size_++; + + double used_cells_coefficient = double(used_elements_) / table_size_; + if (used_cells_coefficient >= rehashCoefficient) { + ReHash(); + } +} + +void HashTable::Remove(int value) { + size_t hash = Hash(value) % table_size_; + int cnt_attemts = 0; + while (elements_conditions_[hash] != Condition::Empty) { + if (table_container_[hash] == value && + elements_conditions_[hash] == Condition::Fill) { + elements_conditions_[hash] = Condition::Deleted; + size_--; + break; + } + if (table_container_[hash] == value && + elements_conditions_[hash] == Condition::Deleted) { + break; + } + cnt_attemts++; + hash = (Hash(value) + Hash(value) * cnt_attemts) % table_size_; + } +} diff --git a/task_08/src/hash_table.hpp b/task_08/src/hash_table.hpp new file mode 100644 index 00000000..8222bf8a --- /dev/null +++ b/task_08/src/hash_table.hpp @@ -0,0 +1,41 @@ +#pragma once +#include +#include + +class HashTable { + public: + HashTable() { + used_elements_ = 0; + size_ = 0; + table_size_ = 8; + table_container_ = std::vector(table_size_); + elements_conditions_ = + std::vector(table_size_, Condition::Empty); + } + + bool Contains(int value); + + void Insert(int value); + + void Remove(int value); + + void Clear(); + + size_t Size(); + + private: + enum class Condition { Fill, Deleted, Empty }; + constexpr static const double rehashCoefficient = 0.5; + constexpr static const double hashCoefficient = 0.618033989; + size_t table_size_; + size_t size_; + unsigned used_elements_; + std::vector table_container_; + std::vector elements_conditions_; + + size_t Hash(int key); + + void ReSize(); + + void ReHash(); +}; diff --git a/task_08/src/test.cpp b/task_08/src/test.cpp index 5e11617e..0a25a708 100644 --- a/task_08/src/test.cpp +++ b/task_08/src/test.cpp @@ -1,6 +1,66 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include +#include + +TEST(HashTableTest, ContainsElement) { + HashTable table; + table.Insert(5); + ASSERT_TRUE(table.Contains(5)); +} + +TEST(HashTableTest, InsertElement) { + HashTable table; + table.Insert(10); + ASSERT_TRUE(table.Contains(10)); +} + +TEST(HashTableTest, RemoveElement) { + HashTable table; + table.Insert(15); + table.Remove(15); + ASSERT_FALSE(table.Contains(15)); +} + +TEST(HashTableTest, ClearTable) { + HashTable table; + table.Insert(20); + table.Clear(); + ASSERT_EQ(table.Size(), 0); +} + +TEST(HashTableTest, SizeAfterInsertion) { + HashTable table; + table.Insert(25); + table.Insert(30); + ASSERT_EQ(table.Size(), 2); +} + +TEST(HashTableTest, ClearTableWithManyElements) { + HashTable table; + for (int i = 0; i < 100; ++i) { + table.Insert(i); + } + table.Clear(); + ASSERT_EQ(table.Size(), 0); +} + +TEST(HashTableTest, CollisionHandling) { + HashTable table; + table.Insert(5); + table.Insert(15); + ASSERT_TRUE(table.Contains(5)); + ASSERT_TRUE(table.Contains(15)); +} + +TEST(HashTableTest, SizeAfterRemoval) { + HashTable table; + for (int i = 0; i < 50; ++i) { + table.Insert(i); + } + for (int i = 0; i < 25; ++i) { + table.Remove(i); + } + table.Clear(); + ASSERT_EQ(table.Size(), 0); } diff --git a/task_09/src/change_mondey.cpp b/task_09/src/change_mondey.cpp new file mode 100644 index 00000000..b57aecfb --- /dev/null +++ b/task_09/src/change_mondey.cpp @@ -0,0 +1,18 @@ +#include + +#include "change_money.hpp" + +int CoinExchange(int sum, std::vector coins) { + std::vector money(sum + 1, 1e9); + money[0] = 0; + for (int m = 1; m <= sum; m++) { + for (auto coin : coins) { + if (coin <= m) { + money[m] = std::min(money[m], money[m - coin] + 1); + } + } + } + if (money[sum] == 1e9) return -1; + + return money[sum]; +} \ No newline at end of file diff --git a/task_09/src/change_money.hpp b/task_09/src/change_money.hpp new file mode 100644 index 00000000..ec7b644d --- /dev/null +++ b/task_09/src/change_money.hpp @@ -0,0 +1,4 @@ +#pragma once + +#include +int CoinExchange(int sum, std::vector coins); \ No newline at end of file diff --git a/task_09/src/test.cpp b/task_09/src/test.cpp index 869094dd..e4fd2a8d 100644 --- a/task_09/src/test.cpp +++ b/task_09/src/test.cpp @@ -1,4 +1,37 @@ - #include -TEST(TopologySort, Simple) { ASSERT_EQ(1, 1); } +#include "change_money.hpp" +TEST(ChangeCoinsTest, Simple) { + std::vector coins = {1, 2, 5}; + EXPECT_EQ(CoinExchange(11, coins), 3); +} + +TEST(ChangeCoinsTest, Impossible) { + std::vector coins = {2, 3}; + EXPECT_EQ(CoinExchange(1, coins), -1); +} + +TEST(ChangeCoinsTest, Zero) { + std::vector coins = {1, 2, 5}; + EXPECT_EQ(CoinExchange(0, coins), 0); +} + +TEST(ChangeCoinsTest, LargeSum) { + std::vector coins = {1, 2, 5, 10, 20, 50, 100}; + EXPECT_EQ(CoinExchange(12321377, coins), 123217); +} + +TEST(ChangeCoinsTest, SingleCoin) { + std::vector coins = {1}; + EXPECT_EQ(CoinExchange(5, coins), 5); +} + +TEST(ChangeCoinsTest, NoCoins) { + std::vector coins = {}; + EXPECT_EQ(CoinExchange(10, coins), -1); +} + +TEST(ChangeCoinsTest, LargeCoins) { + std::vector coins = {1, 2, 5, 10, 20, 50, 100, 200, 500, 1000}; + EXPECT_EQ(CoinExchange(1279, coins), 7); +} \ No newline at end of file diff --git a/task_sortings/CMakeLists.txt b/task_sortings/CMakeLists.txt new file mode 100644 index 00000000..0e239848 --- /dev/null +++ b/task_sortings/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.10) + +get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_LIST_DIR} NAME) +string(REPLACE " " "_" PROJECT_NAME ${PROJECT_NAME}) +project(${PROJECT_NAME} C CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +file(GLOB_RECURSE source_list "src/*.cpp" "src/*.hpp") +file(GLOB_RECURSE lib_source_list "../lib/src/*.cpp" "../lib/src/*.hpp") +file(GLOB_RECURSE main_source_list "src/main.cpp") +file(GLOB_RECURSE test_source_list "src/*.cpp") +file(GLOB_RECURSE test_list "src/*test.cpp") + +list(REMOVE_ITEM test_source_list ${main_source_list}) +list(REMOVE_ITEM source_list ${test_list}) + +include_directories(${PROJECT_NAME} PUBLIC src) +include_directories(${PROJECT_NAME} PUBLIC ../lib/src) + +add_executable(${PROJECT_NAME} ${source_list}) +target_link_libraries(${PROJECT_NAME} PUBLIC Utils) + +# Locate GTest +enable_testing() +find_package(GTest REQUIRED) +include_directories(${GTEST_INCLUDE_DIRS}) + +# Link runTests with what we want to test and the GTest and pthread library +add_executable(${PROJECT_NAME}_tests ${test_source_list}) +target_link_libraries( + ${PROJECT_NAME}_tests + GTest::gtest_main + Utils +) + +include(GoogleTest) +gtest_discover_tests(${PROJECT_NAME}_tests) diff --git a/task_sortings/README.md b/task_sortings/README.md new file mode 100644 index 00000000..e4c3faae --- /dev/null +++ b/task_sortings/README.md @@ -0,0 +1,3 @@ +# Сортировки + +Реализовать сортировок diff --git a/task_sortings/src/heap_sort.cpp b/task_sortings/src/heap_sort.cpp new file mode 100644 index 00000000..3391051a --- /dev/null +++ b/task_sortings/src/heap_sort.cpp @@ -0,0 +1,19 @@ +#include "heap_sort.hpp" + +#include + +std::vector HeapSort(std::vector massive) { + Heap heap; + + // put all elems into heap one by one + for (int i = 0; i < massive.size(); i++) { + heap.Insert(massive[i]); + } + + // push back with mins + for (int i = 0; i < massive.size(); i++) { + massive[i] = heap.PopMin(); + } + + return massive; +} \ No newline at end of file diff --git a/task_sortings/src/heap_sort.hpp b/task_sortings/src/heap_sort.hpp new file mode 100644 index 00000000..4ad0ba22 --- /dev/null +++ b/task_sortings/src/heap_sort.hpp @@ -0,0 +1,5 @@ +#pragma once + +#include "../../task_04/src/heap.hpp" + +std::vector HeapSort(std::vector massive); diff --git a/task_sortings/src/main.cpp b/task_sortings/src/main.cpp new file mode 100644 index 00000000..0e4393ba --- /dev/null +++ b/task_sortings/src/main.cpp @@ -0,0 +1,3 @@ +#include + +int main() { return 0; } diff --git a/task_sortings/src/quick_sort.cpp b/task_sortings/src/quick_sort.cpp new file mode 100644 index 00000000..f548b3ac --- /dev/null +++ b/task_sortings/src/quick_sort.cpp @@ -0,0 +1,38 @@ +#include "quick_sort.h" + +// O*(NlogN) (but upper limit is O(n^2) if pivat is always bad) +std::vector QuickSort(std::vector massive) { + int pivat_index = massive.size() / 2; + int pivat = massive[pivat_index]; + + std::vector smaller_part; + std::vector bigger_part; + + if (massive.size() > 1) { + for (int i = 0; i < massive.size(); i++) { + if (i != pivat_index) { + if (massive[i] <= pivat) { + smaller_part.push_back(massive[i]); + } else { + bigger_part.push_back(massive[i]); + } + } + } + } else { + return massive; + } + if (smaller_part.size() > 1) { + smaller_part = QuickSort(smaller_part); + } + + if (bigger_part.size() > 1) { + bigger_part = QuickSort(bigger_part); + } + + std::vector result = smaller_part; + result.push_back(pivat); + for (int i = 0; i < bigger_part.size(); i++) { + result.push_back(bigger_part[i]); + } + return result; +} \ No newline at end of file diff --git a/task_sortings/src/quick_sort.h b/task_sortings/src/quick_sort.h new file mode 100644 index 00000000..71465909 --- /dev/null +++ b/task_sortings/src/quick_sort.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +// O*(NlogN) (but upper limit is O(n^2) if pivat is bad) +std::vector QuickSort(std::vector massive); \ No newline at end of file diff --git a/task_sortings/src/test.cpp b/task_sortings/src/test.cpp new file mode 100644 index 00000000..c23c8b9b --- /dev/null +++ b/task_sortings/src/test.cpp @@ -0,0 +1,15 @@ + +#include + +#include "bogo_sort.h" +#include "bubble_sort.h" +#include "insertion_sort.h" +#include "merge_sort.h" +#include "quick_sort.h" +#include "selection_sort.h" + +// BogoSort tests +TEST(BogoSort, Simple) { + std::vector mas = {1}; + ASSERT_EQ({1}, {1}); +}