diff --git a/task_01/src/main.cpp b/task_01/src/main.cpp index 0e4393b..3d92284 100644 --- a/task_01/src/main.cpp +++ b/task_01/src/main.cpp @@ -1,3 +1,3 @@ -#include +#include "two_numbers.hpp" -int main() { return 0; } +int main() {} diff --git a/task_01/src/test.cpp b/task_01/src/test.cpp index 87cef73..686e32a 100644 --- a/task_01/src/test.cpp +++ b/task_01/src/test.cpp @@ -1,5 +1,35 @@ #include -TEST(Test, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include "two_numbers.hpp" + +TEST(TwoSumTest, BasicTest) { + std::vector nums = {2, 7, 11, 15}; + auto result = FindSum::findTwoSum(nums, 9); + EXPECT_EQ(result.first, 2); + EXPECT_EQ(result.second, 7); +} + +TEST(TwoSumTest, NoSolution) { + std::vector nums = {1, 2, 3, 4}; + auto result = FindSum::findTwoSum(nums, 10); + EXPECT_EQ(result.first, -1); + EXPECT_EQ(result.second, -1); +} + +TEST(TwoSumTest, DuplicateNumbers) { + std::vector nums = {3, 3, 4, 4}; + auto result = FindSum::findTwoSum(nums, 7); + EXPECT_TRUE((result == std::pair{3, 4})); +} + +TEST(TwoSumTest, EmptyArray) { + std::vector nums; + auto result = FindSum::findTwoSum(nums, 5); + EXPECT_EQ(result.first, -1); + EXPECT_EQ(result.second, -1); +} + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } \ No newline at end of file diff --git a/task_01/src/two_numbers.cpp b/task_01/src/two_numbers.cpp new file mode 100644 index 0000000..8e7526d --- /dev/null +++ b/task_01/src/two_numbers.cpp @@ -0,0 +1,22 @@ +#include "two_numbers.hpp" + +#include + +std::pair FindSum::findTwoSum(const std::vector& nums, + int target) { + int left = 0; + int right = nums.size() - 1; + + while (left < right) { + int sum = nums[left] + nums[right]; + if (sum == target) { + return {nums[left], nums[right]}; + } else if (sum < target) { + left++; + } else { + right--; + } + } + + return {-1, -1}; // Если пара не найдена +} diff --git a/task_01/src/two_numbers.hpp b/task_01/src/two_numbers.hpp new file mode 100644 index 0000000..1c674e5 --- /dev/null +++ b/task_01/src/two_numbers.hpp @@ -0,0 +1,8 @@ +#include +#include + +class FindSum { + public: + static std::pair findTwoSum(const std::vector& nums, + int target); +}; \ No newline at end of file diff --git a/task_02/README.md b/task_02/README.md index 10911e3..0a63c3b 100644 --- a/task_02/README.md +++ b/task_02/README.md @@ -1,3 +1,2 @@ # Задача на стэк - -В данной задаче необходимо реализовать один стэк и стэк с минимумом (нельзя использовать std::stack). Получение минимума должно работать за константное время \ No newline at end of file +В данной задаче необходимо реализовать один стэк и стэк с минимумом (нельзя использовать std::stack). Получение минимума должно работать за константное время diff --git a/task_02/src/main.cpp b/task_02/src/main.cpp index 0e4393b..fb77339 100644 --- a/task_02/src/main.cpp +++ b/task_02/src/main.cpp @@ -1,3 +1,27 @@ #include -int main() { return 0; } +#include "stack.hpp" + +int main() { + Stack stack; + stack.Push(2); + stack.Push(1); + stack.Push(3); + stack.Push(4); + stack.Push(5); + stack.Push(7); + + stack.display(); + std::cout << "\n"; + + stack.pop(); + stack.display(); + std::cout << "\n"; + + int a = stack.peek(); + std::cout << a << "\n"; + + int b = stack.min(); + std::cout << "minimal element: " << b; + return 0; +} diff --git a/task_02/src/stack.cpp b/task_02/src/stack.cpp index 8ca8990..04e4cbd 100644 --- a/task_02/src/stack.cpp +++ b/task_02/src/stack.cpp @@ -1,21 +1,47 @@ #include "stack.hpp" -#include +#include +#include +#include -void Stack::Push(int value) { data_.push(value); } +void Stack::Push(int element) { + arr.push_back(element); + if (min_stack.empty() || element <= min_stack.back()) { + min_stack.push_back(element); + } +} -int Stack::Pop() { - auto result = data_.top(); - data_.pop(); - return result; +void Stack::pop() { + if (arr.empty()) { + throw std::out_of_range("Stack is empty. Cannot pop."); + } + if (arr.back() == min_stack.back()) { + min_stack.pop_back(); + } + arr.pop_back(); } -void MinStack::Push(int value) { data_.push_back(value); } +int Stack::peek() { + if (arr.empty()) { + throw std::out_of_range("Stack is empty. Cannot peek."); + } + return arr.back(); +} -int MinStack::Pop() { - auto result = data_.back(); - data_.pop_back(); - return result; +void Stack::display() { + if (arr.empty()) { + std::cout << "Stack is empty." << std::endl; + return; + } + for (int i = 0; i < arr.size(); ++i) { + std::cout << arr[i] << " "; + } + std::cout << std::endl; } -int MinStack::GetMin() { return *std::min_element(data_.begin(), data_.end()); } \ No newline at end of file +int Stack::min() { + if (arr.empty()) { + throw std::out_of_range("Stack is empty. Cannot find min."); + } + return min_stack.back(); +} \ No newline at end of file diff --git a/task_02/src/stack.hpp b/task_02/src/stack.hpp index 138ec40..09f6435 100644 --- a/task_02/src/stack.hpp +++ b/task_02/src/stack.hpp @@ -1,23 +1,24 @@ #pragma once -#include #include class Stack { - public: - void Push(int value); - int Pop(); - private: - std::stack data_; -}; + std::vector arr; + std::vector min_stack; -class MinStack { public: - void Push(int value); - int Pop(); - int GetMin(); + void Push(int element); - private: - std::vector data_; + void pop(); + + int peek(); + + void display(); + + int min(); + + bool isEmpty() const { return arr.empty(); } + + size_t size() const { return arr.size(); } }; diff --git a/task_02/src/test.cpp b/task_02/src/test.cpp index 54e7ce9..0c08195 100644 --- a/task_02/src/test.cpp +++ b/task_02/src/test.cpp @@ -1,42 +1,69 @@ - #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, PushPopPeek) { + Stack s; + s.Push(10); + s.Push(20); + EXPECT_EQ(s.peek(), 20); + s.pop(); + EXPECT_EQ(s.peek(), 10); +} + +TEST(StackTest, PopEmptyStack) { + Stack s; + EXPECT_THROW(s.pop(), std::out_of_range); +} + +TEST(StackTest, PeekEmptyStack) { + Stack s; + EXPECT_THROW(s.peek(), std::out_of_range); +} + +TEST(StackTest, MinElement) { + Stack s; + s.Push(5); + s.Push(2); + s.Push(7); + s.Push(1); + EXPECT_EQ(s.min(), 1); + s.pop(); + EXPECT_EQ(s.min(), 2); +} + +TEST(StackTest, MinEmptyStack) { + Stack s; + EXPECT_THROW(s.min(), std::out_of_range); +} + +TEST(StackTest, DisplayEmpty) { + Stack s; + testing::internal::CaptureStdout(); + s.display(); + std::string output = testing::internal::GetCapturedStdout(); + EXPECT_EQ(output, "Stack is empty.\n"); +} + +TEST(StackTest, DisplayNonEmpty) { + Stack s; + s.Push(1); + s.Push(2); + s.Push(3); + testing::internal::CaptureStdout(); + s.display(); + std::string output = testing::internal::GetCapturedStdout(); + EXPECT_TRUE(output == "1 2 3 \n" || output == "1 2 3\n"); } -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, MultipleOperations) { + Stack s; + s.Push(10); + s.Push(5); + s.Push(15); + EXPECT_EQ(s.min(), 5); + s.pop(); + s.Push(3); + EXPECT_EQ(s.peek(), 3); + EXPECT_EQ(s.min(), 3); } \ No newline at end of file diff --git a/task_03/src/main.cpp b/task_03/src/main.cpp index 0e4393b..496031a 100644 --- a/task_03/src/main.cpp +++ b/task_03/src/main.cpp @@ -1,3 +1,13 @@ #include +#include -int main() { return 0; } +#include "topology_sort.hpp" + +int main() { + std::vector temps = {73, 74, 75, 71, 69, 72, 76, 73}; + std::vector result = TemperatureSorting(temps); + + for (int i{0}; i < result.size(); ++i) { + std::cout << result[i] << " "; + } +} \ No newline at end of file diff --git a/task_03/src/test.cpp b/task_03/src/test.cpp index ef5a86a..1ea75c4 100644 --- a/task_03/src/test.cpp +++ b/task_03/src/test.cpp @@ -1,8 +1,35 @@ - #include +#include + #include "topology_sort.hpp" -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(TopologyFuncTest, OrdinaryWeek) { + std::vector temperatures = {73, 74, 75, 71, 69, 72, 76, 73}; + std::vector expected = {1, 1, 4, 2, 1, 1, 0, 0}; + ASSERT_EQ(TemperatureSorting(temperatures), expected); +} + +TEST(TopologyFuncTest, EmptyInput) { + std::vector temperatures = {}; + std::vector expected = {}; + ASSERT_EQ(TemperatureSorting(temperatures), expected); +} + +TEST(TopologyFuncTest, SingleDay) { + std::vector temperatures = {30}; + std::vector expected = {0}; + ASSERT_EQ(TemperatureSorting(temperatures), expected); +} + +TEST(TopologyFuncTest, IncreasingTemperatures) { + std::vector temperatures = {10, 20, 30, 40}; + std::vector expected = {1, 1, 1, 0}; + ASSERT_EQ(TemperatureSorting(temperatures), expected); +} + +TEST(TopologyFuncTest, MixedTemperatures) { + std::vector temperatures = {73, 74, 75, 71, 69, 72, 76, 73}; + std::vector expected = {1, 1, 4, 2, 1, 1, 0, 0}; + ASSERT_EQ(TemperatureSorting(temperatures), expected); } diff --git a/task_03/src/topology_sort.cpp b/task_03/src/topology_sort.cpp index e53f670..e1656a6 100644 --- a/task_03/src/topology_sort.cpp +++ b/task_03/src/topology_sort.cpp @@ -1 +1,19 @@ #include "topology_sort.hpp" + +#include + +std::vector TemperatureSorting(const std::vector& temperatures) { + std::vector result(temperatures.size(), 0); + std::stack> s; + + for (int i{0}; i < temperatures.size(); ++i) { + while (!s.empty() && temperatures[i] > s.top().first) { + int prev_index = s.top().second; + result[prev_index] = i - prev_index; + s.pop(); + } + s.push({temperatures[i], i}); + } + + return result; +} \ No newline at end of file diff --git a/task_03/src/topology_sort.hpp b/task_03/src/topology_sort.hpp index 6f70f09..5777340 100644 --- a/task_03/src/topology_sort.hpp +++ b/task_03/src/topology_sort.hpp @@ -1 +1,4 @@ #pragma once +#include + +std::vector TemperatureSorting(const std::vector& temperatures); \ No newline at end of file diff --git a/task_04/src/fish.cpp b/task_04/src/fish.cpp new file mode 100644 index 0000000..2eeba31 --- /dev/null +++ b/task_04/src/fish.cpp @@ -0,0 +1,33 @@ +#include "fish.hpp" + +#include +#include + +std::vector> buyFishSimplified( + const std::vector& prices, int K) { + std::vector> purchases; + int N = prices.size(); + + for (int i = 0; i < N;) { + int min_price = INT_MAX; + int best_day = i; + int window_end = std::min(i + K, N); + + // Находим день с минимальной ценой в окне + for (int j = i; j < window_end; j++) { + if (prices[j] < min_price) { + min_price = prices[j]; + best_day = j; + } + } + + // Вычисляем сколько дней можно покрыть этой покупкой + int days_covered = std::min(K, N - best_day); + purchases.emplace_back(best_day, days_covered); + + // Переходим к следующему непокрытому дню + i = best_day + days_covered; + } + + return purchases; +} \ No newline at end of file diff --git a/task_04/src/fish.hpp b/task_04/src/fish.hpp new file mode 100644 index 0000000..b2c7e3b --- /dev/null +++ b/task_04/src/fish.hpp @@ -0,0 +1,4 @@ +#include + +std::vector> buyFishSimplified( + const std::vector& prices, int K); \ No newline at end of file diff --git a/task_04/src/main.cpp b/task_04/src/main.cpp index 0e4393b..732c5eb 100644 --- a/task_04/src/main.cpp +++ b/task_04/src/main.cpp @@ -1,3 +1,3 @@ -#include +#include "fish.hpp" -int main() { return 0; } +int main() { return 0; } \ No newline at end of file diff --git a/task_04/src/test.cpp b/task_04/src/test.cpp index 5e11617..717f9ba 100644 --- a/task_04/src/test.cpp +++ b/task_04/src/test.cpp @@ -1,6 +1,49 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include +#include + +#include "fish.hpp" + +TEST(TopologySort, Simple) { ASSERT_EQ(1, 1); } + +TEST(BuyFishTest, BasicCase) { + std::vector prices = {3, 2, 5, 4, 1, 6}; + int K = 3; + std::vector> expected = { + {1, 3}, // Покупаем на 2-й день (цена 2) на 3 дня + {4, 2} // Покупаем на 5-й день (цена 1) на оставшиеся 2 дня + }; + auto result = buyFishSimplified(prices, K); + ASSERT_EQ(result, expected); } + +TEST(BuyFishTest, SingleDay) { + std::vector prices = {5}; + int K = 1; + std::vector> expected = { + {0, 1} // Покупаем в единственный день + }; + auto result = buyFishSimplified(prices, K); + ASSERT_EQ(result, expected); +} + +TEST(BuyFishTest, SmallShelfLife) { + std::vector prices = {4, 3, 2, 1, 5, 6}; + int K = 1; // Рыба портится сразу + std::vector> expected = { + {0, 1}, // Покупаем каждый день отдельно + {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}}; + auto result = buyFishSimplified(prices, K); + ASSERT_EQ(result, expected); +} + +TEST(BuyFishTest, ConstantPrices) { + std::vector prices = {2, 2, 2, 2, 2}; + int K = 5; // Большой срок хранения + std::vector> expected = { + {0, 5} // Покупаем в первый день на все 5 дней + }; + auto result = buyFishSimplified(prices, K); + ASSERT_EQ(result, expected); +} \ No newline at end of file diff --git a/task_05/src/main.cpp b/task_05/src/main.cpp index 0e4393b..1dc4cf0 100644 --- a/task_05/src/main.cpp +++ b/task_05/src/main.cpp @@ -1,3 +1,22 @@ #include +#include -int main() { return 0; } +#include "merge_sort.h" + +int main() { + std::cout << "Enter the size of an array:\n"; + int N; + std::cin >> N; + + std::cout << "Enter an array:\n"; + std::vector A(N); + for (int i{0}; i < N; i++) std::cin >> A[i]; + + mergeSort(A, 0, A.size()); + + for (int i{0}; i < N; i++) { + std::cout << A[i] << " "; + } + + return 0; +} \ 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 0000000..9b176aa --- /dev/null +++ b/task_05/src/merge_sort.cpp @@ -0,0 +1,39 @@ +#include "merge_sort.h" + +std::vector merge(std::vector &arr, int l, int mid, int r) { + int i = 0; + int j = 0; + + std::vector res; + + while (i + l < mid && j + mid < r) { + if (arr[l + i] < arr[mid + j]) { + res.push_back(arr[l + i]); + i++; + } else { + res.push_back(arr[mid + j]); + j++; + } + } + while (j + mid < r) { + res.push_back(arr[mid + j]); + j++; + } + while (i + l < mid) { + res.push_back(arr[l + i]); + i++; + } + return res; +} + +void mergeSort(std::vector &arr, int l, int r) { + if (l + 1 >= r) return; + int mid = (l + r) / 2; + mergeSort(arr, l, mid); + mergeSort(arr, mid, r); + + std::vector merged = merge(arr, l, mid, r); + for (int i = 0; i < merged.size(); i++) { + arr[l + i] = merged[i]; + } +} diff --git a/task_05/src/merge_sort.h b/task_05/src/merge_sort.h new file mode 100644 index 0000000..45b96e9 --- /dev/null +++ b/task_05/src/merge_sort.h @@ -0,0 +1,4 @@ +#include + +std::vector merge(std::vector &arr, int l, int mid, int r); +void mergeSort(std::vector &arr, int l, int r); \ No newline at end of file diff --git a/task_05/src/test.cpp b/task_05/src/test.cpp index 5e11617..175873b 100644 --- a/task_05/src/test.cpp +++ b/task_05/src/test.cpp @@ -1,6 +1,64 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include + +#include "merge_sort.h" + +TEST(MergeSortTest, EmptyArray) { + std::vector arr = {}; + std::vector expected = {}; + mergeSort(arr, 0, arr.size()); + EXPECT_EQ(arr, expected); +} + +TEST(MergeSortTest, SingleElement) { + std::vector arr = {5}; + std::vector expected = {5}; + mergeSort(arr, 0, arr.size()); + EXPECT_EQ(arr, expected); +} + +TEST(MergeSortTest, AlreadySorted) { + std::vector arr = {1, 2, 3, 4, 5}; + std::vector expected = {1, 2, 3, 4, 5}; + mergeSort(arr, 0, arr.size()); + EXPECT_EQ(arr, expected); +} + +TEST(MergeSortTest, ReverseSorted) { + std::vector arr = {5, 4, 3, 2, 1}; + std::vector expected = {1, 2, 3, 4, 5}; + mergeSort(arr, 0, arr.size()); + EXPECT_EQ(arr, expected); +} + +TEST(MergeSortTest, RandomOrder) { + std::vector arr = {3, 1, 4, 1, 5, 9, 2, 6}; + std::vector expected = {1, 1, 2, 3, 4, 5, 6, 9}; + mergeSort(arr, 0, arr.size()); + EXPECT_EQ(arr, expected); +} + +TEST(MergeSortTest, PartialSort) { + std::vector arr = {7, 6, 5, 1, 2, 3, 4}; + std::vector expected_full = {1, 2, 3, 4, 5, 6, 7}; + std::vector expected_partial = {5, 6, 7, 1, + 2, 3, 4}; // если сортировать часть + + // Тестируем полную сортировку + mergeSort(arr, 0, arr.size()); + EXPECT_EQ(arr, expected_full); + + // Тестируем частичную сортировку (первые 3 элемента) + arr = {7, 6, 5, 1, 2, 3, 4}; + mergeSort(arr, 0, 3); + expected_partial = {5, 6, 7, 1, 2, 3, 4}; + EXPECT_EQ(arr, expected_partial); } + +TEST(MergeSortTest, MergeFunction) { + std::vector arr = {1, 3, 5, 2, 4, 6}; + std::vector merged = merge(arr, 0, 3, 6); + std::vector expected = {1, 2, 3, 4, 5, 6}; + EXPECT_EQ(merged, expected); +} \ No newline at end of file diff --git a/task_07/src/main.cpp b/task_07/src/main.cpp index 0e4393b..174c242 100644 --- a/task_07/src/main.cpp +++ b/task_07/src/main.cpp @@ -1,3 +1,3 @@ -#include +#include "tree.hpp" -int main() { return 0; } +int main() {} \ No newline at end of file diff --git a/task_07/src/test.cpp b/task_07/src/test.cpp index 5e11617..003adbf 100644 --- a/task_07/src/test.cpp +++ b/task_07/src/test.cpp @@ -1,6 +1,83 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include "tree.hpp" + +class AVLTreeTest : public ::testing::Test { + protected: + AVLTree tree; + + void SetUp() override { + tree.insert(50); + tree.insert(30); + tree.insert(70); + tree.insert(20); + tree.insert(40); + tree.insert(60); + tree.insert(80); + } +}; + +TEST_F(AVLTreeTest, InsertAndContains) { + EXPECT_TRUE(tree.contains(50)); + EXPECT_TRUE(tree.contains(30)); + EXPECT_TRUE(tree.contains(70)); + EXPECT_TRUE(tree.contains(20)); + EXPECT_TRUE(tree.contains(40)); + EXPECT_TRUE(tree.contains(60)); + EXPECT_TRUE(tree.contains(80)); + EXPECT_FALSE(tree.contains(10)); + EXPECT_FALSE(tree.contains(100)); +} + +TEST_F(AVLTreeTest, RemoveElements) { + tree.remove(20); + EXPECT_FALSE(tree.contains(20)); + EXPECT_TRUE(tree.contains(30)); + + tree.remove(30); + EXPECT_FALSE(tree.contains(30)); + EXPECT_TRUE(tree.contains(50)); + + tree.remove(50); + EXPECT_FALSE(tree.contains(50)); + EXPECT_TRUE(tree.contains(60)); + EXPECT_TRUE(tree.contains(70)); } + +TEST_F(AVLTreeTest, MaintainsBalanceProperty) { + AVLTree balanceTestTree; + + // Вставляем элементы в порядке, который создает дисбаланс в обычном BST + for (int i = 1; i <= 100; ++i) { + balanceTestTree.insert(i); + // Можно добавить проверку баланса на каждом шаге + } + + // Проверяем, что все элементы присутствуют + for (int i = 1; i <= 100; ++i) { + EXPECT_TRUE(balanceTestTree.contains(i)); + } +} + +TEST_F(AVLTreeTest, ClearTree) { + EXPECT_TRUE(tree.contains(50)); + tree.clear(); + EXPECT_FALSE(tree.contains(50)); + + // Проверяем, что можно снова использовать дерево + tree.insert(100); + EXPECT_TRUE(tree.contains(100)); +} + +TEST(AVLTreeEmptyTest, HandlesEmptyTree) { + AVLTree emptyTree; + EXPECT_FALSE(emptyTree.contains(10)); + + // Удаление из пустого дерева не должно вызывать ошибок + EXPECT_NO_THROW(emptyTree.remove(10)); +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/task_07/src/tree.cpp b/task_07/src/tree.cpp new file mode 100644 index 0000000..22eb055 --- /dev/null +++ b/task_07/src/tree.cpp @@ -0,0 +1,87 @@ +#include "tree.hpp" + +Node* AVLTree::insert(Node* node, int key) { + if (!node) return new Node{key, nullptr, nullptr, 1}; + + if (key < node->key) + node->left = insert(node->left, key); + else if (key > node->key) + node->right = insert(node->right, key); + else + return node; // Дубликаты не допускаем + + return balance(node); +} + +Node* AVLTree::remove(Node* node, int key) { + if (!node) return nullptr; + + if (key < node->key) + node->left = remove(node->left, key); + else if (key > node->key) + node->right = remove(node->right, key); + else { + if (!node->left || !node->right) { + Node* temp = node->left ? node->left : node->right; + delete node; + return temp; + } + Node* temp = findMin(node->right); + node->key = temp->key; + node->right = remove(node->right, temp->key); + } + return balance(node); +} + +bool AVLTree::contains(const Node* node, int key) const { + if (!node) return false; + if (key == node->key) return true; + return key < node->key ? contains(node->left, key) + : contains(node->right, key); +} + +void AVLTree::clear(Node* node) { + if (node) { + clear(node->left); + clear(node->right); + delete node; + } +} + +Node* AVLTree::rotateRight(Node* y) { + Node* x = y->left; + y->left = x->right; + x->right = y; + updateHeight(y); + updateHeight(x); + return x; +} + +Node* AVLTree::rotateLeft(Node* x) { + Node* y = x->right; + x->right = y->left; + y->left = x; + updateHeight(x); + updateHeight(y); + return y; +} + +Node* AVLTree::balance(Node* node) { + updateHeight(node); + int bf = balanceFactor(node); + + if (bf > 1) { + if (balanceFactor(node->left) < 0) node->left = rotateLeft(node->left); + return rotateRight(node); + } + if (bf < -1) { + if (balanceFactor(node->right) > 0) node->right = rotateRight(node->right); + return rotateLeft(node); + } + return node; +} + +Node* AVLTree::findMin(Node* node) { + while (node && node->left) node = node->left; + return node; +} \ No newline at end of file diff --git a/task_07/src/tree.hpp b/task_07/src/tree.hpp new file mode 100644 index 0000000..ad49be9 --- /dev/null +++ b/task_07/src/tree.hpp @@ -0,0 +1,44 @@ +#include + +struct Node { + int key; + Node* left; + Node* right; + int height; +}; + +class AVLTree { + public: + AVLTree() : root(nullptr) {} + ~AVLTree() { clear(root); } + + void insert(int key) { root = insert(root, key); } + void remove(int key) { root = remove(root, key); } + bool contains(int key) const { return contains(root, key); } + void clear() { + clear(root); + root = nullptr; + } + + private: + Node* root; + + Node* insert(Node* node, int key); + Node* remove(Node* node, int key); + bool contains(const Node* node, int key) const; + void clear(Node* node); + + // Вспомогательные функции + int height(Node* node) { return node ? node->height : 0; } + int balanceFactor(Node* node) { + return node ? height(node->left) - height(node->right) : 0; + } + void updateHeight(Node* node) { + node->height = 1 + std::max(height(node->left), height(node->right)); + } + + Node* rotateRight(Node* y); + Node* rotateLeft(Node* x); + Node* balance(Node* node); + Node* findMin(Node* node); +}; \ No newline at end of file diff --git a/task_08/src/hashmap.hpp b/task_08/src/hashmap.hpp new file mode 100644 index 0000000..cca7386 --- /dev/null +++ b/task_08/src/hashmap.hpp @@ -0,0 +1,34 @@ +#include +#include +#include + +class HashMap { + private: + struct KeyValuePair { + std::string key; + int value; + }; + + static const size_t DEFAULT_CAPACITY = 16; + static const double LOAD_FACTOR_THRESHOLD; + + std::vector> buckets; + size_t size; + + size_t hash(const std::string& key) const; + size_t getBucketIndex(const std::string& key) const; + void rehash(); + + public: + HashMap(); + explicit HashMap(size_t initialCapacity); + ~HashMap() = default; + + void insert(const std::string& key, int value); + bool contains(const std::string& key) const; + int get(const std::string& key) const; + void remove(const std::string& key); + size_t getSize() const; + bool isEmpty() const; + void clear(); +}; diff --git a/task_08/src/hasmap.cpp b/task_08/src/hasmap.cpp new file mode 100644 index 0000000..f0f1769 --- /dev/null +++ b/task_08/src/hasmap.cpp @@ -0,0 +1,91 @@ +#include +#include + +#include "hashmap.hpp" + +const double HashMap::LOAD_FACTOR_THRESHOLD = 0.75; + +HashMap::HashMap() : HashMap(DEFAULT_CAPACITY) {} + +HashMap::HashMap(size_t initialCapacity) : buckets(initialCapacity), size(0) {} + +size_t HashMap::hash(const std::string& key) const { + return std::hash{}(key); +} + +size_t HashMap::getBucketIndex(const std::string& key) const { + return hash(key) % buckets.size(); +} + +void HashMap::rehash() { + std::vector> oldBuckets = std::move(buckets); + buckets.resize(oldBuckets.size() * 2); + size = 0; + + for (auto& bucket : oldBuckets) { + for (auto& pair : bucket) { + insert(pair.key, pair.value); + } + } +} + +void HashMap::insert(const std::string& key, int value) { + size_t index = getBucketIndex(key); + for (auto& pair : buckets[index]) { + if (pair.key == key) { + pair.value = value; + return; + } + } + + buckets[index].push_back({key, value}); + size++; + + if (static_cast(size) / buckets.size() > LOAD_FACTOR_THRESHOLD) { + rehash(); + } +} + +bool HashMap::contains(const std::string& key) const { + size_t index = getBucketIndex(key); + for (const auto& pair : buckets[index]) { + if (pair.key == key) { + return true; + } + } + return false; +} + +int HashMap::get(const std::string& key) const { + size_t index = getBucketIndex(key); + for (const auto& pair : buckets[index]) { + if (pair.key == key) { + return pair.value; + } + } + throw std::out_of_range("Key not found"); +} + +void HashMap::remove(const std::string& key) { + size_t index = getBucketIndex(key); + auto& bucket = buckets[index]; + + for (auto it = bucket.begin(); it != bucket.end(); ++it) { + if (it->key == key) { + bucket.erase(it); + size--; + return; + } + } +} + +size_t HashMap::getSize() const { return size; } + +bool HashMap::isEmpty() const { return size == 0; } + +void HashMap::clear() { + for (auto& bucket : buckets) { + bucket.clear(); + } + size = 0; +} \ No newline at end of file diff --git a/task_08/src/main.cpp b/task_08/src/main.cpp index 0e4393b..991fe18 100644 --- a/task_08/src/main.cpp +++ b/task_08/src/main.cpp @@ -1,3 +1,25 @@ #include -int main() { return 0; } +#include "hashmap.hpp" + +int main() { + HashMap map; + + // Вставка элементов + map.insert("apple", 10); + map.insert("banana", 20); + map.insert("orange", 30); + + std::cout << "Contains 'apple': " << map.contains("apple") << "\n"; + std::cout << "Contains 'grape': " << map.contains("grape") << "\n"; + + std::cout << "Value of 'banana': " << map.get("banana") << "\n"; + + map.remove("apple"); + std::cout << "After remove, contains 'apple': " << map.contains("apple") + << "\n"; + + std::cout << "Size: " << map.getSize() << "\n"; + + return 0; +} \ No newline at end of file diff --git a/task_08/src/test.cpp b/task_08/src/test.cpp index 5e11617..af7f88b 100644 --- a/task_08/src/test.cpp +++ b/task_08/src/test.cpp @@ -1,6 +1,63 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include "hashmap.hpp" + +TEST(HashMapTest, InsertAndGet) { + HashMap map; + map.insert("apple", 10); + map.insert("banana", 20); + + ASSERT_EQ(map.get("apple"), 10); + ASSERT_EQ(map.get("banana"), 20); + ASSERT_THROW(map.get("orange"), std::out_of_range); } + +TEST(HashMapTest, ContainsAndRemove) { + HashMap map; + map.insert("one", 1); + map.insert("two", 2); + + ASSERT_TRUE(map.contains("one")); + ASSERT_TRUE(map.contains("two")); + ASSERT_FALSE(map.contains("three")); + + map.remove("one"); + ASSERT_FALSE(map.contains("one")); + ASSERT_TRUE(map.contains("two")); +} + +TEST(HashMapTest, SizeAndEmpty) { + HashMap map; + ASSERT_TRUE(map.isEmpty()); + ASSERT_EQ(map.getSize(), 0); + + map.insert("a", 1); + map.insert("b", 2); + + ASSERT_FALSE(map.isEmpty()); + ASSERT_EQ(map.getSize(), 2); + + map.remove("a"); + ASSERT_EQ(map.getSize(), 1); + + map.clear(); + ASSERT_TRUE(map.isEmpty()); + ASSERT_EQ(map.getSize(), 0); +} + +TEST(HashMapTest, Rehashing) { + HashMap map(2); + + map.insert("a", 1); + map.insert("b", 2); + map.insert("c", 3); + + ASSERT_EQ(map.getSize(), 3); + ASSERT_EQ(map.get("a"), 1); + ASSERT_EQ(map.get("b"), 2); + ASSERT_EQ(map.get("c"), 3); + + map.insert("d", 4); + ASSERT_EQ(map.getSize(), 4); + ASSERT_EQ(map.get("d"), 4); +} \ No newline at end of file diff --git a/task_09/src/table.cpp b/task_09/src/table.cpp new file mode 100644 index 0000000..027e8d8 --- /dev/null +++ b/task_09/src/table.cpp @@ -0,0 +1,57 @@ +#include "table.hpp" + +void TableChecker::readTable(std::istream& in) { + in >> n >> m; + table.assign(n, std::vector(m)); + + for (int i = 0; i < n; ++i) { + for (int j = 0; j < m; ++j) { + in >> table[i][j]; + } + } + + prepareData(); +} + +void TableChecker::prepareData() { + column_ok.assign(m, std::vector(n, 1)); // Initialize all as 1 + prefix.assign(m, std::vector(n + 1, 0)); + + for (int j = 0; j < m; ++j) { + for (int i = 0; i < n - 1; ++i) { + if (table[i][j] > table[i + 1][j]) { + column_ok[j][i] = 0; // Mark as not OK + } + } + + // Build prefix sum of violations + for (int i = 0; i < n; ++i) { + prefix[j][i + 1] = prefix[j][i] + (column_ok[j][i] == 0 ? 1 : 0); + } + } +} + +bool TableChecker::isRangeSorted(int l, int r) const { + if (l >= r) return true; + + for (int j = 0; j < m; ++j) { + int violations = prefix[j][r] - prefix[j][l]; + if (violations == 0) { + return true; + } + } + return false; +} + +void TableChecker::processQueries(std::istream& in, std::ostream& out) { + int k; + in >> k; + + while (k--) { + int l, r; + in >> l >> r; + --l; // convert to 0-based + + out << (isRangeSorted(l, r - 1) ? "Yes" : "No") << '\n'; + } +} \ No newline at end of file diff --git a/task_09/src/table.hpp b/task_09/src/table.hpp new file mode 100644 index 0000000..2a79329 --- /dev/null +++ b/task_09/src/table.hpp @@ -0,0 +1,17 @@ +#include +#include + +class TableChecker { + public: + void readTable(std::istream& in); + void processQueries(std::istream& in, std::ostream& out); + + private: + int n = 0, m = 0; + std::vector> table; + std::vector> column_ok; + std::vector> prefix; + + void prepareData(); + bool isRangeSorted(int l, int r) const; +}; \ No newline at end of file diff --git a/task_09/src/test.cpp b/task_09/src/test.cpp index a42caa4..4f76cf6 100644 --- a/task_09/src/test.cpp +++ b/task_09/src/test.cpp @@ -1,23 +1,43 @@ #include -#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"})); +#include + +#include "table.hpp" + +TEST(TableCheckerTest, EmptyTable) { + TableChecker tc; + std::istringstream in("0 0\n0\n"); + std::ostringstream out; + + tc.readTable(in); + tc.processQueries(in, out); + + EXPECT_EQ(out.str(), ""); } -TEST(CanReachNonDecreasingSegment, 2) { - // ASSERT_EQ(SolveFunction(1, 1, 1, std::vector>{{1, 1}}, - // std::vector>{{1, 1}}), - // (std::vector{"Yes"})); +TEST(TableCheckerTest, SingleRow) { + TableChecker tc; + std::istringstream in("1 3\n10 20 30\n2\n1 1\n1 1\n"); + std::ostringstream out; + + tc.readTable(in); + tc.processQueries(in, out); + + EXPECT_EQ(out.str(), "Yes\nYes\n"); } + +TEST(TableCheckerTest, SortedColumns) { + TableChecker tc; + std::istringstream in("3 2\n1 5\n2 6\n3 7\n2\n1 3\n2 3\n"); + std::ostringstream out; + + tc.readTable(in); + tc.processQueries(in, out); + + EXPECT_EQ(out.str(), "Yes\nYes\n"); +} + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file