diff --git a/lib/src/util.hpp b/lib/src/util.hpp index e69de29b..5e656486 100644 --- a/lib/src/util.hpp +++ b/lib/src/util.hpp @@ -0,0 +1,29 @@ +#include +#include +#include + +template +static std::size_t Partition(std::vector& data, std::size_t left, + std::size_t right) { + std::function RandomPivotIndex = + [&](std::size_t left, std::size_t right) { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(left, right); + return dis(gen); + }; + + std::size_t pivot_index = RandomPivotIndex(left, right); + std::swap(data[pivot_index], data[right]); + std::size_t index = left; + + for (std::size_t i = left; i < right; i++) { + if (data[i] < data[right]) { + std::swap(data[i], data[index]); + index++; + } + } + + std::swap(data[right], data[index]); + return index; +} \ No newline at end of file diff --git a/task_02/src/list_stack.cpp b/task_02/src/list_stack.cpp new file mode 100644 index 00000000..f32a8514 --- /dev/null +++ b/task_02/src/list_stack.cpp @@ -0,0 +1 @@ +#include "list_stacks.hpp" \ No newline at end of file diff --git a/task_02/src/list_stacks.hpp b/task_02/src/list_stacks.hpp new file mode 100644 index 00000000..26285220 --- /dev/null +++ b/task_02/src/list_stacks.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include +#include + +template +class Stack final { + public: + constexpr Stack() noexcept {} + Stack(const Stack& other) : list_(other.list_) {} + Stack(Stack&& other) : list_(std::move(other.list_)) { other.list_.clear(); } + Stack(const std::initializer_list& init_list) : list_(init_list) {} + + ~Stack() = default; + + void Push(const T& value) { list_.push_back(value); } + void Pop() { + if (Empty()) throw std::underflow_error("Stack is empty!"); + list_.pop_back(); + } + + T& Top() { + if (Empty()) throw std::underflow_error("Stack is empty!"); + return list_.back(); + } + bool Empty() { return list_.empty(); } + std::size_t Size() { return list_.size(); } + + private: + std::list list_; +}; + +template +class StackMin final { + public: + constexpr StackMin() noexcept {} + StackMin(const StackMin& other) : list_(other.list_) {} + StackMin(StackMin&& other) : list_(other.list_) { other.list_.clear(); } + StackMin(const std::initializer_list& init_list_) : list_(init_list_) {} + + ~StackMin() = default; + + void Push(const T& value) { + if (min_stack.Empty() || min_stack.Top() > value) min_stack.Push(value); + list_.push_back(value); + } + void Pop() { + if (Empty()) throw std::underflow_error("Stack is empty!"); + if (min_stack.Top() == list_.back()) min_stack.Pop(); + list_.pop_back(); + } + + T& Top() { + if (Empty()) throw std::underflow_error("Stack is empty!"); + return list_.back(); + } + bool Empty() { return list_.empty(); } + std::size_t Size() { return list_.size(); } + + T& Min() { return min_stack.Top(); } + + private: + std::list list_; + Stack min_stack; +}; diff --git a/task_02/src/stack.cpp b/task_02/src/stack.cpp deleted file mode 100644 index 8ca89902..00000000 --- a/task_02/src/stack.cpp +++ /dev/null @@ -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 deleted file mode 100644 index 138ec40f..00000000 --- a/task_02/src/stack.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include - -class Stack { - public: - void Push(int value); - int Pop(); - - private: - std::stack data_; -}; - -class MinStack { - public: - void Push(int value); - int Pop(); - int GetMin(); - - private: - std::vector data_; -}; diff --git a/task_02/src/test.cpp b/task_02/src/test.cpp index 54e7ce90..d9a8e80e 100644 --- a/task_02/src/test.cpp +++ b/task_02/src/test.cpp @@ -2,41 +2,62 @@ #include #include +#include -#include "stack.hpp" +#include "list_stacks.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, test1) { + Stack stack; + stack.Push(1); + stack.Pop(); + EXPECT_THROW(stack.Pop(), std::underflow_error); + stack.Push(1); + stack.Push(2); + ASSERT_EQ(stack.Top(), 2); + ASSERT_EQ(stack.Top(), 2); + stack.Push(1000); + stack.Push(21412); + stack.Pop(); + stack.Pop(); + stack.Pop(); + stack.Pop(); + EXPECT_THROW(stack.Pop(), std::underflow_error); + EXPECT_THROW(stack.Top(), std::underflow_error); + stack.Push(1); + stack.Push(3); + ASSERT_EQ(stack.Top(), 3); + stack.Pop(); + ASSERT_EQ(stack.Top(), 1); } -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(MinStackTest, test2) { + StackMin stack; + stack.Push(1); + stack.Pop(); + EXPECT_THROW(stack.Pop(), std::underflow_error); + stack.Push(1); + stack.Push(2); + ASSERT_EQ(stack.Top(), 2); + ASSERT_EQ(stack.Top(), 2); + stack.Push(1000); + stack.Push(21412); + ASSERT_EQ(stack.Min(), 1); + stack.Pop(); + stack.Pop(); + stack.Pop(); + stack.Pop(); + EXPECT_THROW(stack.Min(), std::underflow_error); + EXPECT_THROW(stack.Pop(), std::underflow_error); + EXPECT_THROW(stack.Top(), std::underflow_error); + stack.Push(1); + stack.Push(3); + ASSERT_EQ(stack.Top(), 3); + stack.Pop(); + ASSERT_EQ(stack.Top(), 1); + stack.Push(-10); + stack.Push(-102410); + stack.Push(10432140); + stack.Push(0); + stack.Push(-1010); + ASSERT_EQ(stack.Min(), -102410); } \ No newline at end of file diff --git a/task_03/src/temperature.cpp b/task_03/src/temperature.cpp new file mode 100644 index 00000000..90841768 --- /dev/null +++ b/task_03/src/temperature.cpp @@ -0,0 +1,14 @@ +#include "temperature.hpp" + +std::vector TemperatureCounter(std::vector temps) { + std::stack days; + std::vector result(temps.size(), 0); + for (int i = 0; i < temps.size(); i++) { + while (!days.empty() && days.top().value < temps[i]) { + result[days.top().index] = i - days.top().index; + days.pop(); + } + days.push(Day(i, temps[i])); + } + return result; +} \ No newline at end of file diff --git a/task_03/src/temperature.hpp b/task_03/src/temperature.hpp new file mode 100644 index 00000000..09fa0d2a --- /dev/null +++ b/task_03/src/temperature.hpp @@ -0,0 +1,11 @@ +#pragma once +#include +#include + +struct Day { + int index; + double value; + Day(int index, double value) : index(index), value(value) {} +}; + +std::vector TemperatureCounter(std::vector temps); \ No newline at end of file diff --git a/task_03/src/test.cpp b/task_03/src/test.cpp index ef5a86ae..87f9337d 100644 --- a/task_03/src/test.cpp +++ b/task_03/src/test.cpp @@ -1,8 +1,18 @@ #include -#include "topology_sort.hpp" +#include "temperature.hpp" -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] -} +TEST(TemperatureCnt, Simple) { + ASSERT_EQ(TemperatureCounter(std::vector{5.8, 7.2, 4.1, 5.999}), + (std::vector{1, 0, 1, 0})); + ASSERT_EQ( + TemperatureCounter(std::vector{5.99, 12, 4, 9.1, 5.15, 4, 2}), + (std::vector{1, 0, 1, 0, 0, 0, 0})); + ASSERT_EQ( + TemperatureCounter(std::vector{2, 6, 17.512512, 7, 3, 4.412151}), + (std::vector{1, 1, 0, 0, 1, 0})); + ASSERT_EQ(TemperatureCounter(std::vector{}), std::vector{}); + ASSERT_EQ(TemperatureCounter(std::vector{2, 6, 5, 4, 3, 7}), + (std::vector{1, 4, 3, 2, 1, 0})); +} \ 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 e53f670c..00000000 --- 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 6f70f09b..00000000 --- a/task_03/src/topology_sort.hpp +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/task_04/src/binary_heap.hpp b/task_04/src/binary_heap.hpp new file mode 100644 index 00000000..500c23f1 --- /dev/null +++ b/task_04/src/binary_heap.hpp @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include + +template +class BinaryMinHeap { + public: + BinaryMinHeap() = default; + BinaryMinHeap(const std::vector& data) { + for (const auto& elem : data) Add(elem); + } + + BinaryMinHeap(const std::initializer_list& data) { + for (const auto& elem : data) Add(elem); + } + + T operator[](size_t index) const { + if (index > Size()) throw std::out_of_range("invalid index"); + + return data[index]; + } + + const std::vector& Data() const { return data; } + + void Add(T elem) { + data.push_back(elem); + SiftUp(); + } + + T ExtractMin() { + if (Empty()) throw std::underflow_error("Heap is empty!"); + + std::swap(data[0], data[Size() - 1]); + data.pop_back(); + SiftDown(); + + return data[0]; + } + + T GetMin() const { + if (Empty()) throw std::underflow_error("Heap is empty!"); + + return data[0]; + } + + size_t Size() const { return data.size(); } + + bool Empty() const { return Size() == 0; } + + private: + size_t ParentOf(size_t index) const { return (index - 1) / 2; } + + size_t LeftChildOf(size_t index) const { return (2 * index + 1); } + + size_t RightChildOf(size_t index) const { return (2 * index + 2); } + + void SiftUp() { + size_t index = Size() - 1; + + while (index > 0 && data[ParentOf(index)] > data[index]) { + std::swap(data[index], data[ParentOf(index)]); + index = ParentOf(index); + } + } + + void SiftDown(size_t index = 0) { + while (index < Size()) { + size_t current_index = index; + + if (LeftChildOf(index) < Size() && + data[LeftChildOf(index)] < data[current_index]) { + current_index = LeftChildOf(index); + } + + if (RightChildOf(index) < Size() && + data[RightChildOf(index)] < data[current_index]) { + current_index = RightChildOf(index); + } + + if (current_index == index) break; + + std::swap(data[index], data[current_index]); + + index = current_index; + } + } + + std::vector data; +}; + +template +class BinaryMaxHeap { + public: + BinaryMaxHeap() = default; + BinaryMaxHeap(const std::vector& data) { + for (const auto& elem : data) Add(elem); + } + + BinaryMaxHeap(const std::initializer_list& data) { + for (const auto& elem : data) Add(elem); + } + + T operator[](size_t index) const { + if (index > Size()) throw std::out_of_range("invalid index"); + + return data[index]; + } + + const std::vector& Data() const { return data; } + + void Add(T elem) { + data.push_back(elem); + SiftUp(); + } + + T ExtractMax() { + if (Empty()) throw std::underflow_error("Heap is empty!"); + + std::swap(data[0], data[Size() - 1]); + data.pop_back(); + SiftDown(); + + return data[0]; + } + + T GetMax() const { + if (Empty()) throw std::underflow_error("Heap is empty!"); + + return data[0]; + } + + size_t Size() const { return data.size(); } + + bool Empty() const { return Size() == 0; } + + private: + size_t ParentOf(size_t index) const { return (index - 1) / 2; } + + size_t LeftChildOf(size_t index) const { return (2 * index + 1); } + + size_t RightChildOf(size_t index) const { return (2 * index + 2); } + + void SiftUp() { + size_t index = Size() - 1; + + while (index > 0 && data[ParentOf(index)] < data[index]) { + std::swap(data[index], data[ParentOf(index)]); + index = ParentOf(index); + } + } + + void SiftDown(size_t index = 0) { + while (index < Size()) { + size_t current_index = index; + + if (LeftChildOf(index) < Size() && + data[LeftChildOf(index)] > data[current_index]) { + current_index = LeftChildOf(index); + } + + if (RightChildOf(index) < Size() && + data[RightChildOf(index)] > data[current_index]) { + current_index = RightChildOf(index); + } + + if (current_index == index) break; + + std::swap(data[index], data[current_index]); + + index = current_index; + } + } + + 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..d6822514 100644 --- a/task_04/src/test.cpp +++ b/task_04/src/test.cpp @@ -1,6 +1,40 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include "binary_heap.hpp" +#include "util.hpp" + +TEST(BinaryMinHeap_test, Empty) { + BinaryMinHeap heap; + ASSERT_EQ(heap.Empty(), true); + ASSERT_EQ(heap.Size(), 0); + heap.Add(1); + ASSERT_EQ(heap.Empty(), false); + ASSERT_EQ(heap.Size(), 1); + EXPECT_EQ(heap.GetMin(), 1); + ASSERT_EQ(heap.ExtractMin(), 1); + EXPECT_THROW(heap.GetMin(), std::underflow_error); + EXPECT_THROW(heap.ExtractMin(), std::underflow_error); + heap.Add(4); + heap.Add(14); + heap.Add(6); + heap.Add(111); + EXPECT_EQ(heap.GetMin(), 4); +} + +TEST(BinaryMaxHeap_test, Empty) { + BinaryMaxHeap heap; + ASSERT_EQ(heap.Empty(), true); + ASSERT_EQ(heap.Size(), 0); + heap.Add(1); + ASSERT_EQ(heap.Empty(), false); + ASSERT_EQ(heap.Size(), 1); + EXPECT_EQ(heap.GetMax(), 1); + ASSERT_EQ(heap.ExtractMax(), 1); + EXPECT_THROW(heap.GetMax(), std::underflow_error); + EXPECT_THROW(heap.ExtractMax(), std::underflow_error); + heap.Add(4); + heap.Add(14); + heap.Add(6); + heap.Add(111); + EXPECT_EQ(heap.GetMax(), 111); } diff --git a/task_05/src/quick_sort.hpp b/task_05/src/quick_sort.hpp new file mode 100644 index 00000000..93a0ecab --- /dev/null +++ b/task_05/src/quick_sort.hpp @@ -0,0 +1,15 @@ +#include <../lib/src/util.hpp> + +template +void QuickSort(std::vector& data) { + if (data.empty()) return; + std::function QuickSortStep = + [&](std::size_t l, std::size_t r) { + if (l >= r) return; + std::size_t pivot_index = Partition(data, l, r); + if (pivot_index) QuickSortStep(l, pivot_index - 1); + QuickSortStep(pivot_index + 1, r); + }; + + QuickSortStep(0, data.size() - 1); +} \ No newline at end of file diff --git a/task_05/src/test.cpp b/task_05/src/test.cpp index 5e11617e..3b61ff4b 100644 --- a/task_05/src/test.cpp +++ b/task_05/src/test.cpp @@ -1,6 +1,26 @@ #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] -} +#include "quick_sort.hpp" + +TEST(Sort, test1) { + std::vector a{5.34, 3.11, 4.41515215, -4151.51, 2.00001}; + QuickSort(a); + EXPECT_TRUE(std::is_sorted(a.begin(), a.end())); + + std::vector b; + QuickSort(b); + EXPECT_TRUE(b.empty()); + + std::vector c{-114, -452, -3, -455, -511}; + QuickSort(c); + EXPECT_TRUE(std::is_sorted(c.begin(), c.end())); + + std::vector d{-5.3, 3.1, 4.7, 1.2, -2.8}; + QuickSort(d); + EXPECT_TRUE(std::is_sorted(d.begin(), d.end())); + + std::vector e{51, 3, -414, 1, 2, 34, 1, 4}; + QuickSort(e); + EXPECT_TRUE(std::is_sorted(e.begin(), e.end())); +} \ No newline at end of file diff --git a/task_06/src/statistics.hpp b/task_06/src/statistics.hpp new file mode 100644 index 00000000..a0724f2b --- /dev/null +++ b/task_06/src/statistics.hpp @@ -0,0 +1,12 @@ +#include <../lib/src/util.hpp> + +template +T FindStatistics(std::vector& data, int order) { + int pivot_pos = 0, left = 0, right = data.size(); + while (left < right) { + pivot_pos = Partition(data, left, right - 1); + if (pivot_pos == order) return data[pivot_pos]; + pivot_pos > order ? right = pivot_pos : left = pivot_pos + 1; + } + return data[pivot_pos]; +} \ No newline at end of file diff --git a/task_06/src/test.cpp b/task_06/src/test.cpp index 5e11617e..9a0a5b33 100644 --- a/task_06/src/test.cpp +++ b/task_06/src/test.cpp @@ -1,6 +1,26 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include + +#include "statistics.hpp" + +TEST(OrderStats, Simple1) { + std::vector v{51, 83, 11, 64, 66, 57, 55}; + ASSERT_EQ(FindStatistics(v, 3), 57); } +TEST(OrderStats, Simple2) { + std::vector v{ + 41, 99, 43, 22, 33, 60, 61, 8, 1, 97, + }; + ASSERT_EQ(FindStatistics(v, 5), 43); +} +TEST(OrderStats, Simple3) { + std::vector v{21.468, 19.642, 46.517, 17.44, + 464.22, 66.171, 57.68, 19.58}; + ASSERT_EQ(FindStatistics(v, 2), 19.642); +} + +TEST(OrderStats, Simple4) { + std::vector v{'d', 's', 't', 'b'}; + ASSERT_EQ(FindStatistics(v, 1), 'd'); +} \ No newline at end of file diff --git a/task_07/src/avl_tree.hpp b/task_07/src/avl_tree.hpp new file mode 100644 index 00000000..e0045ab8 --- /dev/null +++ b/task_07/src/avl_tree.hpp @@ -0,0 +1,114 @@ +#pragma once + +#include +#include +#include + +template +struct Node { + T key; + std::size_t height = 1; + Node* left = nullptr; + Node* right = nullptr; + Node(T key) : key(key){}; +}; + +template +class AVLTree { + public: + void Push(int k) { root = Insert(root, k); } + void Pop(int k) { root = Remove(root, k); } + bool Contains(int k) { return Find(root, k) ? true : false; } + + private: + std::size_t Height(Node* n) { return n ? n->height : 0; } + int BFactor(Node* n) { return Height(n->right) - Height(n->left); } + + void SetHeight(Node* n) { + n->height = std::max(Height(n->left), Height(n->right)) + 1; + } + + Node* RotateRight(Node* n) { + Node* q = n->left; + n->left = q->right; + q->right = n; + SetHeight(n); + SetHeight(q); + return q; + } + + Node* RotateLeft(Node* n) { + Node* q = n->right; + n->right = q->left; + q->left = n; + SetHeight(q); + SetHeight(n); + return q; + } + + Node* Balance(Node* n) { + SetHeight(n); + switch (BFactor(n)) { + case 2: + if (BFactor(n->right) < 0) n->right = RotateRight(n->right); + return RotateLeft(n); + case -2: + if (BFactor(n->left) > 0) n->left = RotateLeft(n->left); + return RotateRight(n); + default: + return n; + } + } + + Node* Insert(Node* n, T k) { + { + if (!n) { + return new Node(k); + } + if (k < n->key) + n->left = Insert(n->left, k); + else + n->right = Insert(n->right, k); + return Balance(n); + } + } + + Node* FindMin(Node* n) { return n->left ? FindMin(n->left) : n; } + + Node* RemoveMin(Node* n) { + { + if (!n->left) { + delete n->left; + return n->right; + } + n->left = RemoveMin(n->left); + return Balance(n); + } + } + + Node* Remove(Node* n, int k) { + if (!n) { + delete n; + return nullptr; + } + if (k == n->key) { + if (!n->right) { + return n->left; + } + FindMin(n->right)->right = RemoveMin(n->right); + FindMin(n->right)->left = n->left; + return Balance(FindMin(n->right)); + } + k < n->key ? n->left = Remove(n->left, k) : n->right = Remove(n->right, k); + return Balance(n); + } + + Node* Find(Node* n, int k) { + if (n == nullptr || n->key == k) { + return n; + } + return k < n->key ? Find(n->left, k) : Find(n->right, k); + } + + Node* root = nullptr; +}; \ No newline at end of file diff --git a/task_07/src/test.cpp b/task_07/src/test.cpp index 5e11617e..8f89bdbf 100644 --- a/task_07/src/test.cpp +++ b/task_07/src/test.cpp @@ -1,6 +1,22 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] -} +#include +#include + +TEST(AVLTree, test) { + AVLTree avl; + ASSERT_EQ(avl.Contains(10), false); + ASSERT_EQ(avl.Contains(5), false); + ASSERT_EQ(avl.Contains(15), false); + avl.Push(10); + avl.Push(5); + avl.Push(15); + ASSERT_EQ(avl.Contains(10), true); + ASSERT_EQ(avl.Contains(5), true); + ASSERT_EQ(avl.Contains(15), true); + avl.Push(12); + avl.Pop(5); + ASSERT_EQ(avl.Contains(5), false); + avl.Pop(15); + ASSERT_EQ(avl.Contains(15), false); +} \ 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..de6574f1 --- /dev/null +++ b/task_08/src/hash_table.cpp @@ -0,0 +1,90 @@ +#include "hash_table.hpp" + +#include + +#include +#include + +size_t HashTable::FirstHashFunc(std::size_t key) { + return floor(buffers_size * + ((key * hashCoefficient) - floor(key * hashCoefficient))); +} + +size_t HashTable::SecondHashFunc(std::size_t key) { + return (key * buffers_size - 1) % buffers_size; +} + +void HashTable::Clear() { + cells = 0; + size = 0; + for (auto &cell : cell_conditions) cell = Condition::Empty; +} + +void HashTable::ReSize() { + buffers_size *= 2; + t_container.resize(buffers_size); + cell_conditions.resize(buffers_size); +} + +void HashTable::ReHash() { + std::vector subdata; + for (std::size_t i{0}; i < buffers_size; i++) + if (cell_conditions[i] == Condition::Fill) + subdata.push_back(t_container[i]); + + ReSize(); + Clear(); + for (auto &elem : subdata) Insert(elem); +} + +bool HashTable::Contains(std::size_t value) { + size_t hash = FirstHashFunc(value) % buffers_size; + std::size_t count = 0; + while (cell_conditions[hash] != Condition::Empty) { + if (t_container[hash] == value && cell_conditions[hash] == Condition::Fill) + return true; + count++; + hash = + (FirstHashFunc(value) + count * SecondHashFunc(value)) % buffers_size; + } + return false; +} + +void HashTable::Insert(std::size_t value) { + size_t hash = FirstHashFunc(value) % buffers_size; + std::size_t count = 0; + while (cell_conditions[hash] == Condition::Fill) { + if (t_container[hash] == value) return; + count++; + hash = + (FirstHashFunc(value) + count * SecondHashFunc(value)) % buffers_size; + } + + t_container[hash] = value; + cell_conditions[hash] = Condition::Fill; + cells++; + size++; + + double cellss_coefficient = double(cells) / buffers_size; + if (cellss_coefficient >= rehashCoefficient) ReHash(); +} + +void HashTable::Remove(std::size_t value) { + size_t hash = FirstHashFunc(value) % buffers_size; + std::size_t count = 0; + while (cell_conditions[hash] != Condition::Empty) { + if (t_container[hash] == value && + cell_conditions[hash] == Condition::Fill) { + cell_conditions[hash] = Condition::Deleted; + size--; + break; + } + if (t_container[hash] == value && + cell_conditions[hash] == Condition::Deleted) + break; + + count++; + hash = + (FirstHashFunc(value) + SecondHashFunc(value) * count) % buffers_size; + } +} \ 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 00000000..8096189a --- /dev/null +++ b/task_08/src/hash_table.hpp @@ -0,0 +1,41 @@ +#pragma once +#include + +class HashTable { + public: + HashTable() { + cells = 0; + size = 0; + buffers_size = DefaultBufferSize; + t_container = std::vector(buffers_size); + cell_conditions = std::vector(buffers_size, Condition::Empty); + } + + bool Contains(std::size_t value); + + void Insert(std::size_t value); + + void Remove(std::size_t value); + + void Clear(); + + size_t Size() { return size; } + + private: + enum class Condition { Fill, Deleted, Empty }; + constexpr static const double rehashCoefficient = 0.7; + constexpr static const double hashCoefficient = 0.618033989; + constexpr static const double DefaultBufferSize = 8; + size_t buffers_size; + size_t size; + std::size_t cells; + std::vector t_container; + std::vector cell_conditions; + + size_t FirstHashFunc(std::size_t key); + size_t SecondHashFunc(std::size_t key); + + void ReSize(); + + void ReHash(); +}; \ No newline at end of file diff --git a/task_08/src/test.cpp b/task_08/src/test.cpp index 5e11617e..12ad5efc 100644 --- a/task_08/src/test.cpp +++ b/task_08/src/test.cpp @@ -1,6 +1,61 @@ - #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(14); + ASSERT_TRUE(table.Contains(14)); +} + +TEST(HashTableTest, RemoveElement) { + HashTable table; + table.Insert(45); + table.Remove(45); + ASSERT_FALSE(table.Contains(45)); +} + +TEST(HashTableTest, ClearTable) { + HashTable table; + table.Insert(41420); + table.Clear(); + ASSERT_EQ(table.Size(), 0); +} + +TEST(HashTableTest, SizeAfterInsertion) { + HashTable table; + table.Insert(245); + table.Insert(301); + ASSERT_EQ(table.Size(), 2); +} + +TEST(HashTableTest, ClearTableWithManyElements) { + HashTable table; + for (int i = 0; i < 1000; ++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, ADD100Delete50Rehash) { + HashTable table; + for (int i = 0; i < 100; i++) table.Insert(i); + for (int i = 0; i <= 50; i++) table.Remove(100 - i); + for (int i = 0; i < 38; i++) table.Insert(i); + ASSERT_EQ(table.Size(), 50); +} \ No newline at end of file diff --git a/task_09/src/money.cpp b/task_09/src/money.cpp new file mode 100644 index 00000000..dd9ff72b --- /dev/null +++ b/task_09/src/money.cpp @@ -0,0 +1,12 @@ +#include "money.hpp" + +#include + +std::size_t CoinExchange(std::size_t sum, std::vector coins) { + std::vector money(sum + 1, 1e9); + money[0] = 0; + for (std::size_t i = 1; i <= sum; i++) + for (std::size_t j : coins) + if (j <= i) money[i] = std::min(money[i], money[i - j] + 1); + return money[sum]; +} \ No newline at end of file diff --git a/task_09/src/money.hpp b/task_09/src/money.hpp new file mode 100644 index 00000000..1e363980 --- /dev/null +++ b/task_09/src/money.hpp @@ -0,0 +1,4 @@ +#pragma once + +#include +std::size_t CoinExchange(std::size_t 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..a09435ab 100644 --- a/task_09/src/test.cpp +++ b/task_09/src/test.cpp @@ -1,4 +1,12 @@ - #include -TEST(TopologySort, Simple) { ASSERT_EQ(1, 1); } +#include "money.hpp" + +TEST(ChangeMoney, Simple) { + ASSERT_EQ(CoinExchange(14, std::vector{4, 5, 1, 10}), 2); + ASSERT_EQ(CoinExchange(21, std::vector{11, 3, 9}), 3); + ASSERT_EQ(CoinExchange(25, std::vector{1, 2, 4, 5}), 5); + ASSERT_EQ(CoinExchange(137, std::vector{4, 3, 7, 19}), 8); + + ASSERT_EQ(CoinExchange(104, std::vector{3, 2, 5, 8, 11}), 10); +} \ No newline at end of file