diff --git a/task_01/src/find_numbers.cpp b/task_01/src/find_numbers.cpp new file mode 100644 index 0000000..309c91a --- /dev/null +++ b/task_01/src/find_numbers.cpp @@ -0,0 +1,26 @@ +#include "find_numbers.hpp" + +std::vector FindNumberOfamount(std::vector vec, int summa) { + if (vec.empty()) { + throw std::runtime_error("Vector is empty"); + } + int start_iterator{0}; + int end_iterator{vec.size() - 1}; + std::vector result; + while (true) { + if (vec[start_iterator] + vec[end_iterator] == summa) { + result.push_back(vec[start_iterator]); + result.push_back(vec[end_iterator]); + return result; + } + if (vec[start_iterator] + vec[end_iterator] < summa) { + start_iterator++; + } + if (vec[start_iterator] + vec[end_iterator] > summa) { + end_iterator--; + } + if (start_iterator == end_iterator) { + throw std::runtime_error("Sum not found"); + } + } +} \ No newline at end of file diff --git a/task_01/src/find_numbers.hpp b/task_01/src/find_numbers.hpp new file mode 100644 index 0000000..c0b1ba8 --- /dev/null +++ b/task_01/src/find_numbers.hpp @@ -0,0 +1,9 @@ +#ifndef FIND_NUMBERS +#define FIND_NUMBERS + +#include +#include + +std::vector FindNumberOfamount(std::vector vec, int summa); + +#endif // FIND_NUMBERS \ No newline at end of file diff --git a/task_01/src/test.cpp b/task_01/src/test.cpp index 87cef73..8432c08 100644 --- a/task_01/src/test.cpp +++ b/task_01/src/test.cpp @@ -1,5 +1,30 @@ #include +#include -TEST(Test, Simple) { - ASSERT_EQ(1, 1); // Stack [] -} \ No newline at end of file +#include "find_numbers.hpp" + +TEST(FindNumberOfamountTest, SimpleCase) { + std::vector vec = {1, 2, 3, 4, 5}; + int summa = 8; + std::vector expected = {3, 5}; + ASSERT_EQ(FindNumberOfamount(vec, summa), expected); +} + +TEST(FindNumberOfamountTest, FirstAndLastElements) { + std::vector vec = {1, 2, 3, 4, 5}; + int summa = 6; + std::vector expected = {1, 5}; + ASSERT_EQ(FindNumberOfamount(vec, summa), expected); +} + +TEST(FindNumberOfamountTest, NoPairFound) { + std::vector vec = {1, 2, 3, 4, 5}; + int summa = 10; + EXPECT_THROW(FindNumberOfamount(vec, summa), std::runtime_error); +} + +TEST(FindNumberOfamountTest, EmptyVector) { + std::vector vec; + int summa = 5; + EXPECT_THROW(FindNumberOfamount(vec, summa), std::runtime_error); +} diff --git a/task_02/src/stack.cpp b/task_02/src/stack.cpp index 8ca8990..e69de29 100644 --- a/task_02/src/stack.cpp +++ b/task_02/src/stack.cpp @@ -1,21 +0,0 @@ -#include "stack.hpp" - -#include - -void Stack::Push(int value) { data_.push(value); } - -int Stack::Pop() { - auto result = data_.top(); - data_.pop(); - return result; -} - -void MinStack::Push(int value) { data_.push_back(value); } - -int MinStack::Pop() { - auto result = data_.back(); - data_.pop_back(); - return result; -} - -int MinStack::GetMin() { return *std::min_element(data_.begin(), data_.end()); } \ No newline at end of file diff --git a/task_02/src/stack.hpp b/task_02/src/stack.hpp index 138ec40..4486702 100644 --- a/task_02/src/stack.hpp +++ b/task_02/src/stack.hpp @@ -1,23 +1,73 @@ -#pragma once +#ifndef STACK_HPP +#define STACK_HPP -#include +#include #include +template class Stack { + private: + std::vector data; + public: - void Push(int value); - int Pop(); + void Push(T value) { data.push_back(value); } - private: - std::stack data_; + void Pop() { + if (IsEmpty()) { + throw std::runtime_error("Stack is empty"); + } + data.pop_back(); + } + + T Top() { + if (IsEmpty()) { + throw std::runtime_error("Stack is empty"); + } + return data.back(); + } + + bool IsEmpty() { return data.empty(); } }; +template class MinStack { + private: + std::vector stack; + std::vector minStack; + public: - void Push(int value); - int Pop(); - int GetMin(); + void Push(T value) { + stack.push_back(value); + if (minStack.empty() || value <= minStack.back()) { + minStack.push_back(value); + } + } - private: - std::vector data_; + void Pop() { + if (stack.empty()) { + throw std::runtime_error("Stack is empty"); + } + if (stack.back() == minStack.back()) { + minStack.pop_back(); + } + stack.pop_back(); + } + + T Top() { + if (stack.empty()) { + throw std::runtime_error("Stack is empty"); + } + return stack.back(); + } + + T FindMin() { + if (minStack.empty()) { + throw std::runtime_error("Stack is empty"); + } + return minStack.back(); + } + + bool IsEmpty() { return stack.empty(); } }; + +#endif // STACK_HPP \ No newline at end of file diff --git a/task_02/src/test.cpp b/task_02/src/test.cpp index 54e7ce9..a741e06 100644 --- a/task_02/src/test.cpp +++ b/task_02/src/test.cpp @@ -1,42 +1,62 @@ - #include -#include - #include "stack.hpp" -TEST(StackTest, Simple) { - Stack stack; - stack.Push(1); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] - stack.Push(1); // Stack [1] - stack.Push(2); // Stack [1, 2] - ASSERT_EQ(stack.Pop(), 2); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] - stack.Push(1); // Stack [1] - stack.Push(2); // Stack [1, 2] - ASSERT_EQ(stack.Pop(), 2); // Stack [1] - stack.Push(3); // Stack [1, 3] - ASSERT_EQ(stack.Pop(), 3); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] +TEST(StackTest, BasicOperations) { + Stack s; + s.Push(1); + s.Push(2); + ASSERT_EQ(s.Top(), 2); + s.Pop(); + ASSERT_EQ(s.Top(), 1); + s.Pop(); + ASSERT_TRUE(s.IsEmpty()); } -TEST(MinStackTest, Simple) { - MinStack stack; - stack.Push(1); // Stack [1] - ASSERT_EQ(stack.GetMin(), 1); - ASSERT_EQ(stack.Pop(), 1); // Stack [] - stack.Push(1); // Stack [1] - stack.Push(2); // Stack [1, 2] - ASSERT_EQ(stack.GetMin(), 1); - ASSERT_EQ(stack.Pop(), 2); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] - stack.Push(1); // Stack [1] - stack.Push(2); // Stack [1, 2] - ASSERT_EQ(stack.GetMin(), 1); - ASSERT_EQ(stack.Pop(), 2); // Stack [1] - stack.Push(3); // Stack [1, 3] - ASSERT_EQ(stack.GetMin(), 1); - ASSERT_EQ(stack.Pop(), 3); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] +TEST(StackTest, EmptyStack) { + MinStack s; + EXPECT_TRUE(s.IsEmpty()); + EXPECT_THROW(s.Top(), std::runtime_error); + EXPECT_THROW(s.Pop(), std::runtime_error); +} + +TEST(MinStackTest, BasicOperations) { + MinStack s; + s.Push(3); + s.Push(5); + ASSERT_EQ(s.FindMin(), 3); + s.Push(2); + ASSERT_EQ(s.FindMin(), 2); + s.Pop(); + ASSERT_EQ(s.FindMin(), 3); +} + +TEST(MinStackTest, DuplicateMins) { + MinStack s; + s.Push(2); + s.Push(2); + ASSERT_EQ(s.FindMin(), 2); + s.Pop(); + ASSERT_EQ(s.FindMin(), 2); + s.Pop(); + EXPECT_THROW(s.FindMin(), std::runtime_error); +} + +TEST(MinStackTest, ComplexSequence) { + MinStack s; + s.Push(5); + s.Push(3); + s.Push(7); + s.Push(1); + s.Push(2); + + ASSERT_EQ(s.FindMin(), 1); + s.Pop(); + ASSERT_EQ(s.FindMin(), 1); + s.Pop(); + ASSERT_EQ(s.FindMin(), 3); + s.Pop(); + ASSERT_EQ(s.FindMin(), 3); + s.Pop(); + ASSERT_EQ(s.FindMin(), 5); } \ No newline at end of file diff --git a/task_03/src/find_days_to_warm.cpp b/task_03/src/find_days_to_warm.cpp new file mode 100644 index 0000000..60c64ef --- /dev/null +++ b/task_03/src/find_days_to_warm.cpp @@ -0,0 +1,37 @@ +#include "find_days_to_warm.hpp" + +#include +#include +#include +#include + +std::vector DaysToWarming(std::vector temperature_list) { + if (temperature_list.size() == 0) { + return std::vector{}; + } + + std::vector days_to_warming; + std::stack> decreasing_stack; + + int last_index{temperature_list.size() - 1}; + + decreasing_stack.push( + std::pair(temperature_list[last_index], last_index)); + for (int i{last_index}; i >= 0; i--) { + while (!decreasing_stack.empty() && + temperature_list[i] >= decreasing_stack.top().first) { + decreasing_stack.pop(); + } + if (decreasing_stack.empty()) { + days_to_warming.push_back(0); + decreasing_stack.push(std::pair(temperature_list[i], i)); + } else { + int previous_index = decreasing_stack.top().second; + decreasing_stack.push(std::pair(temperature_list[i], i)); + int current_index = decreasing_stack.top().second; + days_to_warming.push_back(previous_index - current_index); + } + } + std::reverse(days_to_warming.begin(), days_to_warming.end()); + return days_to_warming; +} \ No newline at end of file diff --git a/task_03/src/find_days_to_warm.hpp b/task_03/src/find_days_to_warm.hpp new file mode 100644 index 0000000..06bce77 --- /dev/null +++ b/task_03/src/find_days_to_warm.hpp @@ -0,0 +1,8 @@ +#ifndef TASK3_HPP +#define TASK3_HPP + +#include + +std::vector DaysToWarming(std::vector temperature_list); + +#endif // TASK3_HPP \ No newline at end of file diff --git a/task_03/src/test.cpp b/task_03/src/test.cpp index ef5a86a..9d6b603 100644 --- a/task_03/src/test.cpp +++ b/task_03/src/test.cpp @@ -1,8 +1,41 @@ - #include -#include "topology_sort.hpp" +#include + +#include "find_days_to_warm.hpp" + +TEST(DaysToWarmingTest, NormalCase) { + std::vector input = {73, 74, 75, 71, 69, 72, 76, 73}; + std::vector expected = {1, 1, 4, 2, 1, 1, 0, 0}; + EXPECT_EQ(DaysToWarming(input), expected); +} + +TEST(DaysToWarmingTest, NeverWarmer) { + std::vector input = {5, 4, 3, 2, 1}; + std::vector expected = {0, 0, 0, 0, 0}; + EXPECT_EQ(DaysToWarming(input), expected); +} -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(DaysToWarmingTest, AlwaysWarmer) { + std::vector input = {1, 2, 3, 4, 5}; + std::vector expected = {1, 1, 1, 1, 0}; + EXPECT_EQ(DaysToWarming(input), expected); } + +TEST(DaysToWarmingTest, SameTemperatures) { + std::vector input = {10, 10, 10, 10}; + std::vector expected = {0, 0, 0, 0}; + EXPECT_EQ(DaysToWarming(input), expected); +} + +TEST(DaysToWarmingTest, SingleDay) { + std::vector input = {15}; + std::vector expected = {0}; + EXPECT_EQ(DaysToWarming(input), expected); +} + +TEST(DaysToWarmingTest, EmptyInput) { + std::vector input = {}; + std::vector expected = {}; + EXPECT_EQ(DaysToWarming(input), expected); +} \ No newline at end of file diff --git a/task_03/src/topology_sort.cpp b/task_03/src/topology_sort.cpp deleted file mode 100644 index e53f670..0000000 --- a/task_03/src/topology_sort.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "topology_sort.hpp" diff --git a/task_03/src/topology_sort.hpp b/task_03/src/topology_sort.hpp deleted file mode 100644 index 6f70f09..0000000 --- a/task_03/src/topology_sort.hpp +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/task_04/src/task4.cpp b/task_04/src/task4.cpp new file mode 100644 index 0000000..e3866ea --- /dev/null +++ b/task_04/src/task4.cpp @@ -0,0 +1,23 @@ +#include "task4.hpp" + +std::vector BuyFish(std::vector price_list, int period) { + if (price_list.size() == 0) { + return {}; + } + std::priority_queue, std::vector>, + std::greater>> + fish_heap; + + std::vector fish_in_days(price_list.size(), 0); + + for (int day{0}; day < price_list.size(); ++day) { + fish_heap.push(std::pair(price_list[day], day)); + + while (!fish_heap.empty() && fish_heap.top().second + period <= day) { + fish_heap.pop(); + } + auto [best_price, best_day] = fish_heap.top(); + fish_in_days[best_day]++; + } + return fish_in_days; +} \ No newline at end of file diff --git a/task_04/src/task4.hpp b/task_04/src/task4.hpp new file mode 100644 index 0000000..ee9b891 --- /dev/null +++ b/task_04/src/task4.hpp @@ -0,0 +1,10 @@ +#ifndef TASK4_HPP +#define TASK4_HPP + +#include +#include +#include + +std::vector BuyFish(std::vector price_list, int period); + +#endif // TASK4_HPP \ No newline at end of file diff --git a/task_04/src/test.cpp b/task_04/src/test.cpp index 5e11617..7497756 100644 --- a/task_04/src/test.cpp +++ b/task_04/src/test.cpp @@ -1,6 +1,38 @@ - #include +#include "task4.hpp" + +#include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(BuyFishTest, EmptyList) { + std::vector empty; + auto result = BuyFish(empty, 3); + EXPECT_TRUE(result.empty()); } + +TEST(BuyFishTest, SingleDay) { + std::vector prices = {5}; + std::vector expected = {1}; + auto result = BuyFish(prices, 2); + EXPECT_EQ(result, expected); +} + +TEST(BuyFishTest, AllSamePrices) { + std::vector prices = {2, 2, 2, 2}; + std::vector expected = {2, 1, 1, 0}; + auto result = BuyFish(prices, 2); + EXPECT_EQ(result, expected); +} + +TEST(BuyFishTest, DecreasingPrices) { + std::vector prices = {5, 4, 3, 2, 1}; + std::vector expected = {1, 1, 1, 1, 1}; + auto result = BuyFish(prices, 2); + EXPECT_EQ(result, expected); +} + +TEST(BuyFishTest, YourCase) { + std::vector prices = {3, 2, 5, 4, 5, 3, 2}; + std::vector expected = {1, 3, 0, 1, 0, 1, 1}; + auto result = BuyFish(prices, 3); + EXPECT_EQ(result, expected); +} \ No newline at end of file diff --git a/task_05/src/heap.hpp b/task_05/src/heap.hpp new file mode 100644 index 0000000..fe7f520 --- /dev/null +++ b/task_05/src/heap.hpp @@ -0,0 +1,103 @@ +#ifndef HEAP_HPP +#define HEAP_HPP + +#include +#include + +template +class Heap { + public: + Heap(std::vector list) { + for (auto c : list) { + AppendElement(c); + } + } + std::vector ReturnTree() { return tree; } + T PopMin(); + void AppendElement(T element); + + private: + std::vector tree; + + void SiftUp(); + void SiftDown(); + + int parent_index(int index_of_element) { return (index_of_element - 1) / 2; } + int left_child_index(int index_of_element) { + return 2 * index_of_element + 1; + } + int right_child_index(int index_of_element) { + return 2 * index_of_element + 2; + } +}; + +template +T Heap::PopMin() { + if (tree.empty()) { + throw std::runtime_error("heap is empty"); + } + T min_elem = tree[0]; + SiftDown(); + return min_elem; +} + +template +void Heap::AppendElement(T element) { + tree.push_back(element); + SiftUp(); +} + +template +void Heap::SiftUp() { + int index = tree.size() - 1; + while (index != 0) { + int p_ind = parent_index(index); + if (tree[p_ind] > tree[index]) { + T bufer = tree[index]; + tree[index] = tree[p_ind]; + tree[p_ind] = bufer; + } + index = p_ind; + } +} + +template +void Heap::SiftDown() { + if (tree.empty()) return; + tree[0] = tree.back(); + tree.pop_back(); + int index{0}; + while (left_child_index(index) < + tree.size()) // существует хотя бы 1 потомок. Если левого потомка нет, + // то и правого тоже быть не может + { + int l_c_ind = left_child_index(index); + int r_c_ind = right_child_index(index); + if (r_c_ind >= tree.size()) // проверка на существование правого потомка + { + if (tree[l_c_ind] < tree[index]) { + std::swap(tree[index], tree[l_c_ind]); + index = l_c_ind; + continue; + } + break; + } + int ind_of_min_elem = tree[l_c_ind] < tree[r_c_ind] ? l_c_ind : r_c_ind; + if (tree[index] > tree[ind_of_min_elem]) { + std::swap(tree[index], tree[ind_of_min_elem]); + } + index = ind_of_min_elem; + } +} + +template +std::vector HeapSort(std::vector list) { + std::vector return_vector; + Heap heap = Heap(list); + while (return_vector.size() != list.size()) { + return_vector.push_back(heap.PopMin()); + } + return return_vector; +} + +#endif // HEAP_HPP \ No newline at end of file diff --git a/task_05/src/test.cpp b/task_05/src/test.cpp index 5e11617..7c6b920 100644 --- a/task_05/src/test.cpp +++ b/task_05/src/test.cpp @@ -1,6 +1,21 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include + +#include "heap.hpp" + +TEST(HeapSortTest, SortsIntegersCorrectly) { + std::vector input = {5, 2, 9, 1, 5, 6}; + std::vector expected = {1, 2, 5, 5, 6, 9}; + std::vector result = HeapSort(input); + + EXPECT_EQ(result, expected); + EXPECT_TRUE(std::is_sorted(result.begin(), result.end())); } + +TEST(HeapSortTest, HandlesEmptyVector) { + std::vector input = {}; + std::vector result = HeapSort(input); + + EXPECT_TRUE(result.empty()); +} \ No newline at end of file diff --git a/task_06/src/task6.cpp b/task_06/src/task6.cpp new file mode 100644 index 0000000..942cc4d --- /dev/null +++ b/task_06/src/task6.cpp @@ -0,0 +1 @@ +#include"task6.hpp" diff --git a/task_06/src/task6.hpp b/task_06/src/task6.hpp new file mode 100644 index 0000000..a061bf4 --- /dev/null +++ b/task_06/src/task6.hpp @@ -0,0 +1,29 @@ +#ifndef TASK6_HPP +#define TASK6_HPP + +#include + +int SearchNstat(std::vector vec, int N) +{ + int pivot{vec.back()}; + std::vector left_arr; + std::vector right_arr; + for (int i{0}; i < vec.size()-1; ++i){ + if (vec[i] <= pivot){ + left_arr.push_back(vec[i]); + } else { + right_arr.push_back(vec[i]); + } + } + int pivot_index{left_arr.size()}; + if (pivot_index == N){ + return pivot; + } + if (pivot_index > N){ + return SearchNstat(left_arr, N); + } else { + return SearchNstat(right_arr, N - pivot_index - 1); + } +} + +#endif // TASK6_HPP \ No newline at end of file diff --git a/task_06/src/test.cpp b/task_06/src/test.cpp index 5e11617..66e1ae5 100644 --- a/task_06/src/test.cpp +++ b/task_06/src/test.cpp @@ -1,6 +1,44 @@ - #include +#include "task6.hpp" + +#include + +TEST(SearchNstatTest, SingleElement) { + std::vector vec = {5}; + EXPECT_EQ(SearchNstat(vec, 0), 5); +} + +TEST(SearchNstatTest, AllSameElements) { + std::vector vec = {2, 2, 2, 2}; + EXPECT_EQ(SearchNstat(vec, 2), 2); +} + +TEST(SearchNstatTest, SortedArray) { + std::vector vec = {1, 2, 3, 4, 5}; + EXPECT_EQ(SearchNstat(vec, 2), 3); +} -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(SearchNstatTest, ReverseSortedArray) { + std::vector vec = {5, 4, 3, 2, 1}; + EXPECT_EQ(SearchNstat(vec, 1), 2); } + +TEST(SearchNstatTest, RandomArray) { + std::vector vec = {3, 1, 4, 1, 5, 9, 2, 6}; + EXPECT_EQ(SearchNstat(vec, 3), 3); +} + +TEST(SearchNstatTest, PivotIsNth) { + std::vector vec = {3, 1, 4, 2, 5}; + EXPECT_EQ(SearchNstat(vec, 3), 4); +} + +TEST(SearchNstatTest, AllGreaterThanPivot) { + std::vector vec = {6, 7, 8, 5}; + EXPECT_EQ(SearchNstat(vec, 3), 8); +} + +TEST(SearchNstatTest, AllLessThanPivot) { + std::vector vec = {1, 2, 3, 5}; + EXPECT_EQ(SearchNstat(vec, 2), 3); +} \ No newline at end of file diff --git a/task_07/src/splay.hpp b/task_07/src/splay.hpp new file mode 100644 index 0000000..63e9b9b --- /dev/null +++ b/task_07/src/splay.hpp @@ -0,0 +1,327 @@ +#ifndef SP_TREE_HPP +#define SP_TREE_HPP + +#include +#include +#include +#include +#include + +template +struct Node { + K key; + V value; + Node *left_child{nullptr}; + Node *right_child{nullptr}; + Node *parent{nullptr}; + + Node(const K &key_, const V &value_, Node *left = nullptr, + Node *right = nullptr, Node *parent = nullptr) + : key(key_), + value(value_), + left_child(left), + right_child(right), + parent(parent) { + if (left_child) { + left_child->parent = this; + } + if (right_child) { + right_child->parent = this; + } + } + + ~Node() { + delete left_child; + delete right_child; + } + + bool operator==(const Node &other) const { + return (left_child == other.left_child) && + (right_child == other.right_child) && (parent == other.parent) && + (key == other.key); + } +}; + +template +class SplayTree { + public: + std::vector tree_vector(Node *x); + Node *getRoot() const { return root; } + void PrintTree(); + + void Splay(Node *node); + + V Search(K key_); + Node *maximum(); + bool Contains(const K &key); + bool IsEmpty() { return root == nullptr; } + + void Insert(Node *another); + void Remove(Node *x); + + void Merge(SplayTree *another_tree); + + SplayTree() : root(nullptr) {} + SplayTree(Node *root_) : root(root_) {} + ~SplayTree() { delete root; } + + private: + Node *root; + + void zig(Node *x); + void left_zig(Node *x); + void right_zig(Node *x); + + void zig_zig(Node *x); + void zig_zag(Node *x); +}; + +template +void SplayTree::right_zig(Node *x) { + if (x->parent == nullptr) { + throw std::runtime_error("Нет родителя, zig невозможен"); + } + Node *parent = x->parent; + Node *parent_of_parent = parent->parent; + + parent->left_child = x->right_child; + if (parent->left_child != nullptr) { + parent->left_child->parent = parent; + } + parent->parent = (x); + x->right_child = parent; + x->parent = parent_of_parent; + if (parent_of_parent != nullptr) { + if (parent_of_parent->left_child == parent) { + parent_of_parent->left_child = x; + } else { + parent_of_parent->right_child = x; + } + } + if (parent_of_parent == nullptr) { + root = x; + } +} + +template +void SplayTree::left_zig(Node *x) { + if (x->parent == nullptr) { + throw std::runtime_error("Нет родителя, zig невозможен"); + } + Node *parent = x->parent; + Node *parent_of_parent = parent->parent; + + parent->right_child = x->left_child; + if (parent->right_child != nullptr) { + parent->right_child->parent = parent; + } + parent->parent = x; + x->left_child = parent; + x->parent = parent_of_parent; + if (parent_of_parent != nullptr) { + if (parent_of_parent->left_child == parent) { + parent_of_parent->left_child = x; + } else { + parent_of_parent->right_child = x; + } + } + if (parent_of_parent == nullptr) { + root = x; + } +} + +template +void SplayTree::zig(Node *x) { + if (x->parent->left_child == x) { + right_zig(x); + } else { + left_zig(x); + } +} + +template +void SplayTree::zig_zig(Node *x) { + Node *parent = x->parent; + Node *parent_of_parent = parent->parent; + if (x == nullptr || x->parent == nullptr || x->parent->parent == nullptr) { + return; // Нельзя выполнить zig_zig, если нет родителя или дедушки + } + zig(x); + zig(x); +} + +template +void SplayTree::zig_zag(Node *x) { + Node *parent = x->parent; + Node *parent_of_parent = parent->parent; + if (x == nullptr || x->parent == nullptr || x->parent->parent == nullptr) { + return; // Нельзя выполнить zig_zag, если нет родителя или дедушки + } + zig(x); + zig(x); +} + +template +void SplayTree::Splay(Node *x) { + while (x->parent != nullptr) { + Node *parent = x->parent; + Node *parent_of_parent = parent->parent; + if (parent_of_parent == nullptr) { + zig(x); + return; + } + if ((parent_of_parent->left_child == parent && parent->left_child == x) || + (parent_of_parent->right_child == parent && parent->right_child == x)) { + zig_zig(x); + } + if ((parent_of_parent->left_child == parent && parent->right_child == x) || + (parent_of_parent->right_child == parent && parent->left_child == x)) { + zig_zag(x); + } + } +} + +template +V SplayTree::Search(K key_) { + Node *x = root; + while (x != nullptr) { + if (x->key == key_) { + Splay(x); + return x->value; + } + if (key_ < x->key) { + x = x->left_child; + } else { + x = x->right_child; + } + } + throw std::runtime_error("This object wasn't found"); +} + +template +bool SplayTree::Contains(const K &key) { + try { + Search(key); + } catch (const std::runtime_error &error) { + return false; + } + return true; +} + +template +Node *SplayTree::maximum() { + Node *max = root; + while (max->right_child != nullptr) { + max = max->right_child; + } + return max; +} + +template +void SplayTree::Insert(Node *another) { + if (root == nullptr) { + root = another; + return; + } + Node *t = root; + Node *parent = nullptr; + while (t != nullptr) { + parent = t; + if (another->key < t->key) { + t = t->left_child; + } else { + t = t->right_child; + } + } + another->parent = parent; + if (another->key < parent->key) { + parent->left_child = another; + } else { + parent->right_child = another; + } + + Splay(another); +} + +template +void SplayTree::Merge(SplayTree *another_tree) { + /*Для слияния деревьев T1 и T2, в которых все ключи T1 меньше ключей в T2, + делаем Splay для максимального элемента T1, + тогда у корня T1 не будет правого ребенка. + После этого делаем T2 правым ребенком T1.*/ + if (another_tree == nullptr) { + return; + } + if (root == nullptr) { + root = another_tree->root; + if (root != nullptr) { + root->parent = nullptr; + } + another_tree->root = nullptr; + delete another_tree; + return; + } + Node *max = maximum(); + Splay(max); + Node *another_root = another_tree->getRoot(); + if (another_root != nullptr) { + max->right_child = another_root; + another_root->parent = max; + } + another_tree->root = nullptr; + delete another_tree; +} + +template +void SplayTree::Remove(Node *x) { + if (x == nullptr || !Contains(x->key)) { + return; + } + Splay(x); + SplayTree *another_tree = new SplayTree(x->right_child); + root = x->left_child; + if (another_tree->getRoot()->parent != nullptr) { + another_tree->getRoot()->parent = nullptr; + } + if (root != nullptr) { + root->parent = nullptr; + } + Merge(another_tree); +} + +template +std::vector SplayTree::tree_vector(Node *x) { + /*BFS (обход в ширину) + по факту возвращает дерево по слоям, начиная с вершины x*/ + std::vector tree_vector; + if (root == nullptr) { + return tree_vector; + } + std::queue *> q; + q.push(root); + int level{0}; + while (!q.empty()) { + Node *current = q.front(); + q.pop(); + tree_vector.push_back(current->key); + if (current->left_child != nullptr) { + q.push(current->left_child); + } + + if (current->right_child != nullptr) { + q.push(current->right_child); + } + } + return tree_vector; +} + +template +void SplayTree::PrintTree() { + /*выводит всё дерево по слоям*/ + std::vector vector = tree_vector(root); + for (auto c : vector) { + std::cout << c << " "; + } +} + +#endif // SP_TREE_HPP \ No newline at end of file diff --git a/task_07/src/test.cpp b/task_07/src/test.cpp index 5e11617..52b2cd8 100644 --- a/task_07/src/test.cpp +++ b/task_07/src/test.cpp @@ -1,6 +1,99 @@ - #include +#include "splay.hpp" +#include + +TEST(SplayTreeTest, AllOperations) { + // само дерево 9 5 11 3 7 6 8 (по уровням) + Node *A = new Node(3, 52); + Node *B = new Node(6, 6666); + Node *C = new Node(8, 8852); + Node *D = new Node(11, 1171); + Node *X = new Node(7, 7732, B, C); + Node *P = new Node(5, 555, A, X); + Node *G = new Node(9, 999, P, D); + SplayTree Tr(G); + + // тесты на сплей + Tr.Splay(P); + std::vector tree_after_1sp = Tr.tree_vector(P); + std::vector expect_list1 = {5, 3, 9, 7, 11, 6, 8}; + EXPECT_EQ(tree_after_1sp, expect_list1); + + Tr.Splay(X); + std::vector tree_after_2sp = Tr.tree_vector(P); + std::vector expect_list2 = {7, 5, 9, 3, 6, 8, 11}; + EXPECT_EQ(tree_after_2sp, expect_list2); + + // наше дерево выглядит так: 7 5 9 3 6 8 11 + /* + 7 + / \ + 5 9 + / \ / \ + 3 6 8 11 + */ + + // тестик на поиск(даём ключ, получаем значение) + int val1 = Tr.Search(3); + EXPECT_EQ(val1, 52); + int val2 = Tr.Search(5); + EXPECT_EQ(val2, 555); + int val3 = Tr.Search(9); + EXPECT_EQ(val3, 999); + std::vector expected_after_search_test = {9, 5, 11, 3, 7, 6, 8}; + std::vector tree_after_search_test = Tr.tree_vector(Tr.getRoot()); + EXPECT_EQ(expected_after_search_test, tree_after_search_test); -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] + // наше дерево выглядит так: 9 5 11 3 7 6 8 + /* + 9 + / \ + 5 11 + / \ + 3 7 + / \ + 6 8 + */ + + // тестик на максимум + int max = Tr.maximum()->key; + EXPECT_EQ(max, 11); + + // тестик на удаление(одновременно и merge проверили) + Tr.Remove(X); + std::vector expected_tree_after_remove = {6, 5, 9, 3, 8, 11}; + std::vector tree_after_remove = Tr.tree_vector(Tr.getRoot()); + EXPECT_EQ(expected_tree_after_remove, tree_after_remove); + + // наше дерево выглядит так: 6 5 9 3 8 11 + /* + 6 + / \ + 5 9 + / / \ + 3 8 11 + */ + + // тестик на вставку + Node *I = new Node(4, 45444); + Tr.Insert(I); + std::vector expected_tree_after_insert = {4, 3, 6, 5, 9, 8, 11}; + std::vector tree_after_insert = Tr.tree_vector(Tr.getRoot()); + EXPECT_EQ(expected_tree_after_insert, tree_after_insert); + + // наше дерево выглядит так: 4 3 6 5 9 8 11 + /* + 4 + / \ + 3 6 + / \ + 5 9 + / \ + 8 11 + */ } + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/task_08/src/hash_table.hpp b/task_08/src/hash_table.hpp new file mode 100644 index 0000000..13abc81 --- /dev/null +++ b/task_08/src/hash_table.hpp @@ -0,0 +1,124 @@ +#ifndef HASH_TABLE_HPP +#define HASH_TABLE_HPP + +#include +#include +#include +#include + +template +struct Node { + K key; + V value; + Node(K key_, V value_ = V{}) : key(key_), value(value_) {} +}; + +template +class HashTable { + public: + HashTable() : hash_vector(10) {}; + V& Search(K key); + bool Contains(K key); + void AddElement(K key, V value); + void DelElement(K key); + V& operator[](const K& key); + + void Print() const; + + private: + std::vector>> hash_vector; + void ReHashVector(); + int number_of_elemnts{0}; +}; + +template +bool HashTable::Contains(K key) { + int hash = std::hash{}(key); + int index = hash % hash_vector.size(); + for (auto node : hash_vector[index]) { + if (node.key == key) { + return true; + } + } + return false; +} + +template +void HashTable::ReHashVector() { + int new_size = hash_vector.size() * 2; + std::vector>> buf_vec = hash_vector; + hash_vector = std::vector>>(new_size); + for (int i{0}; i < buf_vec.size(); ++i) { + for (auto element : buf_vec[i]) { + int hash = std::hash{}(element.key); + int index = hash % hash_vector.size(); + hash_vector[index].push_back(element); + } + } +} + +template +void HashTable::AddElement(K key, V value) { + number_of_elemnts++; + int half_of_size_h_vec = static_cast(hash_vector.size() / 2); + if (number_of_elemnts > half_of_size_h_vec) { + ReHashVector(); + } + int hash = std::hash{}(key); + int index = hash % hash_vector.size(); + hash_vector[index].push_back(Node(key, value)); +} + +template +void HashTable::DelElement(K key) { + int hash = std::hash{}(key); + int index = hash % hash_vector.size(); + if (Contains(key)) { + std::vector> buf_vector; + for (auto node : hash_vector[index]) { + if (node.key != key) { + buf_vector.push_back(node); + } + } + hash_vector[index] = buf_vector; + return; + } + throw std::runtime_error("Can't find this element"); +} + +template +V& HashTable::Search(K key) { + int hash = std::hash{}(key); + int index = hash % hash_vector.size(); + for (auto& node : hash_vector[index]) { + if (node.key == key) { + return node.value; + } + } + throw std::runtime_error("Can't find this element"); +} + +template +V& HashTable::operator[](const K& key) { + if (Contains(key)) { + return Search(key); + } else { + AddElement(key, V{}); + return Search(key); + } +} + +template +void HashTable::Print() const { + std::cout << "HashTable contents:\n"; + for (size_t i = 0; i < hash_vector.size(); ++i) { + std::cout << "Vector" << i << ": "; + for (const auto& node : hash_vector[i]) { + std::cout << "[" << node.key << " -> " << node.value << "] "; + } + std::cout << "\n"; + } + std::cout << "--------------------------\n"; +} + +#endif // HASH_TABLE_HPP \ No newline at end of file diff --git a/task_08/src/test.cpp b/task_08/src/test.cpp index 5e11617..c1f86e9 100644 --- a/task_08/src/test.cpp +++ b/task_08/src/test.cpp @@ -1,6 +1,49 @@ - +#include "hash_table.hpp" #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(HashTableTests, AddElementAndContains) { + HashTable ht; + ht.AddElement(1, "one"); + + EXPECT_TRUE(ht.Contains(1)); + EXPECT_FALSE(ht.Contains(2)); +} + +TEST(HashTableTests, SearchOperation) { + HashTable ht; + ht.AddElement(1, "one"); + + EXPECT_EQ(ht.Search(1), "one"); + EXPECT_THROW(ht.Search(2), std::runtime_error); +} + +TEST(HashTableTests, DelElementOperation) { + HashTable ht; + ht.AddElement(1, "one"); + + ht.DelElement(1); + EXPECT_FALSE(ht.Contains(1)); + EXPECT_THROW(ht.DelElement(1), std::runtime_error); +} + +TEST(HashTableTests, SubscriptOperator) { + HashTable ht; + + ht[3] = "three"; + EXPECT_EQ(ht[3], "three"); } + +TEST(HashTableTests, RehashOperation) { + HashTable ht; + + // Добавляем элементы для проверки rehash + for (int i = 0; i < 12; ++i) { + ht.AddElement(i*i+i, std::to_string(i*i+i)); + } + + // Проверяем доступность элементов + for (int i = 0; i < 12; ++i) { + EXPECT_TRUE(ht.Contains(i*i+i)); + EXPECT_EQ(ht.Search(i*i+i), std::to_string(i*i+i)); + } +} \ No newline at end of file diff --git a/task_09/src/task9.hpp b/task_09/src/task9.hpp new file mode 100644 index 0000000..81387df --- /dev/null +++ b/task_09/src/task9.hpp @@ -0,0 +1,47 @@ +#ifndef TASK9_HPP +#define TASK9_HPP + +#include +#include +#include + +std::vector PreprocessMaxReach(std::vector>& a) { + int n = a.size(); + int m = a[0].size(); + + std::vector> max_reach_col(m, std::vector(n)); + for (int j = 0; j < m; ++j) { + max_reach_col[j][n - 1] = n - 1; + for (int i = n - 2; i >= 0; --i) { + if (a[i][j] <= a[i + 1][j]) { + max_reach_col[j][i] = max_reach_col[j][i + 1]; + } else { + max_reach_col[j][i] = i; + } + } + } + + std::vector max_reach_for_row(n); + for (int i = 0; i < n; ++i) { + max_reach_for_row[i] = i; + for (int j = 0; j < m; ++j) { + if (max_reach_col[j][i] > max_reach_for_row[i]) { + max_reach_for_row[i] = max_reach_col[j][i]; + } + } + } + + for (int i = 1; i < n; ++i) { + if (max_reach_for_row[i] < max_reach_for_row[i - 1]) { + max_reach_for_row[i] = max_reach_for_row[i - 1]; + } + } + + return max_reach_for_row; +} + +bool CheckRangeSorted(const std::vector& max_reach_for_row, int l, int r) { + return max_reach_for_row[l] >= r; +} + +#endif // TASK9_HPP \ No newline at end of file diff --git a/task_09/src/test.cpp b/task_09/src/test.cpp index a42caa4..01f2e43 100644 --- a/task_09/src/test.cpp +++ b/task_09/src/test.cpp @@ -1,23 +1,18 @@ #include - +#include "task9.hpp" #include -TEST(CanReachNonDecreasingSegment, 1) { - // ASSERT_EQ(SolveFunction(5, 4, 6, - // std::vector>{{1, 2, 3, 5}, - // {3, 1, 3, 2}, - // {4, 5, 2, 3}, - // {5, 5, 3, 2}, - // {4, 4, 3, 4}}, - // std::vector>{ - // {1, 1}, {2, 5}, {4, 5}, {3, 5}, {1, 3}, {1, - // 5}}), - // (std::vector{"Yes", "No", "Yes", "Yes", "Yes", - // "No"})); -} - -TEST(CanReachNonDecreasingSegment, 2) { - // ASSERT_EQ(SolveFunction(1, 1, 1, std::vector>{{1, 1}}, - // std::vector>{{1, 1}}), - // (std::vector{"Yes"})); +TEST(TableSortTest, AllColumnsAscending) { + std::vector> table = { + {1, 10, 100}, + {2, 20, 200}, + {3, 30, 300}, + {4, 40, 400} + }; + + auto reach = PreprocessMaxReach(table); + + EXPECT_TRUE(CheckRangeSorted(reach, 0, 3)); // Весь диапазон + EXPECT_TRUE(CheckRangeSorted(reach, 1, 2)); // Часть диапазона + EXPECT_TRUE(CheckRangeSorted(reach, 0, 0)); // Одна строка }