diff --git a/lib/src/util.hpp b/lib/src/util.hpp
index e69de29b..675809a0 100644
--- a/lib/src/util.hpp
+++ b/lib/src/util.hpp
@@ -0,0 +1,27 @@
+#pragma once
+#include <algorithm>
+#include <cstdlib>
+#include <ctime>
+#include <vector>
+
+template <typename T>
+int Partition(std::vector<T>& arr, int l, int r) {
+  std::srand(std::time(nullptr));
+  int pv_index = l + std::rand() % (r - l + 1);
+  T pivot = arr[pv_index];
+  std::swap(arr[pv_index], arr[(l + r) / 2]);
+  int i = l, j = r;
+  while (i <= j) {
+    while (arr[i] < pivot) {
+      i++;
+    }
+    while (arr[j] > pivot) {
+      j--;
+    }
+    if (i >= j) {
+      break;
+    }
+    std::swap(arr[i++], arr[j--]);
+  }
+  return j;
+}
\ No newline at end of file
diff --git a/task_01/src/test.cpp b/task_01/src/test.cpp
index ef5a86ae..babf52ce 100644
--- a/task_01/src/test.cpp
+++ b/task_01/src/test.cpp
@@ -1,7 +1,7 @@
 
 #include <gtest/gtest.h>
 
-#include "topology_sort.hpp"
+#include "utils.hpp"
 
 TEST(TopologySort, Simple) {
   ASSERT_EQ(1, 1);  // Stack []
diff --git a/task_01/src/topology_sort.cpp b/task_01/src/topology_sort.cpp
deleted file mode 100644
index e53f670c..00000000
--- a/task_01/src/topology_sort.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "topology_sort.hpp"
diff --git a/task_01/src/utils.cpp b/task_01/src/utils.cpp
new file mode 100644
index 00000000..0ee624c5
--- /dev/null
+++ b/task_01/src/utils.cpp
@@ -0,0 +1 @@
+#include "utils.hpp"
diff --git a/task_01/src/topology_sort.hpp b/task_01/src/utils.hpp
similarity index 100%
rename from task_01/src/topology_sort.hpp
rename to task_01/src/utils.hpp
diff --git a/task_02/src/main.cpp b/task_02/src/main.cpp
index 0e4393ba..87ff7786 100644
--- a/task_02/src/main.cpp
+++ b/task_02/src/main.cpp
@@ -1,3 +1,4 @@
 #include <iostream>
 
+#include "stack.hpp"
 int main() { return 0; }
diff --git a/task_02/src/stack.cpp b/task_02/src/stack.cpp
index 8ca89902..06af66bf 100644
--- a/task_02/src/stack.cpp
+++ b/task_02/src/stack.cpp
@@ -2,20 +2,48 @@
 
 #include <algorithm>
 
-void Stack::Push(int value) { data_.push(value); }
+void Stack::Push(int value) {
+  Node* t = new Node();
+  t->value_ = value;
+  if (top_ == nullptr) {
+    top_ = t;
+  } else {
+    t->prev_ = top_;
+    top_ = t;
+  }
+}
+
+bool Stack::CheckTop() {
+  if (Top() == nullptr) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+int Stack::GetTopValue() { return Top()->value_; }
 
 int Stack::Pop() {
-  auto result = data_.top();
-  data_.pop();
-  return result;
+  Node* t = top_;
+  top_ = top_->prev_;
+  int value = t->value_;
+  delete t;
+  return value;
 }
 
-void MinStack::Push(int value) { data_.push_back(value); }
+Stack::Node* Stack::Top() { return top_; }
+void MinStack::Push(int value) {
+  if (data_.CheckTop()) {
+    min_values_.Push(value);
+  } else {
+    min_values_.Push(std::min(value, data_.GetTopValue()));
+  }
+  data_.Push(value);
+}
 
 int MinStack::Pop() {
-  auto result = data_.back();
-  data_.pop_back();
-  return result;
+  int t = min_values_.Pop();
+  return data_.Pop();
 }
 
-int MinStack::GetMin() { return *std::min_element(data_.begin(), data_.end()); }
\ No newline at end of file
+int MinStack::GetMin() { return min_values_.GetTopValue(); }
\ No newline at end of file
diff --git a/task_02/src/stack.hpp b/task_02/src/stack.hpp
index 138ec40f..4445fcd1 100644
--- a/task_02/src/stack.hpp
+++ b/task_02/src/stack.hpp
@@ -1,15 +1,19 @@
 #pragma once
 
-#include <stack>
-#include <vector>
-
 class Stack {
+ private:
+  struct Node {
+    int value_ = 0;
+    Node* prev_ = nullptr;
+  };
+  Node* top_ = nullptr;
+  Node* Top();
+
  public:
   void Push(int value);
   int Pop();
-
- private:
-  std::stack<int> data_;
+  bool CheckTop();
+  int GetTopValue();
 };
 
 class MinStack {
@@ -19,5 +23,6 @@ class MinStack {
   int GetMin();
 
  private:
-  std::vector<int> data_;
+  Stack data_;
+  Stack min_values_;
 };
diff --git a/task_03/src/temp_up_days.cpp b/task_03/src/temp_up_days.cpp
new file mode 100644
index 00000000..57a2c760
--- /dev/null
+++ b/task_03/src/temp_up_days.cpp
@@ -0,0 +1,23 @@
+#include "temp_up_days.hpp"
+
+#include <stack>
+
+std::vector<int> TempUpDayCounter(std::vector<int> temps) {
+  std::stack<Day> days;
+  std::vector<int> result(temps.size(), 0);
+  for (int i = 0; i < temps.size(); i++) {
+    Day d;
+    d.index_ = i;
+    d.temp_ = temps[i];
+    while (!days.empty()) {
+      if (days.top().temp_ < d.temp_) {
+        result[days.top().index_] = d.index_ - days.top().index_;
+        days.pop();
+      } else {
+        break;
+      }
+    }
+    days.push(d);
+  }
+  return result;
+}
\ No newline at end of file
diff --git a/task_03/src/temp_up_days.hpp b/task_03/src/temp_up_days.hpp
new file mode 100644
index 00000000..ab255eb3
--- /dev/null
+++ b/task_03/src/temp_up_days.hpp
@@ -0,0 +1,9 @@
+#pragma once
+#include <vector>
+
+struct Day {
+  int index_;
+  int temp_;
+};
+
+std::vector<int> TempUpDayCounter(std::vector<int> temps);
diff --git a/task_03/src/test.cpp b/task_03/src/test.cpp
index ef5a86ae..539ca88c 100644
--- a/task_03/src/test.cpp
+++ b/task_03/src/test.cpp
@@ -1,8 +1,21 @@
 
 #include <gtest/gtest.h>
 
-#include "topology_sort.hpp"
+#include "temp_up_days.hpp"
 
-TEST(TopologySort, Simple) {
-  ASSERT_EQ(1, 1);  // Stack []
+TEST(TempUpDays, Simple) {
+  ASSERT_EQ(TempUpDayCounter(std::vector<int>{5, 7, 4, 5}),
+            (std::vector<int>{1, 0, 1, 0}));
+  ASSERT_EQ(TempUpDayCounter(std::vector<int>{5, 12, 4, 9, 5, 4, 2}),
+            (std::vector<int>{1, 0, 1, 0, 0, 0, 0}));
+  ASSERT_EQ(TempUpDayCounter(std::vector<int>{2, 6, 17, 7, 3, 4}),
+            (std::vector<int>{1, 1, 0, 0, 1, 0}));
+  ASSERT_EQ(TempUpDayCounter(std::vector<int>{}), std::vector<int>{});
+
+  ASSERT_EQ(TempUpDayCounter(
+                std::vector<int>{70, 41, 86, 49, 31, 71, 39, 79, 24, 46}),
+            (std::vector<int>{2, 1, 0, 2, 1, 2, 1, 0, 1, 0}));
+  ASSERT_EQ(TempUpDayCounter(std::vector<int>{84, 44, 32, 65, 33, 11, 70, 57,
+                                              73, 98, 52, 93}),
+            (std::vector<int>{9, 2, 1, 3, 2, 1, 2, 1, 1, 0, 1, 0}));
 }
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/heap.cpp b/task_04/src/heap.cpp
new file mode 100644
index 00000000..fa06672e
--- /dev/null
+++ b/task_04/src/heap.cpp
@@ -0,0 +1,61 @@
+#include "heap.hpp"
+
+#include <cstddef>
+#include <stdexcept>
+#include <vector>
+
+void Heap::SiftUp(int index) {
+  while (index >= 0 && heap_[index] < heap_[(index - 1) / 2]) {
+    std::swap(heap_[index], heap_[(index - 1) / 2]);
+    index = (index - 1) / 2;
+  }
+}
+
+void Heap::SiftDown(int index) {
+  while (2 * index + 1 < heap_.size()) {
+    int left = 2 * index + 1;
+    int right = 2 * index + 2;
+    int small_child_index = left;
+    if (right < heap_.size() && heap_[right] < heap_[left]) {
+      small_child_index = right;
+    }
+    if (heap_[index] < heap_[small_child_index]) {
+      break;
+    }
+    std::swap(heap_[index], heap_[small_child_index]);
+    index = small_child_index;
+  }
+}
+
+int Heap::Min() {
+  if (Size() == 0) throw std::runtime_error("Empty Heap");
+  int m = heap_[0];
+  std::swap(heap_[0], heap_[heap_.size() - 1]);
+  heap_.pop_back();
+  SiftDown(0);
+  return m;
+}
+
+void Heap::Insert(int value) {
+  heap_.push_back(value);
+  this->SiftUp(heap_.size() - 1);
+}
+
+void Heap::Build(std::vector<int> data) {
+  for (auto x : data) {
+    this->Insert(x);
+  }
+}
+
+int Heap::Size() { return heap_.size(); }
+
+int Heap::Top() {
+  if (Size() == 0) throw std::runtime_error("Empty Heap");
+  return heap_[0];
+}
+
+int FindMin(std::vector<int> data) {
+  Heap heap;
+  heap.Build(data);
+  return heap.Min();
+}
diff --git a/task_04/src/heap.hpp b/task_04/src/heap.hpp
new file mode 100644
index 00000000..29255f59
--- /dev/null
+++ b/task_04/src/heap.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <vector>
+class Heap {
+ public:
+  int Top();
+  int Size();
+  int Min();
+  void Insert(int value);
+  void Build(std::vector<int> data);
+
+ private:
+  std::vector<int> heap_;
+  void SiftUp(int index);
+  void SiftDown(int index);
+};
+
+int FindMin(std::vector<int> data);
\ No newline at end of file
diff --git a/task_04/src/test.cpp b/task_04/src/test.cpp
index 5e11617e..49da1095 100644
--- a/task_04/src/test.cpp
+++ b/task_04/src/test.cpp
@@ -1,6 +1,33 @@
-
 #include <gtest/gtest.h>
 
-TEST(TopologySort, Simple) {
-  ASSERT_EQ(1, 1);  // Stack []
+#include <stdexcept>
+
+#include "heap.hpp"
+
+TEST(HeapMin, Simple) {
+  ASSERT_EQ(FindMin(std::vector<int>{4, 5, 16, 3, 6}), 3);
+  ASSERT_EQ(FindMin(std::vector<int>{29, 25, 10, 13, 14, 23, 4, 6}), 4);
+  ASSERT_EQ(FindMin(std::vector<int>{29, 17, 16, 27, 6, 11}), 6);
+}
+
+TEST(EmptyHeap, Simple) {
+  Heap empty_heap;
+
+  ASSERT_EQ(empty_heap.Size(), 0);
+  EXPECT_THROW(empty_heap.Top(), std::runtime_error);
+  EXPECT_THROW(empty_heap.Min(), std::runtime_error);
 }
+
+TEST(Heap, Simple) {
+  Heap heap;
+  heap.Insert(5);
+  heap.Insert(3);
+
+  ASSERT_EQ(heap.Size(), 2);
+  ASSERT_EQ(heap.Top(), 3);
+
+  ASSERT_EQ(heap.Min(), 3);
+
+  ASSERT_EQ(heap.Size(), 1);
+  ASSERT_EQ(heap.Top(), 5);
+}
\ No newline at end of file
diff --git a/task_05/src/main.cpp b/task_05/src/main.cpp
index 0e4393ba..c2134b68 100644
--- a/task_05/src/main.cpp
+++ b/task_05/src/main.cpp
@@ -1,3 +1,6 @@
 #include <iostream>
+#include <vector>
+
+#include "qsort.hpp"
 
 int main() { return 0; }
diff --git a/task_05/src/qsort.cpp b/task_05/src/qsort.cpp
new file mode 100644
index 00000000..e69de29b
diff --git a/task_05/src/qsort.hpp b/task_05/src/qsort.hpp
new file mode 100644
index 00000000..63752ae9
--- /dev/null
+++ b/task_05/src/qsort.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <iostream>
+#include <util.hpp>
+#include <vector>
+
+template <typename T>
+void QuickSort(std::vector<T>& arr, int l, int r) {
+  if (l < r) {
+    int q = Partition(arr, l, r);
+    QuickSort(arr, l, q);
+    QuickSort(arr, q + 1, r);
+  }
+}
diff --git a/task_05/src/test.cpp b/task_05/src/test.cpp
index 5e11617e..4c48f0d8 100644
--- a/task_05/src/test.cpp
+++ b/task_05/src/test.cpp
@@ -1,6 +1,36 @@
-
 #include <gtest/gtest.h>
 
-TEST(TopologySort, Simple) {
-  ASSERT_EQ(1, 1);  // Stack []
+#include <vector>
+
+#include "qsort.hpp"
+
+TEST(Qsort, Simple1) {
+  std::vector<int> vec = {77, 42, 19, 53, 18, 20};
+  QuickSort<int>(vec, 0, vec.size() - 1);
+  ASSERT_EQ((vec), (std::vector<int>{18, 19, 20, 42, 53, 77}));
+}
+
+TEST(Qsort, Simple2) {
+  std::vector<double> vec2{12.75, 5.3, 1.1, 23.223, -13.1, 37.37};
+  QuickSort<double>(vec2, 0, vec2.size() - 1);
+  ASSERT_EQ((vec2),
+            (std::vector<double>{-13.1, 1.1, 5.3, 12.75, 23.223, 37.37}));
+}
+
+TEST(Qsort, Simple3) {
+  std::vector<int> vec3 = {-1, 2, -1, 3, 4, 5, 2};
+  QuickSort<int>(vec3, 0, vec3.size() - 1);
+  ASSERT_EQ((vec3), (std::vector<int>{-1, -1, 2, 2, 3, 4, 5}));
+}
+
+TEST(Qsort, Simple4) {
+  std::vector<int> vec4{2, 4, 2, 1, 3, 4, 1};
+  QuickSort<int>(vec4, 0, vec4.size() - 1);
+  ASSERT_EQ((vec4), (std::vector<int>{1, 1, 2, 2, 3, 4, 4}));
+}
+
+TEST(Qsort, Simple5) {
+  std::vector<int> vec5{};
+  QuickSort<int>(vec5, 0, vec5.size() - 1);
+  ASSERT_EQ((vec5), std::vector<int>{});
 }
diff --git a/task_06/src/order_stats.hpp b/task_06/src/order_stats.hpp
new file mode 100644
index 00000000..9df85de1
--- /dev/null
+++ b/task_06/src/order_stats.hpp
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <ctime>
+#include <vector>
+
+template <class T>
+int Partition(std::vector<T>& data, int l, int r) {
+  std::srand(std::time(nullptr));
+  int pivot_pos = l + std::rand() % (r - l);
+  if (pivot_pos != r - 1) {
+    std::swap(data[r - 1], data[pivot_pos]);
+  }
+
+  int i = l, j = l;
+  T pivot = data[r - 1];
+  while (j < r - 1) {
+    if (data[j] <= pivot) {
+      std::swap(data[i++], data[j]);
+    }
+    j++;
+  }
+  if (i != r - 1) {
+    std::swap(data[i], data[r - 1]);
+  }
+  return i;
+}
+
+template <class T>
+T FindKStatistics(std::vector<T>& data, int l, int r, int k) {
+  int lastPivotPos = 0, left = l, right = r;
+  while (left < right) {
+    if ((lastPivotPos = Partition(data, left, right)) == k) {
+      return data[lastPivotPos];
+    } else if (lastPivotPos > k) {
+      right = lastPivotPos;
+    } else {
+      left = lastPivotPos + 1;
+    }
+  }
+  return data[lastPivotPos];
+}
diff --git a/task_06/src/test.cpp b/task_06/src/test.cpp
index 5e11617e..dffc0874 100644
--- a/task_06/src/test.cpp
+++ b/task_06/src/test.cpp
@@ -1,6 +1,29 @@
-
 #include <gtest/gtest.h>
 
-TEST(TopologySort, Simple) {
-  ASSERT_EQ(1, 1);  // Stack []
+#include <vector>
+
+#include "order_stats.hpp"
+
+TEST(OrderStats, Simple1) {
+  std::vector<int> v{50, 82, 11, 64, 66, 57, 35};
+  ASSERT_EQ(FindKStatistics(v, 0, v.size(), 3), 57);
+}
+TEST(OrderStats, Simple2) {
+  std::vector<int> v{
+      40, 99, 63, 22, 37, 60, 61, 8, 84, 97,
+  };
+  ASSERT_EQ(FindKStatistics(v, 0, v.size(), 5), 61);
+}
+TEST(OrderStats, Simple3) {
+  std::vector<int> v{69, 91, 69, 64, 18, 76, 28, 9, 59, 40, 22, 48};
+  ASSERT_EQ(FindKStatistics(v, 0, v.size(), 0), 9);
+}
+TEST(OrderStats, Simple4) {
+  std::vector<double> v{84.68, 39.62, 36.57, 17.44, 34.22, 66.11, 57.68, 1.58};
+  ASSERT_EQ(FindKStatistics(v, 0, v.size(), 2), 34.22);
+}
+
+TEST(OrderStats, Simple5) {
+  std::vector<char> v{'d', 's', 'a', 'b'};
+  ASSERT_EQ(FindKStatistics(v, 0, v.size(), 1), 'b');
 }
diff --git a/task_07/src/test.cpp b/task_07/src/test.cpp
index 5e11617e..dbda586a 100644
--- a/task_07/src/test.cpp
+++ b/task_07/src/test.cpp
@@ -1,6 +1,56 @@
-
 #include <gtest/gtest.h>
 
-TEST(TopologySort, Simple) {
-  ASSERT_EQ(1, 1);  // Stack []
+#include <vector>
+
+#include "tree.hpp"
+
+TEST(AVLTree, EmptyTree) {
+  Tree<int> avl;
+  ASSERT_EQ(avl.Contains(10), false);
+  ASSERT_EQ(avl.Contains(5), false);
+  ASSERT_EQ(avl.Contains(0), false);
+}
+
+TEST(AVLTree, AddElements) {
+  Tree<int> avl;
+  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);
+}
+
+TEST(AVLTree, RemoveElements) {
+  Tree<int> avl;
+  avl.Push(10);
+  avl.Push(5);
+  avl.Push(15);
+  avl.Pop(5);
+  ASSERT_EQ(avl.Contains(5), false);
+}
+
+TEST(AVLTree, ContainsMethod) {
+  Tree<int> avl;
+  avl.Push(10);
+  avl.Push(5);
+  ASSERT_EQ(avl.Contains(10), true);
+  ASSERT_EQ(avl.Contains(5), true);
+  ASSERT_EQ(avl.Contains(15), false);
 }
+
+TEST(AVLTree, RemoveNonExistentElement) {
+  Tree<int> avl;
+  avl.Push(10);
+  avl.Push(5);
+  avl.Pop(15);
+  ASSERT_EQ(avl.Contains(15), false);
+}
+
+TEST(AVLTree, RemoveInEmptyTree) {
+  Tree<int> avl;
+  ASSERT_EQ(avl.Contains(13), false);
+  avl.Pop(13);
+  ASSERT_EQ(avl.Contains(13), false);
+  ASSERT_EQ(avl.Contains(37), false);
+}
\ 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 00000000..f4a89e6e
--- /dev/null
+++ b/task_07/src/tree.hpp
@@ -0,0 +1,162 @@
+#pragma once
+
+#include <algorithm>
+#include <cstddef>
+
+template <typename T>
+struct Node {
+  T key;
+  unsigned int height = 1;
+  Node* left = nullptr;
+  Node* right = nullptr;
+  Node(T k) : key{k} {};
+};
+
+template <typename T>
+class Tree {  // AVl-tree
+ public:
+  void Push(int k);
+  void Pop(int k);
+  bool Contains(int k);
+
+ private:
+  unsigned int Height(Node<T>* node_ptr);
+  int BFactor(Node<T>* node_ptr);
+  void FixHeight(Node<T>* node_ptr);
+  Node<T>* RotateRight(Node<T>* node_ptr);
+  Node<T>* RotateLeft(Node<T>* node_ptr);
+  Node<T>* Balance(Node<T>* node_ptr);
+  Node<T>* Insert(Node<T>* node_ptr, T k);
+  Node<T>* FindMin(Node<T>* node_ptr);
+  Node<T>* RemoveMin(Node<T>* node_ptr);
+  Node<T>* Remove(Node<T>* node_ptr, int k);
+  Node<T>* Find(Node<T>* node_ptr, int k);
+  Node<T>* root_ = nullptr;
+};
+
+template <typename T>
+void Tree<T>::Push(int k) {
+  root_ = Insert(root_, k);
+}
+template <typename T>
+void Tree<T>::Pop(int k) {
+  root_ = Remove(root_, k);
+}
+template <typename T>
+bool Tree<T>::Contains(int k) {
+  return Find(root_, k) ? true : false;
+}
+
+template <typename T>
+unsigned int Tree<T>::Height(Node<T>* node_ptr) {
+  return node_ptr ? node_ptr->height : 0;
+}
+
+template <typename T>
+int Tree<T>::BFactor(Node<T>* node_ptr) {
+  return Height(node_ptr->right) - Height(node_ptr->left);
+}
+
+template <typename T>
+void Tree<T>::FixHeight(Node<T>* node_ptr) {
+  unsigned int hl = Height(node_ptr->left);
+  unsigned int hr = Height(node_ptr->right);
+  node_ptr->height = std::max(hl, hr) + 1;
+}
+
+template <typename T>
+Node<T>* Tree<T>::RotateRight(Node<T>* node_ptr) {
+  Node<T>* q = node_ptr->left;
+  node_ptr->left = q->right;
+  q->right = node_ptr;
+  FixHeight(node_ptr);
+  FixHeight(q);
+  return q;
+}
+
+template <typename T>
+Node<T>* Tree<T>::RotateLeft(Node<T>* node_ptr) {
+  Node<T>* q = node_ptr->right;
+  node_ptr->right = q->left;
+  q->left = node_ptr;
+  FixHeight(q);
+  FixHeight(node_ptr);
+  return q;
+}
+
+template <typename T>
+Node<T>* Tree<T>::Balance(Node<T>* node_ptr) {
+  FixHeight(node_ptr);
+  if (BFactor(node_ptr) == 2) {
+    if (BFactor(node_ptr->right) < 0)
+      node_ptr->right = RotateRight(node_ptr->right);
+    return RotateLeft(node_ptr);
+  }
+  if (BFactor(node_ptr) == -2) {
+    if (BFactor(node_ptr->left) > 0)
+      node_ptr->left = RotateLeft(node_ptr->left);
+    return RotateRight(node_ptr);
+  }
+  return node_ptr;
+}
+
+template <typename T>
+Node<T>* Tree<T>::Insert(Node<T>* node_ptr, T k) {
+  if (!node_ptr) return new Node(k);
+  if (k < node_ptr->key)
+    node_ptr->left = Insert(node_ptr->left, k);
+  else
+    node_ptr->right = Insert(node_ptr->right, k);
+  return Balance(node_ptr);
+}
+
+template <typename T>
+Node<T>* Tree<T>::FindMin(Node<T>* node_ptr) {
+  return node_ptr->left ? FindMin(node_ptr->left) : node_ptr;
+}
+
+template <typename T>
+Node<T>* Tree<T>::RemoveMin(Node<T>* node_ptr) {
+  if (node_ptr->left == nullptr) {
+    return node_ptr->right;
+  }
+  node_ptr->left = RemoveMin(node_ptr->left);
+  return Balance(node_ptr);
+}
+
+template <typename T>
+Node<T>* Tree<T>::Remove(Node<T>* node_ptr, int k) {
+  if (!node_ptr) {
+    return nullptr;
+  }
+  if (k < node_ptr->key) {
+    node_ptr->left = Remove(node_ptr->left, k);
+  } else if (k > node_ptr->key) {
+    node_ptr->right = Remove(node_ptr->right, k);
+  } else {
+    Node<T>* l = node_ptr->left;
+    Node<T>* r = node_ptr->right;
+    delete node_ptr;
+    if (!r) {
+      return l;
+    }
+    Node<T>* m = FindMin(r);
+    m->right = RemoveMin(r);
+    m->left = l;
+    return Balance(m);
+  }
+  return Balance(node_ptr);
+}
+
+template <typename T>
+Node<T>* Tree<T>::Find(Node<T>* node_ptr, int k) {
+  if (node_ptr == nullptr || node_ptr->key == k) {
+    return node_ptr;
+  }
+  if (k < node_ptr->key) {
+    return Find(node_ptr->left, k);
+  }
+  if (k > node_ptr->key) {
+    return Find(node_ptr->right, k);
+  }
+}
\ No newline at end of file
diff --git a/task_08/src/hashtable.cpp b/task_08/src/hashtable.cpp
new file mode 100644
index 00000000..64c60604
--- /dev/null
+++ b/task_08/src/hashtable.cpp
@@ -0,0 +1,89 @@
+#include "hashtable.hpp"
+
+#include <cmath>
+
+unsigned HashTable::HashFunction1(int key) {
+  return floor(buffer_size_ * ((key * HashCoeff) - floor(key * HashCoeff)));
+}
+
+unsigned HashTable::HashFunction2(int key) {
+  return (key * buffer_size_ - 1) % buffer_size_;
+}
+
+void HashTable::Resize() {
+  buffer_size_ *= 2;
+  table_.resize(buffer_size_);
+  cell_status_.resize(buffer_size_);
+}
+
+void HashTable::Clear() {
+  size_ = 0;
+  used_cell_size_ = 0;
+  for (int i = 0; i < buffer_size_; i++) {
+    cell_status_[i] = Status::Empty;
+  }
+}
+void HashTable::Rehash() {
+  std::vector<int> temp;
+  for (int i = 0; i < buffer_size_; i++) {
+    if (cell_status_[i] == Status::Fill) {
+      temp.push_back(table_[i]);
+    }
+  }
+  Resize();
+  Clear();
+  for (int i = 0; i < temp.size(); i++) {
+    Insert(temp[i]);
+  }
+}
+
+void HashTable::Insert(int key) {
+  unsigned hash = HashFunction1(key) % buffer_size_;
+  int counter = 0;
+  while (cell_status_[hash] == Status::Fill) {
+    if (table_[hash] == key) {
+      return;
+    }
+    counter++;
+    hash = (HashFunction1(key) + counter * HashFunction2(key)) % buffer_size_;
+  }
+  table_[hash] = key;
+  cell_status_[hash] = Status::Fill;
+  used_cell_size_++;
+  size_++;
+
+  double fill_coeff = double(used_cell_size_) / buffer_size_;
+  if (fill_coeff >= RehashSize) Rehash();
+}
+
+void HashTable::Remove(int key) {
+  unsigned hash = HashFunction1(key) % buffer_size_;
+  int counter = 0;
+  while (cell_status_[hash] != Status::Empty) {
+    if (table_[hash] == key && cell_status_[hash] == Status::Deleted) {
+      return;
+    }
+    if (table_[hash] == key && cell_status_[hash] == Status::Fill) {
+      size_--;
+      cell_status_[hash] = Status::Deleted;
+      return;
+    }
+    counter++;
+    hash = (HashFunction1(key) + counter * HashFunction2(key)) % buffer_size_;
+  }
+}
+
+bool HashTable::Contains(int key) {
+  unsigned hash = HashFunction1(key) % buffer_size_;
+  int counter = 0;
+  while (cell_status_[hash] != Status::Empty) {
+    if (table_[hash] == key && cell_status_[hash] == Status::Fill) {
+      return true;
+    }
+    counter++;
+    hash = (HashFunction1(key) + counter * HashFunction2(key)) % buffer_size_;
+  }
+  return false;
+}
+
+unsigned HashTable::Size() { return size_; }
\ No newline at end of file
diff --git a/task_08/src/hashtable.hpp b/task_08/src/hashtable.hpp
new file mode 100644
index 00000000..4d4027b3
--- /dev/null
+++ b/task_08/src/hashtable.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <vector>
+
+class HashTable {
+ public:
+  HashTable()
+      : size_{0},
+        buffer_size_{DefaultSize},
+        used_cell_size_{0},
+        table_{std::vector<int>(buffer_size_)},
+        cell_status_{std::vector<Status>(buffer_size_, Status::Empty)} {};
+  void Insert(int key);
+  void Remove(int key);
+  bool Contains(int key);
+  unsigned Size();
+
+ private:
+  constexpr static const int DefaultSize = 8;
+  constexpr static const double RehashSize = 0.75;
+  constexpr static const double HashCoeff = 0.61803398;
+  unsigned size_;  // занятые ячейки без учёта Deleted
+  unsigned buffer_size_;
+  unsigned used_cell_size_;  // занятые ячейки с учётом Deleted
+  std::vector<int> table_;
+  enum class Status { Empty, Deleted, Fill };
+  std::vector<Status> cell_status_;
+
+  unsigned HashFunction1(int key);
+  unsigned HashFunction2(int key);
+  void Rehash();
+  void Resize();
+  void Clear();
+};
diff --git a/task_08/src/test.cpp b/task_08/src/test.cpp
index 5e11617e..3e12290c 100644
--- a/task_08/src/test.cpp
+++ b/task_08/src/test.cpp
@@ -1,6 +1,34 @@
-
 #include <gtest/gtest.h>
 
-TEST(TopologySort, Simple) {
-  ASSERT_EQ(1, 1);  // Stack []
+#include "hashtable.hpp"
+
+TEST(Hashtable, Simple) {
+  HashTable table;
+  table.Insert(5);
+  table.Insert(17);
+  table.Insert(33);
+  ASSERT_EQ(table.Contains(17), true);
+  ASSERT_EQ(table.Size(), 3);
+  table.Remove(5);
+  ASSERT_EQ(table.Contains(5), false);
+}
+
+TEST(Hashtable, EmptyTable) {
+  HashTable table;
+  ASSERT_EQ(table.Size(), 0);
+  ASSERT_EQ(table.Contains(10), false);
 }
+
+TEST(Hashtable, RemoveNonExistentElement) {
+  HashTable table;
+  table.Insert(7);
+  table.Remove(10);
+  ASSERT_EQ(table.Size(), 1);
+}
+
+TEST(Hashtable, InsertDuplicateElement) {
+  HashTable table;
+  table.Insert(5);
+  table.Insert(5);
+  ASSERT_EQ(table.Size(), 1);
+}
\ No newline at end of file
diff --git a/task_09/src/change_money.cpp b/task_09/src/change_money.cpp
new file mode 100644
index 00000000..399b30da
--- /dev/null
+++ b/task_09/src/change_money.cpp
@@ -0,0 +1,16 @@
+#include "change_money.hpp"
+
+#include <vector>
+
+int CoinExchange(int sum, std::vector<int> coins) {
+  std::vector<int> 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);
+      }
+    }
+  }
+  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 <vector>
+int CoinExchange(int sum, std::vector<int> coins);
\ No newline at end of file
diff --git a/task_09/src/test.cpp b/task_09/src/test.cpp
index 869094dd..b702efd2 100644
--- a/task_09/src/test.cpp
+++ b/task_09/src/test.cpp
@@ -1,4 +1,14 @@
-
 #include <gtest/gtest.h>
 
-TEST(TopologySort, Simple) { ASSERT_EQ(1, 1); }
+#include <vector>
+
+#include "change_money.hpp"
+
+TEST(ChangeMoney, Simple) {
+  ASSERT_EQ(CoinExchange(14, std::vector<int>{1, 2, 5, 10}), 3);
+  ASSERT_EQ(CoinExchange(21, std::vector<int>{1, 3, 6}), 4);
+  ASSERT_EQ(CoinExchange(25, std::vector<int>{1, 2, 3, 5}), 5);
+  ASSERT_EQ(CoinExchange(137, std::vector<int>{1, 3, 7, 19}), 9);
+
+  ASSERT_EQ(CoinExchange(14, std::vector<int>{1, 2, 5, 7, 10}), 2);
+}