├── presentations ├── Lecture_1.pdf ├── Lecture_2.pdf └── Lecture_3.pdf ├── materials ├── Simple queue │ ├── .clang-format │ ├── test.cpp │ └── Queue.hpp ├── Tree example │ ├── main.cpp │ └── BinaryTree.hpp ├── Repetition │ ├── Pointers.cpp │ ├── Scope.cpp │ ├── CharTricks.cpp │ └── NewDeleteExpression.cpp ├── How to inherit from stl data structures │ ├── MinStack.hpp │ └── TreeChar.cpp └── Comparator example │ ├── test.cpp │ └── MergeSort.hpp ├── README.md ├── program.md └── code-review.md /presentations/Lecture_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TieBeTie/DataStructuresAndAlgorithms-I/HEAD/presentations/Lecture_1.pdf -------------------------------------------------------------------------------- /presentations/Lecture_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TieBeTie/DataStructuresAndAlgorithms-I/HEAD/presentations/Lecture_2.pdf -------------------------------------------------------------------------------- /presentations/Lecture_3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TieBeTie/DataStructuresAndAlgorithms-I/HEAD/presentations/Lecture_3.pdf -------------------------------------------------------------------------------- /materials/Simple queue/.clang-format: -------------------------------------------------------------------------------- 1 | # options: https://clang.llvm.org/docs/ClangFormatStyleOptions.html 2 | BasedOnStyle: Google 3 | IndentWidth: 2 -------------------------------------------------------------------------------- /materials/Tree example/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "BinaryTree.hpp" 4 | 5 | using std::cin; 6 | 7 | // recursion <-> loop 8 | int Add(int n) { 9 | if (n == 0) { 10 | return 0; 11 | } 12 | return Add(n - 1); 13 | } 14 | 15 | void f1() { 16 | for (int i = 0; i < 10; ++i) { 17 | // some code 18 | } 19 | } 20 | 21 | void f2(int i = 0) { 22 | if (i >= 10) { 23 | return; 24 | } 25 | // some code 26 | f2(++i); 27 | } 28 | 29 | int main() { 30 | Add(8); 31 | size_t N; 32 | BinaryTree *bin_tree = new BinaryTree(); 33 | int key; 34 | 35 | for (size_t i = 0; i < N; i++) { 36 | cin >> key; 37 | bin_tree->Insert(key); 38 | } 39 | InOrderTraversal(bin_tree->GetRoot()); 40 | delete bin_tree; 41 | } 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Data Structures and Algorithms I 2 | Welcome to the repository for the Algorithms and Data Structures I course offered by the English-speaking stream of MIPT. 3 | 4 | # Course Overview: 5 | This repository hosts materials, assignments, and resources for the Algorithms and Data Structures I course. The course covers advanced topics in algorithms and data structures, providing students with a deeper understanding of complex algorithms and their applications. 6 | 7 | 8 | - [Course program](/program.md) 9 | 10 | - [Practices materials](/materials/materials.md) 11 | 12 | - [Rating](https://docs.google.com/spreadsheets/d/1vLa4rnYe5Bz9ZMRgnPE4m2knCd-NnsLclWbcs8HxYJQ/edit?pli=1#gid=0) 13 | 14 | ###### Code review 15 | 16 | - [How to pass code-review](/code-review.md) 17 | 18 | Happy learning! 🚀 19 | -------------------------------------------------------------------------------- /materials/Simple queue/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "Queue.hpp" 4 | 5 | using std::cout; 6 | 7 | int main() { 8 | { Queue a; } 9 | Queue b(1); 10 | b.PushFront(1); 11 | cout << b.Front() << ' ' << b.Back() << ' ' << b.Size() << '\n'; 12 | b.PushFront(2); 13 | b.PopBack(); 14 | cout << b.Front() << ' ' << b.Back() << ' ' << b.Size() << '\n'; 15 | b.PushFront(3); 16 | cout << b.Front() << ' ' << b.Back() << ' ' << b.Size() << '\n'; 17 | b.PushFront(4); 18 | b.PopBack(); 19 | cout << b.Front() << ' ' << b.Back() << ' ' << b.Size() << '\n'; 20 | b.PushFront(5); 21 | cout << b.Front() << ' ' << b.Back() << ' ' << b.Size() << '\n'; 22 | b.PopBack(); 23 | b.PopBack(); 24 | b.PushFront(6); 25 | cout << b.Front() << ' ' << b.Back() << ' ' << b.Size() << '\n'; 26 | std::cout << -2 % 5; 27 | } 28 | -------------------------------------------------------------------------------- /program.md: -------------------------------------------------------------------------------- 1 | ## Course program 2 | 3 | #### Unit 1: Introduction 4 | 1. Introduction. Complexity. RAM-model. 5 | 2. Linked Lists. Stack implementation using a linked list or an array. Keeping minimum in a stack. Correct brackets sequence checking. Monotonic stack 6 | 7 | #### Unit 2: Sorting 8 | 1. Sortings. Lower bound for comparisons in the sort. Insertion sort. Bubble Sort. Selection Sort. 9 | 2. Quick Sort. Master Theorem. 10 | 3. Merge Sort. 11 | 4. Binary Heap. Sift Up, Sift Down, Insert, GetMin, ExtractMin and DecreaseKey. Heap Sort 12 | 13 | #### Unit 3: Trees 14 | 1. Binary Search Trees. Insert & Delete & BST Sort. 15 | 2. Balanced Binary search Trees. AVL Tree. Height of AVL Tree on n nodes. 16 | 17 | #### Unit 4: Hashing 18 | 1. Hash Table Chaining. Insert & Delete & Search 19 | 2. Hash Table Open Addressing. Insert & Delete & Search 20 | 3. Bloom Filter. Insert & Search. Applications 21 | 22 | -------------------------------------------------------------------------------- /materials/Repetition/Pointers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::cin; 5 | using std::cout; 6 | int main() { 7 | int a = 1; 8 | int b; 9 | // the pointer contains address just a hexadecimal number - the number of a 10 | // cell in a limited area of RAM (Stack, Static, and Heap 11 | // https://stackoverflow.com/questions/408670/stack-static-and-heap-in-c) 12 | int* px; 13 | px = &a; // *px point to 1 too 14 | b = *px; // b = 1 15 | 16 | a = 10; 17 | 18 | cout << &a << '\n'; // take address of a 19 | cout << a << '\n'; // 10 20 | cout << *px << '\n'; // dereference px (take an object in memory) 21 | cout << px << '\n'; // address (hexadecimal 64 bit number) 22 | 23 | px = nullptr; 24 | if (!px /*converts to !px == 1*/) { 25 | } 26 | if (px != NULL /*same thing NULL is 0 or (void*)0 */) { 27 | } 28 | // but it C++20, we should use nullptr 29 | if (px != nullptr) { 30 | // that's ok 31 | } 32 | cout << px << '\n'; 33 | } 34 | -------------------------------------------------------------------------------- /materials/Repetition/Scope.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Each name that appears in a C++ program is only visible in some possibly 4 | // discontiguous portion of the source code called its scope. 5 | 6 | // global scope 7 | int i = 1; // always accessible using :: 8 | 9 | int main() { 10 | if (int i = 2; i < 5) { 11 | std::cout << i; // 2 12 | } 13 | 14 | int i = 3; 15 | { 16 | int i = 4; 17 | std::cout << i << '\n'; // 4, i = 3 is not accessible 18 | { 19 | int i = 5; 20 | std::cout << i << '\n'; // 5, i = 3 and i = 4 is not accessible 21 | } 22 | } 23 | 24 | { 25 | /*statement 1*/ 26 | while (/*condition &&*/ true) { 27 | /*some code*/ 28 | /*statement 2*/ 29 | } 30 | } 31 | // <=> 32 | for (/*statement 1*/; /*condition*/; /*statement 2*/) { 33 | /*some code*/ 34 | } 35 | // we can do something like this 36 | for (std::cin >> i; i < 5; std::cin >> i) { 37 | std::cout << i << ' '; 38 | } 39 | // or this 40 | for (;;) 41 | ; 42 | } -------------------------------------------------------------------------------- /materials/Repetition/CharTricks.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::cin; 5 | using std::cout; 6 | 7 | int main() { 8 | char c; 9 | std::cin >> c; 10 | // https://en.wikipedia.org/wiki/ASCII#Printable_characters tables are 11 | // different, we using just order The following code above will work for each 12 | // ASCII standard 13 | // if ('a' <= c <= 'z' || 'A' <= c <= 'Z') 14 | // that is incorrect because 'a' <= c <= 'z' => ('a' <= c) <= 'z' => true/false <= 'z' => 0/1 <= 'z' is always true 15 | if ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') { 16 | // c is letter 17 | } 18 | if ('0' <= c && c <= '9') { 19 | // c is number 20 | } 21 | // Captitalize problem 22 | int lowercase_uppercase_difference = 23 | 'B' - 'b'; // or 'A' - 'a', 'J' - 'j' whatever 24 | /* someone said that this is too long a variable name, 25 | but in your code you have to write comments in addition to just code. 26 | This is where a comment is obviously needed, 27 | but you don't have to do it by naming the variable this way. 28 | Write the code in such a clear way 29 | that you have to write a minimum number of comments. 30 | This way the code will be more readable and nice-looking*/ 31 | if ('a' <= c && c <= 'z') { 32 | std::cout << c + lowercase_uppercase_difference; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /materials/How to inherit from stl data structures/MinStack.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::stack; 6 | 7 | // Overriding means that you are going to inherit from STL container. Don't do 8 | // this! STL containers are not designed for inheriting from them. 9 | // For instance, std::stack doesn't contain virtual function specifier 10 | 11 | // template 12 | // class MinStack : public stack> { 13 | // public: 14 | // using TPair = Pair; 15 | // using Base = stack; 16 | // void push(const T& value) { 17 | // Base::emplace( 18 | // value, Base::empty() ? value : std::min(value, 19 | // Base::top().min_value)); 20 | // } 21 | // T GetMin() { return Base::top().min_value; } 22 | // }; 23 | 24 | // Do it like this 25 | template 26 | class MinStack { 27 | public: 28 | void Push(const T& value) { 29 | stack_.emplace( 30 | value, stack_.empty() ? value : std::min(value, stack_.top().min_value)); 31 | } 32 | T GetMin() { return stack_.top().min_value; } 33 | void Pop() { stack_.pop(); } 34 | 35 | private: 36 | struct Pair { 37 | T value; 38 | T min_value; 39 | Pair(T value, T min_value) { 40 | this->value = value; 41 | this->min_value = min_value; 42 | } 43 | }; 44 | stack stack_; 45 | }; 46 | -------------------------------------------------------------------------------- /materials/Comparator example/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "MergeSort.hpp" 6 | 7 | using std::cout; 8 | 9 | class Date { 10 | public: 11 | Date() = default; 12 | Date(int day, int month, int year) : year_(year), month_(month), day_(day) {} 13 | friend class DateComparator; 14 | // Do not use Print...(...) for printing, use this 15 | friend std::ostream &operator<<(std::ostream &os, const Date &value) { 16 | os << value.day_ << '.' << value.month_ << '.' << value.year_; 17 | return os; 18 | } 19 | 20 | private: 21 | int day_; 22 | int month_; 23 | int year_; 24 | }; 25 | 26 | class DateComparator { 27 | public: 28 | DateComparator() {} 29 | // to reject using, for example: 30 | // DataComparator a; 31 | // DataComparator a(b); 32 | // a = b; 33 | DateComparator(const DateComparator &) = delete; 34 | 35 | DateComparator(DateComparator &&) = delete; 36 | 37 | DateComparator &operator=(DateComparator &&) = delete; 38 | 39 | DateComparator &operator=(DateComparator &r) = delete; 40 | 41 | bool operator()(const Date &l, const Date &r) const { 42 | if (l.year_ != r.year_) { 43 | return l.year_ < r.year_; 44 | } 45 | if (l.month_ != r.month_) { 46 | return l.month_ < r.month_; 47 | } 48 | return l.day_ <= r.day_; 49 | } 50 | }; 51 | 52 | void TestMergeSort() { 53 | Date *dates = 54 | new Date[10]{Date{12, 04, 2001}, Date{12, 04, 2000}, Date{12, 03, 2001}, 55 | Date{15, 04, 2001}, Date{11, 04, 2001}, Date{12, 03, 2005}, 56 | Date{14, 04, 2001}, Date{10, 04, 2000}, Date{12, 04, 2003}, 57 | Date{12, 04, 2007}}; 58 | // MergeSort(dates, 10, DateComparator()); 59 | // or 60 | MergeSort(dates, 10, DateComparator()); 61 | cout << "Dates example:" << '\n'; 62 | for (int i = 0; i < 10; ++i) { 63 | cout << dates[i] << '\n'; 64 | } 65 | delete[] dates; 66 | cout << '\n'; 67 | 68 | int nums[] = {1, 4, 6, 7, 8, 3, 9, 2, 5, 0}; 69 | MergeSort(nums, 10); 70 | cout << "Nums example:" << '\n'; 71 | for (int i = 0; i < 10; ++i) { 72 | cout << nums[i] << ' '; 73 | } 74 | } 75 | 76 | int main() { TestMergeSort(); } -------------------------------------------------------------------------------- /code-review.md: -------------------------------------------------------------------------------- 1 | # How to pass code-review 2 | 3 | 1. To write the code, use [Google C++ Style Guide]. 4 | 2. Before sending code, check the code using [clang-format] and [clang-tidy]. 5 | 3. If you want to use STL library data structures, such as std::vector, std::stack, std:: unordered_map etc in any task of the course, you have to implement them in the theoretical contest to get points. 6 | 4. Using namespace std is not allowed, instead write concrete namespace member, for example, using std::cin; 7 | 5. Constraints is very important, use minimal count of bytes to save the premitive type or if there is no constraints, use primitive type with maximal count of bytes. 8 | 6. Points for the task will leak if memory leaks are found on the code-review. 9 | 7. If a similar code is found, we will be forced to give the cheater a negative score for the problem 10 | 11 | ## Code-review passing algorithm 12 | 13 | 1. Pass tests in the contest. 14 | 2. Create your **own** repository with readme if it doesn't exist 15 | 3. Create a branch ***NameOfTheProblem*** in the repository 16 | 4. Clone your repository 17 | 5. Commit and push your solution to the ***NameOfTheProblem*** branch 18 | 6. Create a pull-request to merge the ***NameOfTheProblem*** branch with the main branch 19 | 7. Do not approve the pull-request. 20 | 8. Add Islam and me to collaborators 21 | 9. Fix the remarks and **send the fixed solution again to the contest**. If the solution is not sent to the contest, it will not be checked. 22 | 10. In pull request comments send the **link to the successfully passed solution**, example: 23 | 24 | https://contest.yandex.ru/contest/47619/run-report/1234567890 25 | 26 | ## Assessment 27 | 28 | ## Tips for passing code-review & contest verification 29 | ### Using linters 30 | 31 | [//]: # 32 | [Google C++ Style Guide]: 33 | [adress sanitazer]: https://github.com/google/sanitizers/wiki/AddressSanitizer 34 | [CLion]: https://www.jetbrains.com/clion 35 | [CLion clang-tidy]: https://www.jetbrains.com/help/clion/clang-tidy-checks-support.html 36 | [CLion clang-format]: https://www.jetbrains.com/help/clion/clangformat-as-alternative-formatter.html 37 | [clang-format]: https://clang.llvm.org/docs/ClangFormat.html 38 | [clang-tidy]: https://clang.llvm.org/extra/clang-tidy.html 39 | 40 | -------------------------------------------------------------------------------- /materials/How to inherit from stl data structures/TreeChar.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | const int EMPTY = 0; 9 | 10 | struct Node { 11 | const char letter; 12 | Node *left = nullptr; 13 | Node *right = nullptr; 14 | 15 | explicit Node(const char other) : letter(other) {} 16 | }; 17 | 18 | int DFS(Node *node, std::unordered_set &set_of_letters, int &result) { 19 | if (node == nullptr) { 20 | return EMPTY; 21 | } 22 | 23 | int letters = 0; 24 | letters |= DFS(node->left, set_of_letters, result); 25 | letters |= DFS(node->right, set_of_letters, result); 26 | letters |= 1 << (node->letter - 'A'); 27 | 28 | if (set_of_letters.count(letters)) { 29 | result = letters; 30 | } 31 | 32 | if (letters != EMPTY) { 33 | set_of_letters.insert(letters); 34 | } 35 | 36 | return letters; 37 | } 38 | 39 | class BinaryTree { 40 | public: 41 | explicit BinaryTree(std::string &str) { 42 | root = nullptr; 43 | int cur_h = 0; 44 | int h = floor(log2(str.size())) + 1; 45 | int i = 0; 46 | root = GrowBinaryTree(str, i, cur_h, h); 47 | } 48 | ~BinaryTree() { Clear(root); } 49 | void Clear(Node *node) { 50 | if (node == nullptr) { 51 | return; 52 | } 53 | Clear(node->left); 54 | Clear(node->right); 55 | delete node; 56 | } 57 | 58 | Node *root; 59 | 60 | private: 61 | Node *GrowBinaryTree(std::string s, int &i, int &cur_h, int h) { 62 | if (i == s.size() || cur_h == h) { 63 | --cur_h; 64 | return nullptr; 65 | } 66 | if (s[i] == '0') { 67 | i++; 68 | --cur_h; 69 | return nullptr; 70 | } 71 | Node *node = new Node(s[i++]); 72 | node->left = GrowBinaryTree(s, i, ++cur_h, h); 73 | node->right = GrowBinaryTree(s, i, ++cur_h, h); 74 | --cur_h; 75 | return node; 76 | } 77 | }; 78 | 79 | int main() { 80 | std::string s; 81 | std::cin >> s; 82 | BinaryTree tree(s); 83 | int result = EMPTY; 84 | std::unordered_set set; 85 | DFS(tree.root, set, result); 86 | 87 | if (result == EMPTY) { 88 | std::cout << "None\n"; 89 | return 0; 90 | } 91 | 92 | for (int i = 0; i < 26; ++i) { 93 | int letter = 1 << i; 94 | if ((result & letter) != 0) { 95 | std::cout << char('A' + i); 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /materials/Simple queue/Queue.hpp: -------------------------------------------------------------------------------- 1 | const size_t DEFAULT_CAPACITY = 16; 2 | 3 | template 4 | class Queue { 5 | public: 6 | Queue(); 7 | Queue(size_t capacity); 8 | ~Queue(); 9 | void PushFront(T value); 10 | bool PopBack(); 11 | T Back() const; 12 | T Front() const; 13 | void Resize(size_t capacity); // change the array capacity 14 | size_t size() const; 15 | void Clear(); 16 | 17 | private: 18 | size_t Mod(size_t i, size_t n) const; 19 | 20 | private: 21 | T* data_; 22 | size_t capacity_; 23 | size_t head_; 24 | size_t size_; 25 | }; 26 | 27 | template 28 | Queue::Queue() : Queue(DEFAULT_CAPACITY) {} 29 | 30 | template 31 | Queue::Queue(size_t capacity) : capacity_{capacity}, head_{0}, size_{0} { 32 | data_ = new T[capacity_]; 33 | } 34 | 35 | template 36 | Queue::~Queue() { 37 | delete[] data_; 38 | } 39 | 40 | template 41 | size_t Queue::size() const { 42 | return size_; 43 | } 44 | 45 | template 46 | void Queue::Clear() { 47 | delete[] data_; 48 | capacity_ = DEFAULT_CAPACITY; 49 | data_ = new T[capacity_]; 50 | head_ = size_ = 0; 51 | } 52 | 53 | template 54 | bool Queue::PopBack() { 55 | if (size_ == capacity_ / 4 && DEFAULT_CAPACITY <= capacity_ / 2) { 56 | Resize(capacity_ / 2); 57 | } 58 | if (size_ != 0) { 59 | --size_; 60 | return true; 61 | } 62 | return false; 63 | } 64 | 65 | template 66 | T Queue::Back() const { 67 | return data_[Mod(head_ + size_ - 1, capacity_)]; 68 | } 69 | 70 | template 71 | T Queue::Front() const { 72 | return data_[Mod(head_, capacity_)]; 73 | } 74 | 75 | template 76 | void Queue::PushFront(T value) { 77 | if (size_ == capacity_) { 78 | Resize(capacity_ * 2); 79 | } 80 | head_ = Mod(--head_, capacity_); 81 | data_[head_] = value; 82 | ++size_; 83 | } 84 | 85 | template 86 | void Queue::Resize(size_t new_capacity) { 87 | T* clipboard = new T[new_capacity]; 88 | for (size_t i = 0, j = head_; i < size_;) { 89 | clipboard[i++] = data_[Mod(j++, capacity_)]; 90 | } 91 | delete[] data_; 92 | data_ = clipboard; 93 | capacity_ = new_capacity; 94 | head_ = 0; 95 | } 96 | 97 | template 98 | size_t Queue::Mod(size_t i, size_t n) const { 99 | return (i % n + n) % n; 100 | } 101 | -------------------------------------------------------------------------------- /materials/Repetition/NewDeleteExpression.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using std::cout; 4 | 5 | int main() { 6 | // new expression 7 | /*Creates and initializes objects 8 | with dynamic storage (Heap) duration, that is, 9 | objects whose lifetime is not limited by the scope 10 | { 11 | I live only here 12 | } 13 | in which they were created. 14 | New expression returns a POINTER to the object.*/ 15 | 16 | int* p1 = new int(4); // value 17 | double* p2 = new double[10]; // array 18 | 19 | // delete expression 20 | /*Destroys object(s) previously allocated 21 | by the new expression and 22 | releases obtained memory area.*/ 23 | 24 | /*delete expression - destroys one non-array object created by a 25 | delete[] expression - destroys an array created by a new[]-expression*/ 26 | 27 | // delete p1; 28 | delete[] p2; 29 | 30 | // Ḿ̵͎̼E̶̲̓M̴̪̓Ö̷̥̜̚R̵͉̃Y̸̝̺͋͝ L̶̗͗̊Ȅ̷͙A̴͍̐K̶̢͔̓̾S̵̡͔͑ 31 | /*The objects created by new-expressions 32 | (objects with dynamic storage (Heap) duration) 33 | persist until the pointer returned by the 34 | new-expression is used in a matching delete-expression. 35 | If the original value of pointer is lost, 36 | the object becomes unreachable and cannot be deallocated: 37 | a memory leak occurs.*/ 38 | 39 | int* p = new int(7); // dynamically allocated int with value 7 40 | p = nullptr; // memory leak :( 41 | p1 = new int(4); // memory leak ;< 42 | 43 | // Double Free 44 | 45 | delete p; // object is not exist 46 | char* p3 = new char('c'); 47 | delete p3; // ok 48 | // delete p3; // double free 49 | 50 | // Create array of pointers 51 | int* array = new int[5]; 52 | 53 | // take element from array 54 | array[3]; 55 | /*<=>*/ 56 | *(array + 3); 57 | 58 | // How to create 2D-arrays? 59 | // 60 | // 61 | // 62 | // 63 | // 64 | // 65 | // 66 | // a is a pointer to pointers 67 | int** a = new int*[3]; 68 | // and create arrays 69 | for (int i = 0; i < 3; ++i) { 70 | a[i] = new int[2]{42}; // 42 0 71 | } 72 | for (int i = 0; i < 3; ++i) { 73 | for (int j = 0; j < 2; ++j) { 74 | cout << (a[i])[j] /*a[i][j]*/ << '=' << *(*(a + i) + j) << ' '; 75 | } 76 | cout << '\n'; 77 | } 78 | // Then we should delete whole pointers; 79 | for (int i = 0; i < 3; ++i) { 80 | delete[] a[i]; 81 | } 82 | // And the pointer to pointers (to addresses (to numbers)) 83 | delete[] a; 84 | } 85 | // 10D arrays??? 86 | // https://www.youtube.com/watch?v=xFtYY-Rmf1Y 87 | // or 88 | // N-D arrays 89 | // https://www.geeksforgeeks.org/how-to-declare-a-2d-array-dynamically-in-c-using-new-operator/ 90 | -------------------------------------------------------------------------------- /materials/Comparator example/MergeSort.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | // This code defines a struct IsLess, which is a function object that returns 3 | // true if its left-hand operand is less than its right-hand operand. 4 | template 5 | struct IsLess { 6 | bool operator()(const T &l, const T &r) const { return l < r; } 7 | }; 8 | 9 | /* In this function declaration, the template arguments T and TLess are used to 10 | * provide a generic implementation of the Merge function for any type T and any 11 | * comparison function object type TLess. The last parameter is_less is a 12 | * function object that is used to compare elements of type T. This parameter is 13 | * optional, and its default value is IsLess, which is a function object that 14 | * returns true if its left-hand operand is less than its right-hand operand. By 15 | * default, the Merge function uses the IsLess function object to compare 16 | * elements, but you can provide a custom function object that implements a 17 | * different comparison algorithm if needed. 18 | */ 19 | 20 | /* This function merges two SORTED 21 | * arrays (l_array and r_array) of sizes l_size and r_size respectively, and 22 | * stores the result in a dynamically allocated buffer array. The result is 23 | * sorted according to the comparison function object is_less. 24 | */ 25 | template > 26 | void Merge(T *l_array, T *r_array, int l_size, int r_size, 27 | const TLess &is_less = TLess()) { 28 | T *buffer = new T[l_size + r_size]; 29 | 30 | // Merge the two arrays, maintaining the sorted order. 31 | int l_it = 0, r_it = 0; 32 | while (l_it < l_size && r_it < r_size) { 33 | if (is_less(l_array[l_it], r_array[r_it])) { 34 | // buffer[l_it + r_it] = l_array[l_it++]; 35 | // => 36 | // l_array[l_it]; l_it++; buffer[l_it + r_it]; :( 37 | buffer[l_it++ + r_it] = l_array[l_it]; 38 | } else { 39 | buffer[l_it + r_it++] = r_array[r_it]; 40 | } 41 | } 42 | 43 | // Copy any remaining elements from the left array to the buffer. 44 | while (l_it < l_size) { 45 | buffer[l_it++ + r_it] = l_array[l_it]; 46 | } 47 | 48 | // Copy any remaining elements from the right array to the buffer. 49 | while (r_it < r_size) { 50 | buffer[l_it + r_it++] = r_array[r_it]; 51 | } 52 | 53 | // Copy the sorted elements back into the original array. 54 | for (int i = 0; i < l_size + r_size; l_array[i++] = buffer[i]) 55 | ; 56 | delete[] buffer; 57 | } 58 | 59 | // This function sorts an array of n elements using the MergeSort algorithm. 60 | // The elements are sorted according to the comparison function object is_less. 61 | template > 62 | void MergeSort(T *base, int n, const TLess &is_less = TLess()) { 63 | // Split the array into smaller subarrays, merge them, and repeat until the 64 | // entire array is sorted. 65 | // split_size / 2 < n - incorrect 66 | for (int split_size = 1; split_size < n; split_size *= 2) { 67 | for (int i = 0; i < n - split_size; i += split_size * 2) { 68 | Merge(base + i, base + i + split_size, split_size, 69 | std::min(split_size, n - split_size), is_less); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /materials/Tree example/BinaryTree.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::cout; 5 | 6 | template 7 | struct Node { 8 | T key; 9 | Node *left; 10 | Node *right; 11 | 12 | Node(T x) { 13 | key = x; 14 | left = nullptr; 15 | right = nullptr; 16 | } 17 | }; 18 | 19 | template 20 | void Visit(T key) { 21 | cout << key << " "; 22 | } 23 | 24 | template 25 | void InOrderTraversal(Node *root) { 26 | if (root == nullptr) return; 27 | 28 | std::stack *> states; 29 | Node *tmp = root; 30 | 31 | while (states.size() != 0 || tmp != nullptr) { 32 | while (tmp != nullptr) { 33 | states.push(tmp); 34 | tmp = tmp->left; 35 | } 36 | 37 | tmp = states.top(); 38 | states.pop(); 39 | Visit(tmp->key); 40 | 41 | tmp = tmp->right; 42 | } 43 | } 44 | 45 | template 46 | struct IsLess { 47 | bool IsGreater(const T &l, const T &r) const { return l <= r; } // the same 48 | bool operator()(const T &l, const T &r) const { return l <= r; } // but this is more convenient 49 | }; 50 | 51 | template > 52 | class BinaryTree { 53 | public: 54 | BinaryTree(TLess comparator = TLess()) { 55 | root_ = nullptr; 56 | this->comparator_ = comparator; 57 | } 58 | 59 | BinaryTree(const BinaryTree &) = delete; 60 | 61 | BinaryTree(BinaryTree &&) = delete; 62 | 63 | BinaryTree &operator=(const BinaryTree &) = delete; 64 | 65 | BinaryTree &operator=(BinaryTree &&) = delete; 66 | // void clear(Node* a){ 67 | // if(a == nullptr){ 68 | // return; 69 | // } 70 | // clear(a->left); 71 | // clear(a->right); 72 | // delete a; 73 | // } 74 | // ~BinaryTree() { 75 | // clear(root); 76 | 77 | // } 78 | 79 | ~BinaryTree() { 80 | std::stack *> states; 81 | Node *tmp; 82 | 83 | if (root_ == nullptr) { 84 | return; 85 | } 86 | 87 | states.push(root_); 88 | 89 | while (states.size() != 0) { 90 | tmp = states.top(); 91 | states.pop(); 92 | 93 | if (tmp->left != nullptr) states.push(tmp->left); 94 | 95 | if (tmp->right != nullptr) states.push(tmp->right); 96 | 97 | delete tmp; 98 | } 99 | } 100 | 101 | void Insert(T key) { 102 | if (root_ == nullptr) { 103 | root_ = new Node(key); 104 | return; 105 | } 106 | 107 | Node *head = root_; 108 | Node *tale = root_; 109 | bool direction; 110 | 111 | while (head != nullptr) { 112 | if (comparator_(head->key, key)) { // or comparator_.IsGreater(head->key, key) 113 | tale = head; 114 | head = head->right; 115 | direction = false; 116 | } else { 117 | tale = head; 118 | head = head->left; 119 | direction = true; 120 | } 121 | } 122 | 123 | if (!direction) { 124 | tale->right = new Node(key); 125 | } else { 126 | tale->left = new Node(key); 127 | } 128 | } 129 | 130 | Node *GetRoot() { return (this->root_); } 131 | 132 | private: 133 | Node *root_; 134 | TLess comparator_; 135 | }; 136 | --------------------------------------------------------------------------------