├── README.md ├── queue ├── const_queue.hpp ├── queue.hpp └── readme.md ├── recursion └── SimpleRecursionProblems.cpp ├── stack ├── readme.md ├── stack_LinkedList │ ├── readme.md │ └── stack.hpp └── stack_array │ ├── readme.md │ └── stack.hpp └── tree ├── BST ├── BST.hpp ├── Operations │ ├── Insert.cpp │ ├── Search.cpp │ └── delete.cpp ├── README.md └── main.cpp ├── Red-blackTree └── RBT.hpp └── Traversal ├── Inorder.cpp ├── LevelOrder.cpp ├── Postorder.cpp ├── Preorder.cpp └── readme.md /README.md: -------------------------------------------------------------------------------- 1 | # Algorithms-and-Data-Structures-Implmentation -------------------------------------------------------------------------------- /queue/const_queue.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CONST_QUEUE_HPP 2 | #define CONST_QUEUE_HPP 3 | #include 4 | 5 | template 6 | class queue{ 7 | 8 | private: 9 | class node 10 | { 11 | public : 12 | const T &data; 13 | node *next; 14 | node(const T &data):data(data),next(nullptr){} 15 | }; 16 | node * _q; 17 | unsigned int _size; 18 | public : 19 | queue():_q(nullptr),_size(0){} 20 | queue(const queue &q) 21 | { 22 | _size = q._size; 23 | node *tmp = q._q; 24 | if(tmp != nullptr) 25 | { 26 | _q = new node(tmp->data); 27 | tmp = tmp->next; 28 | node *cmp = _q; 29 | while(tmp != nullptr) 30 | { 31 | cmp->next = new node(tmp->data); 32 | cmp = cmp->next; 33 | tmp = tmp->next; 34 | } 35 | } 36 | } 37 | ~queue() 38 | { 39 | node *del; 40 | while(_q != nullptr) 41 | { 42 | del = _q->next; 43 | delete _q; 44 | _q = del; 45 | } 46 | } 47 | const queue & operator=(const queue &q) 48 | { 49 | node *del; 50 | while(_q != nullptr) 51 | { 52 | del = _q->next; 53 | delete _q; 54 | _q = del; 55 | } 56 | this->_size = q._size; 57 | node *tmp = q._q; 58 | if(tmp != nullptr) 59 | { 60 | _q = new node(tmp->data); 61 | tmp = tmp->next; 62 | node *cmp = _q; 63 | while(tmp != nullptr) 64 | { 65 | cmp->next = new node(tmp->data); 66 | cmp = cmp->next; 67 | tmp = tmp->next; 68 | } 69 | } 70 | return *this; 71 | } 72 | void push(const T &data) 73 | { 74 | node *node_add = new node(data); 75 | node *tmp = _q; 76 | if (tmp == nullptr) 77 | _q = node_add; 78 | else 79 | { 80 | while(tmp->next != nullptr) 81 | tmp = tmp->next; 82 | tmp->next = node_add; 83 | } 84 | _size++; 85 | } 86 | void pop() 87 | { 88 | if (_q != nullptr) 89 | { 90 | node *tmp = _q; 91 | _q = _q->next; 92 | delete tmp; 93 | _size--; 94 | } 95 | 96 | } 97 | const T & front() 98 | { 99 | if(empty()) throw std::runtime_error("Error: Queue is empty"); 100 | return _q->data; 101 | } 102 | unsigned int size() const 103 | { 104 | return _size; 105 | } 106 | bool empty() 107 | { 108 | return _size == 0; 109 | } 110 | const T & back() 111 | { 112 | if(empty()) throw std::runtime_error("Error: Queue is empty"); 113 | node *tmp = _q; 114 | while(tmp != nullptr && tmp->next != nullptr) 115 | tmp = tmp->next; 116 | return tmp->data; 117 | } 118 | friend bool operator<(const queue &lhs, const queue &rhs) 119 | { 120 | if (lhs.size() < rhs.size()) return true; 121 | node *r = rhs._q; 122 | node *l = lhs._q; 123 | while(r != nullptr && l != nullptr) 124 | { 125 | if (l->data < r->data) return true; 126 | if (r->data < l->data) return false; 127 | l = l->next; 128 | r = r->next; 129 | } 130 | return false; 131 | } 132 | friend bool operator==(const queue &lhs, const queue &rhs) 133 | { 134 | if (lhs.size() != rhs.size()) return false; 135 | node *r = rhs._q; 136 | node *l = lhs._q; 137 | while(r != nullptr && l != nullptr) 138 | { 139 | if (l->data != r->data) return false; 140 | l = l->next; 141 | r = r->next; 142 | } 143 | return true; 144 | } 145 | friend bool operator>(const queue &lhs , const queue &rhs) 146 | { 147 | return !(lhs < rhs); 148 | } 149 | friend bool operator<=(const queue &lhs, const queue &rhs) 150 | { 151 | return ((lhs < rhs) || (lhs == rhs)); 152 | } 153 | friend bool operator!=(const queue &lhs, const queue &rhs) 154 | { 155 | return !(lhs == rhs); 156 | } 157 | friend bool operator>=(const queue &lhs, const queue &rhs) 158 | { 159 | return ((lhs > rhs) || (lhs == rhs)); 160 | } 161 | }; 162 | #endif -------------------------------------------------------------------------------- /queue/queue.hpp: -------------------------------------------------------------------------------- 1 | #ifndef QUEUE_HPP 2 | #define QUEUE_HPP 3 | #include 4 | 5 | template 6 | class queue{ 7 | 8 | private: 9 | class node 10 | { 11 | public : 12 | T data; 13 | node *next; 14 | node(T &data):data(data),next(nullptr){} 15 | }; 16 | node * _q; 17 | unsigned int _size; 18 | public : 19 | queue():_q(nullptr),_size(0){} 20 | queue(const queue &q) 21 | { 22 | _size = q._size; 23 | node *tmp = q._q; 24 | if(tmp != nullptr) 25 | { 26 | _q = new node(tmp->data); 27 | tmp = tmp->next; 28 | node *cmp = _q; 29 | while(tmp != nullptr) 30 | { 31 | cmp->next = new node(tmp->data); 32 | cmp = cmp->next; 33 | tmp = tmp->next; 34 | } 35 | } 36 | } 37 | ~queue() 38 | { 39 | node *del; 40 | while(_q != nullptr) 41 | { 42 | del = _q->next; 43 | delete _q; 44 | _q = del; 45 | } 46 | } 47 | const queue & operator=(const queue &q) 48 | { 49 | node *del; 50 | while(_q != nullptr) 51 | { 52 | del = _q->next; 53 | delete _q; 54 | _q = del; 55 | } 56 | this->_size = q._size; 57 | node *tmp = q._q; 58 | if(tmp != nullptr) 59 | { 60 | _q = new node(tmp->data); 61 | tmp = tmp->next; 62 | node *cmp = _q; 63 | while(tmp != nullptr) 64 | { 65 | cmp->next = new node(tmp->data); 66 | cmp = cmp->next; 67 | tmp = tmp->next; 68 | } 69 | } 70 | return *this; 71 | } 72 | void push(T data) 73 | { 74 | node *node_add = new node(data); 75 | node *tmp = _q; 76 | if (tmp == nullptr) 77 | _q = node_add; 78 | else 79 | { 80 | while(tmp->next != nullptr) 81 | tmp = tmp->next; 82 | tmp->next = node_add; 83 | } 84 | _size++; 85 | } 86 | void pop() 87 | { 88 | if (_q != nullptr) 89 | { 90 | node *tmp = _q; 91 | _q = _q->next; 92 | delete tmp; 93 | _size--; 94 | } 95 | 96 | } 97 | T & front() 98 | { 99 | if(empty()) throw std::runtime_error("Error: Queue is empty"); 100 | return _q->data; 101 | } 102 | T & front() const 103 | { 104 | if(empty()) throw std::runtime_error("Error: Queue is empty"); 105 | return _q->data; 106 | } 107 | unsigned int size() const 108 | { 109 | return _size; 110 | } 111 | bool empty() 112 | { 113 | return _size == 0; 114 | } 115 | T & back() 116 | { 117 | if(empty()) throw std::runtime_error("Error: Queue is empty"); 118 | node *tmp = _q; 119 | while(tmp != nullptr && tmp->next != nullptr) 120 | tmp = tmp->next; 121 | return tmp->data; 122 | } 123 | T & back() const 124 | { 125 | if(empty()) throw std::runtime_error("Error: Queue is empty"); 126 | node *tmp = _q; 127 | while(tmp != nullptr && tmp->next != nullptr) 128 | tmp = tmp->next; 129 | return tmp->data; 130 | } 131 | friend bool operator==(const queue &lhs, const queue &rhs) 132 | { 133 | if(lhs.size() != rhs.size()) return false; 134 | node *left = lhs._q; 135 | node *right = rhs._q; 136 | while(left != nullptr) 137 | { 138 | if(left->data != right->data) return false; 139 | left = left->next; 140 | right = right->next; 141 | } 142 | return true; 143 | } 144 | friend bool operator<(const queue &lhs, const queue &rhs) { 145 | if (lhs.size() < rhs.size()) return true; 146 | node *left = lhs._q; 147 | node *right = rhs._q; 148 | while (left != nullptr && right != nullptr) 149 | { 150 | if (left->data < right->data) return true; 151 | if (right->data < left->data) return false; 152 | left = left->next; 153 | right = right->next; 154 | } 155 | return false; 156 | } 157 | friend bool operator!=(const queue &lhs, const queue &rhs) 158 | { 159 | return !(lhs == rhs); 160 | } 161 | friend bool operator>(const queue &lhs, const queue &rhs) 162 | { 163 | return !(lhs < rhs); 164 | } 165 | friend bool operator>=(const queue &lhs, const queue &rhs) 166 | { 167 | return ((lhs > rhs) ||(lhs == rhs)); 168 | } 169 | friend bool operator<=(const queue &lhs, const queue &rhs) 170 | { 171 | return ((lhs < rhs) ||(lhs == rhs)); 172 | } 173 | 174 | }; 175 | #endif -------------------------------------------------------------------------------- /queue/readme.md: -------------------------------------------------------------------------------- 1 | # Queue Implementation in C++ 2 | This is a templated implementation of a Queue data structure, implemented using a singly-linked list. It supports the standard queue operations such as push, pop, front, back, size, and empty. It also provides comparison operators for comparison with other queues. 3 | The queue class is a template class, which means it can hold any data type. 4 | 5 | ## Getting Started 6 | 7 | * To use this queue implementation, simply include the queue.hpp header file in your code: `#include "queue.hpp"` 8 | * Then, you can create a queue of any type by specifying its template parameter, for example: `queue my_queue;` 9 | 10 | ## Operators 11 | 12 | The class has the following overloaded operators: 13 | 14 | * Assignment operator operator= 15 | * Comparison operators ==, !=, <, >, <=, >= 16 | 17 | ## Methods 18 | 19 | The class has the following methods: 20 | 21 | * push(T data) - adds a new element to the back of the queue. 22 | * pop() - removes the first element from the queue. 23 | * front() - returns a reference to the first element in the queue. 24 | * back() - returns a reference to the last element in the queue. 25 | * size() - returns the number of elements in the queue. 26 | * empty() - returns true if the queue is empty. 27 | 28 | ## Implementation Details 29 | The Queue class is implemented using a singly linked list of nodes, where each node contains the data element and a pointer to the next node in the list. The Queue class also keeps track of the current size of the Queue, and provides methods to add and remove elements from the Queue, as well as to access the front and back elements of the Queue. 30 | 31 | The Queue class supports copy construction and assignment, as well as the standard comparison operators. The comparison operators are implemented using the size and ordering of the elements in the Queue. The == operator compares the size and values of the elements in the Queue, while the other operators compare the size and ordering of the elements. 32 | -------------------------------------------------------------------------------- /recursion/SimpleRecursionProblems.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | // Function to calculate the length of a string 's' using recursion. 7 | int ft_strlen(string s) 8 | { 9 | if (s.size() == 0 ) return 0; 10 | return ft_strlen(s.substr(1)) + 1; 11 | } 12 | 13 | // Function to reverse a string 's' using recursion. 14 | string ft_reverse(string s) 15 | { 16 | if (!s.size()) return ""; 17 | return ft_reverse(s.substr(1)) + s[0]; 18 | } 19 | 20 | // Function to reverse a string 's' using recursion. 21 | string ft_reverseI(string s, int start = 0) 22 | { 23 | if (start == s.size()) return ""; 24 | return ft_reverseI(s,++start) + s[start]; 25 | } 26 | 27 | // Function to convert a decimal integer 'n' to binary representation using recursion. 28 | string decimalToBinary(int n, string result = "") 29 | { 30 | if (n <= 0) return result; 31 | result = to_string(n%2) + result; 32 | return decimalToBinary(n/2,result); 33 | } 34 | 35 | // Function to check if a string 's' is a palindrome using recursion. 36 | bool palindrome(string s,int start = 0, int end = 0) 37 | { 38 | if (start == 0) end = s.size()-1; 39 | if (start >= end) return true; 40 | if (s[start] == s[end]) 41 | return palindrome(s,++start,--end); 42 | return false; 43 | 44 | } 45 | 46 | // Function to check if a string 's' is a palindrome using recursion. 47 | bool palindromeI(string s) 48 | { 49 | if (s.size() == 1 || s.size() == 0) 50 | return true; 51 | if (s[0] == s[s.size() -1]) 52 | return palindromeI(s.substr(1,s.size()-2)); 53 | return false; 54 | 55 | } 56 | 57 | // Function to calculate the sum of integers from 1 to 'n' using recursion. 58 | int sumOfNumber(int n, int result = 0) 59 | { 60 | if (n == result) return result; 61 | return result + sumOfNumber(n, result+1); 62 | } 63 | 64 | // Function to calculate the sum of integers from 1 to 'n' using recursion. 65 | int sumOfNumberI(int n ) 66 | { 67 | if (n <= 1) return 1; 68 | return n + sumOfNumberI(n-1); 69 | } 70 | 71 | // Recursive function to perform binary search on a sorted vector of integers. 72 | // Returns the index of the target if found, or -1 if not found. 73 | int binarySearch(vector &nums, int target,int left = 0, int right = -1) 74 | { 75 | if (right == -1) right = nums.size() -1; 76 | if (left > right || nums[left] > target || nums[right] < target) 77 | return -1; 78 | int mid = ((right + left)/2); 79 | if (nums[mid] == target) return mid; 80 | if (nums[mid] < target) 81 | return binarySearch(nums,target,mid + 1,right); 82 | return binarySearch(nums,target,left,mid - 1); 83 | } 84 | 85 | // Recursive function to calculate the nth Fibonacci number. 86 | // Returns the Fibonacci number at index 'n'. 87 | int fib(int n) 88 | { 89 | if (n == 0 || n == 1) return n; 90 | return fib(n - 1) + fib(n - 2); 91 | } 92 | 93 | // Helper function for Merge Sort to merge two sorted subarrays into a single sorted array. 94 | void merge(vector& arr, int left, int middle, int right) 95 | { 96 | int L = middle - left + 1; 97 | int R = right - middle; 98 | int i = 0 , j = 0, k = left; 99 | 100 | vector leftArr(L); 101 | vector rightArr(R); 102 | 103 | for (int i = 0; i < L; i++) leftArr[i] = arr[left + i]; 104 | for (int i = 0; i < R; i++) rightArr[i] = arr[middle + 1 + i]; 105 | 106 | 107 | while (i < L && j < R) 108 | if (leftArr[i] <= rightArr[j]) arr[k++] = leftArr[i++]; 109 | else arr[k++] = rightArr[j++]; 110 | 111 | while (i < L) arr[k++] = leftArr[i++]; 112 | 113 | while (j < R) arr[k++] = rightArr[j++]; 114 | } 115 | 116 | // Merge Sort function to sort an input vector of integers using the Merge Sort algorithm. 117 | // - 'nums' is the vector to be sorted. 118 | // - 'left' is the left index of the subarray to be sorted. 119 | // - 'right' is the right index of the subarray to be sorted. 120 | void mergeSort(vector &nums, int left= 0, int right = -1) 121 | { 122 | if (right == -1) right = nums.size() - 1; 123 | if (left < right) 124 | { 125 | int mid = (right + left)/2; 126 | mergeSort(nums,left, mid); 127 | mergeSort(nums,mid+1,right); 128 | merge(nums, left, mid, right); 129 | } 130 | } 131 | 132 | struct ListNode { 133 | int val; 134 | ListNode *next; 135 | ListNode() : val(0), next(nullptr) {} 136 | ListNode(int x) : val(x), next(nullptr) {} 137 | ListNode(int x, ListNode *next) : val(x), next(next) {} 138 | }; 139 | 140 | // Function to reverse a singly linked list using recursion. 141 | // Returns the new head of the reversed list. 142 | ListNode* reverseList(ListNode* head) 143 | { 144 | if (!head || !head->next) 145 | return head; 146 | ListNode *tmp = reverseList(head->next); 147 | head->next->next = head; 148 | head->next = NULL; 149 | return tmp; 150 | } 151 | 152 | // Function to merge two sorted linked lists into a single sorted list. 153 | // Returns the head of the merged list. 154 | ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) 155 | { 156 | if (!list1) return list2; 157 | if (!list2) return list1; 158 | if (list1->val < list2->val) 159 | { 160 | list1->next = mergeTwoLists(list1->next,list2); 161 | return list1; 162 | } 163 | else 164 | { 165 | list2->next = mergeTwoLists(list1,list2->next); 166 | return list2; 167 | } 168 | } 169 | 170 | // Function to delete duplicate elements from a sorted linked list using recursion. 171 | // Returns the head of the list after removing duplicates. 172 | ListNode* deleteDuplicates(ListNode* head) 173 | { 174 | if (!head) 175 | return head; 176 | if (head->next && head->val == head->next->val) 177 | return (deleteDuplicates(head->next)); 178 | else 179 | { 180 | head->next = deleteDuplicates(head->next); 181 | return (head); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /stack/readme.md: -------------------------------------------------------------------------------- 1 | 2 | # Stack Implementation 3 | This repository contains two implementations of a stack data structure, one using an array and the other using a linked list. 4 | 5 | ## [Stack using Array](https://github.com/Mounadi05/Algorithms-and-Data-Structures-Implmentation/blob/master/stack/stack_array/stack.hpp) 6 | The stack class defined in stack_array.hpp uses an array to implement the stack data structure. The stack's capacity is initialized to 10 by default, and can be resized as the number of elements increases. The class is defined as follows: 7 | 8 | `template >` 9 | 10 | ### The stack class has the following public methods: 11 | 12 | * push(const T& data): inserts an element into the stack. 13 | * pop(): removes and returns the top element from the stack. 14 | * top(): returns the top element in the stack without removing it. 15 | * empty(): returns true if the stack is empty, false otherwise. 16 | * size(): returns the number of elements in the stack. 17 | * overloaded comparison operators (==, !=, <, >, <=, >=) and a swap method. 18 | 19 | ## [Stack using Linked List](https://github.com/Mounadi05/Algorithms-and-Data-Structures-Implmentation/blob/master/stack/stack_LinkedList/stack.hpp) 20 | 21 | The stack class defined in stack_linked_list.hpp uses a linked list to implement the stack data structure. The class is defined as follows: 22 | 23 | 24 | ### The stack class has the following public methods: 25 | 26 | * push(const T& data): inserts an element into the stack. 27 | * pop(): removes and returns the top element from the stack. 28 | * top(): returns the top element in the stack without removing it. 29 | * empty(): returns true if the stack is empty, false otherwise. 30 | * size(): returns the number of elements in the stack. 31 | * overloaded comparison operators (==, !=, <, >, <=, >=) and a swap method. 32 | -------------------------------------------------------------------------------- /stack/stack_LinkedList/readme.md: -------------------------------------------------------------------------------- 1 | # Stack Data Structure 2 | 3 | The stack class is a templated class that implements a basic stack data structure in C++ using a singly linked list. The stack is a last-in, first-out (LIFO) data structure, where elements are inserted and removed from the same end. 4 | 5 | ## Usage 6 | ### Instantiating a stack 7 | To create a new stack, simply declare an instance of the class, like so:`stack myStack;` 8 | 9 | This creates a new stack object called myStack that can store integers. 10 | 11 | ### Pushing elements onto the stack 12 | To add an element to the top of the stack, call the push() function and pass in the element you want to add as an argument: `myStack.push(42);` 13 | This adds the integer 42 to the top of the stack. 14 | 15 | ### Popping elements off the stack 16 | To remove the top element from the stack, call the pop() function: `myStack.pop();` 17 | 18 | This removes the top element from the stack. 19 | 20 | ### Swapping stacks 21 | You can swap the contents of two stacks by calling the swap() function: 22 | 23 | ## Implementation Details 24 | The stack class is implemented using a singly-linked list. Each node in the linked list contains a data member that stores the value of the element, and a next pointer that points to the next node in the list. 25 | 26 | The stack class has a Node inner class that represents the nodes in the linked list. The stack class also has a _S member that points to the first node in the list (the "head" of the list), a _tail member that points to the last node in the list (the "tail" of the list), and a _size member that stores the number of elements currently on the stack. 27 | 28 | ## Methodes 29 | 30 | * push: adds an element to the top of the stack. 31 | * pop: removes the top element from the stack. 32 | * top: returns a reference to the top element of the stack. 33 | * empty: returns true if the stack is empty, false otherwise. 34 | * size: returns the number of elements in the stack. 35 | * swap: swaps the contents of two stacks. 36 | 37 | ## Operator Overloading 38 | The stack class overloads several operators to allow for comparison between stack objects. These operators include: 39 | 40 | * `== `(equal to) 41 | 42 | * `!= `(not equal to) 43 | 44 | * `<` (less than) 45 | 46 | * `>` (greater than) 47 | 48 | * `<=` (less than or equal to) 49 | 50 | * `>=` (greater than or equal to) 51 | 52 | These operators allow you to compare stack objects based on their contents. 53 | 54 | ## Memory Management 55 | The stack class manages memory by allocating new nodes on the heap for each element added to the stack, and deallocating them when elements are removed. The class uses a destructor to deallocate all nodes when the stack object is destroyed. The class also has a copy constructor and copy assignment operator to allow for deep copying of stack objects. 56 | -------------------------------------------------------------------------------- /stack/stack_LinkedList/stack.hpp: -------------------------------------------------------------------------------- 1 | #ifndef STACK_HPP 2 | #define STACK_HPP 3 | #include 4 | template 5 | class stack 6 | { 7 | private : 8 | class Node 9 | { 10 | public : 11 | T data; 12 | Node *next; 13 | Node(const T & data):data(data),next(nullptr){} 14 | Node(const T & data, Node *next):data(data),next(next){} 15 | }; 16 | Node * _tail; 17 | Node * _S; 18 | size_t _size; 19 | public : 20 | stack():_tail(nullptr),_S(nullptr),_size(0){} 21 | stack(const stack & s) 22 | { 23 | this->_size = s._size; 24 | Node *tmp = s._S; 25 | while(tmp) 26 | { 27 | _S = new Node(tmp->data); 28 | Node *cur = _S; 29 | tmp = tmp->next; 30 | while(tmp) 31 | { 32 | cur->next = new Node(tmp->data); 33 | cur = cur->next; 34 | if (tmp->next == nullptr) 35 | this->_tail = cur; 36 | tmp = tmp->next; 37 | } 38 | } 39 | } 40 | ~stack() 41 | { 42 | Node *del; 43 | while(_size) 44 | { 45 | del = _S->next; 46 | delete _S; 47 | _S = nullptr; 48 | _S = del; 49 | _size--; 50 | } 51 | 52 | } 53 | const stack & operator=(const stack & s) 54 | { 55 | Node *del; 56 | while(_S) 57 | { 58 | del = _S->next; 59 | delete _S; 60 | _S = del; 61 | } 62 | this->_size = s._size; 63 | Node *tmp = s._S; 64 | while(tmp) 65 | { 66 | _S = new Node(tmp->data); 67 | Node *cur = _S; 68 | tmp = tmp->next; 69 | while(tmp) 70 | { 71 | cur->next = new Node(tmp->data); 72 | cur = cur->next; 73 | if (tmp->next == nullptr) 74 | this->_tail = cur; 75 | tmp = tmp->next; 76 | } 77 | } 78 | return *this; 79 | } 80 | bool empty() 81 | { 82 | return (_size == 0); 83 | } 84 | void push(const T & data) 85 | { 86 | if (empty()) 87 | { 88 | _S = new Node(data); 89 | _tail = _S; 90 | } 91 | else 92 | { 93 | _tail->next = new Node(data); 94 | _tail = _tail->next; 95 | } 96 | _size++; 97 | } 98 | T & top() 99 | { 100 | if (empty()) throw std::runtime_error("stack is empty"); 101 | return _tail->data; 102 | } 103 | void pop() 104 | { 105 | if (empty()) throw std::runtime_error("stack is empty"); 106 | Node *tmp = _S; 107 | Node *cur; 108 | while(tmp->next) 109 | { 110 | cur = tmp; 111 | tmp = tmp->next; 112 | } 113 | _tail = cur; 114 | cur->next = nullptr; 115 | delete tmp; 116 | tmp = nullptr; 117 | _size--; 118 | } 119 | size_t size() 120 | { 121 | return _size; 122 | } 123 | void swap(stack &s) 124 | { 125 | size_t size_tmp = s._size; 126 | s._size = this->_size; 127 | this->_size = size_tmp; 128 | Node *tmp = s._S; 129 | s._S = this->_S; 130 | this->_S = tmp; 131 | } 132 | friend bool operator==(const stack &lhs, const stack &rhs) 133 | { 134 | if(lhs.size() != rhs.size()) return false; 135 | Node *left = lhs._S; 136 | Node *right = rhs._S; 137 | while(left != nullptr) 138 | { 139 | if(left->data != right->data) return false; 140 | left = left->next; 141 | right = right->next; 142 | } 143 | return true; 144 | } 145 | friend bool operator<(const stack &lhs, const stack &rhs) { 146 | if (lhs.size() < rhs.size()) return true; 147 | Node *left = lhs._S; 148 | Node *right = rhs._S; 149 | while (left != nullptr && right != nullptr) 150 | { 151 | if (left->data < right->data) return true; 152 | if (right->data < left->data) return false; 153 | left = left->next; 154 | right = right->next; 155 | } 156 | return false; 157 | } 158 | friend bool operator!=(const stack &lhs, const stack &rhs) 159 | { 160 | return !(lhs == rhs); 161 | } 162 | friend bool operator>(const stack &lhs, const stack &rhs) 163 | { 164 | return !(lhs < rhs); 165 | } 166 | friend bool operator>=(const stack &lhs, const stack &rhs) 167 | { 168 | return ((lhs > rhs) ||(lhs == rhs)); 169 | } 170 | friend bool operator<=(const stack &lhs, const stack &rhs) 171 | { 172 | return ((lhs < rhs) ||(lhs == rhs)); 173 | } 174 | }; 175 | 176 | #endif -------------------------------------------------------------------------------- /stack/stack_array/readme.md: -------------------------------------------------------------------------------- 1 | # Stack Class 2 | This is a C++ implementation of a stack class, which is a linear data structure that follows the Last-In-First-Out (LIFO) principle. 3 | 4 | The stack class template takes two template parameters, T and Alloc, where T represents the type of the elements stored in the stack and Alloc represents the allocator type used for memory management. 5 | 6 | ## Class Members 7 | * _array: a pointer to the underlying array of elements. 8 | * _top: an integer that represents the index of the top element of the stack. 9 | * _capacity: an integer that represents the current capacity of the stack. 10 | * alloc: an allocator object used to manage the memory of the stack. 11 | Class Methods 12 | * stack(): default constructor that creates an empty stack with a default capacity of 10. 13 | * stack(const stack & S): copy constructor that creates a new stack that is a copy of an existing stack S. 14 | const stack &operator=(const stack & S): copy assignment operator that assigns an existing stack S to the current stack. 15 | * ~stack(): destructor that deallocates the memory used by the stack. 16 | * int size() const: returns the number of elements in the stack. 17 | * bool empty(): returns true if the stack is empty, false otherwise. 18 | *void push(const T &data): adds a new element to the top of the stack. 19 | * T & top(): returns a reference to the top element of the stack. 20 | * const T & top() const: returns a const reference to the top element of the stack. 21 | * void pop(): removes the top element from the stack. 22 | * void swap(stack & S): swaps the contents of the current stack with another stack S. 23 | * friend bool operator==(const stack &lhs, const stack &rhs): compares two stacks for equality. 24 | * friend bool operator<(const stack &lhs, const stack &rhs): compares two stacks, returns true if lhs is less than rhs. 25 | * friend bool operator>(const stack &lhs , const stack &rhs): compares two stacks, returns true if lhs is greater than rhs. 26 | * friend bool operator!=(const stack &lhs , const stack &rhs): compares two stacks for inequality. 27 | * friend bool operator>=(const stack &lhs , const stack &rhs): compares two stacks, returns true if lhs is greater than or equal to rhs. 28 | * friend bool operator<=(const stack &lhs , const stack &rhs): compares two stacks, returns true if lhs is less than or equal to rhs. 29 | 30 | ## Usage 31 | To use the stack class, include the stack.hpp header file and create a new instance of the class as shown below: 32 | 33 | ``` 34 | #include "stack.hpp" 35 | stack s; 36 | ``` 37 | You can then use the class methods to add, remove, and access elements of the stack, as well as compare it with other stacks. 38 | 39 | ## Memory Management 40 | The stack class uses an allocator object alloc for memory management. The default allocator is std::allocator, but you can also specify a custom allocator when creating an instance of the class. The alloc.allocate method is used to allocate memory for the stack, and the `alloc.deallocate 41 | -------------------------------------------------------------------------------- /stack/stack_array/stack.hpp: -------------------------------------------------------------------------------- 1 | #ifndef STACK_HPP 2 | #define STACK_HPP 3 | 4 | #include 5 | #include 6 | 7 | template > 8 | class stack 9 | { 10 | private: 11 | T* _array; 12 | int _top; 13 | int _capacity; 14 | Alloc alloc; 15 | 16 | public: 17 | stack(): _top(-1), _capacity(10), _array(nullptr) { 18 | _array = alloc.allocate(_capacity); 19 | } 20 | stack(const stack & S) 21 | { 22 | _top = S._top; 23 | _capacity = S._capacity; 24 | _array = alloc.allocate(_capacity); 25 | for(int i = 0; i <= _top ; i++) 26 | _array[i] = S._array[i]; 27 | } 28 | const stack &operator=(const stack & S) 29 | { 30 | if (this->_capacity > 0) 31 | alloc.deallocate(_array,_capacity); 32 | _top = S._top; 33 | _capacity = S._capacity; 34 | _array = alloc.allocate(_capacity); 35 | for(int i = 0; i <= _top ; i++) 36 | _array[i] = S._array[i]; 37 | return *this; 38 | } 39 | ~stack() 40 | { 41 | alloc.deallocate(&_array[0],_capacity); 42 | } 43 | int size() const 44 | { 45 | return _top + 1; 46 | } 47 | bool empty() 48 | { 49 | return (_top == -1); 50 | } 51 | void push(const T &data) 52 | { 53 | if (_top + 1 == _capacity) 54 | { 55 | T * newarray = alloc.allocate(_capacity * 2); 56 | for(int i = 0; i <= _top ; i++) 57 | alloc.construct(&newarray[i],_array[i]); 58 | alloc.construct(&newarray[++_top],data); 59 | alloc.deallocate(_array,_capacity); 60 | _capacity *= 2; 61 | _array = newarray; 62 | } 63 | else 64 | alloc.construct(&_array[++_top],data); 65 | } 66 | T & top() 67 | { 68 | return _array[_top]; 69 | } 70 | const T & top() const 71 | { 72 | return _array[_top]; 73 | } 74 | void pop() 75 | { 76 | alloc.destroy(&_array[_top--]); 77 | } 78 | void swap(stack & S) 79 | { 80 | int tmp = this->_top; 81 | this->_top = S._top; 82 | S._top = tmp; 83 | tmp = this->_capacity; 84 | this->_capacity = S._capacity; 85 | S._capacity= tmp; 86 | T * _tmp = this->_array; 87 | this->_array= S._array; 88 | S._array = _tmp; 89 | } 90 | friend bool operator==(const stack &lhs, const stack &rhs) 91 | { 92 | if (lhs.size() != rhs.size()) return false; 93 | for(int i = 0; i < lhs._top ; i++) 94 | if (rhs._array[i] != lhs._array[i]) return false; 95 | return true; 96 | } 97 | friend bool operator<(const stack &lhs, const stack &rhs) 98 | { 99 | if(lhs.size() >= rhs.size()) return false; 100 | for(int i = 0; i < lhs.size() ; i++) 101 | { 102 | if(lhs._array[i] < rhs._array[i]) return true; 103 | if(lhs._array[i] > rhs._array[i]) return false; 104 | } 105 | return false; 106 | } 107 | friend bool operator>(const stack &lhs , const stack &rhs) 108 | { 109 | return !(lhs < rhs); 110 | } 111 | friend bool operator!=(const stack &lhs , const stack &rhs) 112 | { 113 | return !(lhs == rhs); 114 | } 115 | friend bool operator>=(const stack &lhs , const stack &rhs) 116 | { 117 | return ((lhs > rhs) || lhs == rhs); 118 | } 119 | friend bool operator<=(const stack &lhs , const stack &rhs) 120 | { 121 | return ((lhs < rhs) || lhs == rhs); 122 | } 123 | }; 124 | 125 | #endif -------------------------------------------------------------------------------- /tree/BST/BST.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BST_HPP 2 | #define BST_HPP 3 | 4 | #include 5 | #include 6 | 7 | template 8 | class bst 9 | { 10 | private: 11 | struct Node 12 | { 13 | Node *left, *right; 14 | k _key; 15 | v _val; 16 | Node(){} 17 | Node(k key, v val) : _key(key),_val(val), left(NULL), right(NULL) {} 18 | }; 19 | Node *_root; 20 | size_t _size; 21 | void insertIntoBST(k key, v val) 22 | { 23 | Node *tmp = _root; 24 | if (tmp == NULL) 25 | { 26 | _root = new Node(key,val); 27 | _size++; 28 | } 29 | else 30 | { 31 | while(tmp) 32 | { 33 | if (tmp->_val > val) 34 | { 35 | if (tmp->left != NULL) 36 | tmp = tmp->left; 37 | else 38 | { 39 | tmp->left = new Node(key,val); 40 | _size++; 41 | break ; 42 | } 43 | 44 | } 45 | else 46 | { 47 | if (tmp->right != NULL) 48 | tmp = tmp->right; 49 | else 50 | { 51 | tmp->right = new Node(key,val); 52 | _size++; 53 | break; 54 | } 55 | } 56 | } 57 | } 58 | } 59 | Node * FindMin(Node *root) 60 | { 61 | while(root->left) 62 | root = root->left; 63 | return root; 64 | } 65 | 66 | Node* deleteNode(Node* root, k key) 67 | { 68 | if(!root) return root; 69 | else if (key < root->_key) root->left = deleteNode(root->left, key); 70 | else if (key > root->_key) root->right = deleteNode(root->right, key); 71 | else 72 | { 73 | // case : no child 74 | if (!root->right && !root->left) 75 | { 76 | delete root; 77 | root = nullptr; 78 | _size--; 79 | return root; 80 | } 81 | // case : one child in left 82 | else if (!root->right) 83 | { 84 | Node *tmp = root; 85 | root = tmp->left; 86 | delete tmp; 87 | _size--; 88 | return root; 89 | } 90 | // case : one child in right 91 | else if (!root->left) 92 | { 93 | Node *tmp = root; 94 | root = tmp->right; 95 | delete tmp; 96 | _size--; 97 | return root; 98 | } 99 | // case : two child 100 | else 101 | { 102 | Node *tmp = FindMin(root->right); 103 | root->_val = tmp->_val; 104 | root->_key = tmp->_key; 105 | root->right = deleteNode(root->right, tmp->_key); 106 | } 107 | } 108 | return root; 109 | } 110 | void copyNode(Node *root) 111 | { 112 | if (root == NULL) 113 | return ; 114 | copyNode(root->left); 115 | insert(root->_key,root->_val); 116 | copyNode(root->right); 117 | } 118 | void inorder(Node* root) 119 | { 120 | if (root == NULL) 121 | return ; 122 | inorder(root->left); 123 | std::cout << " key : " << root->_key << 124 | " <<<<>>>> val : " << root->_val << std::endl; 125 | inorder(root->right); 126 | } 127 | void postorder(Node* root) 128 | { 129 | if (root == NULL) 130 | return ; 131 | postorder(root->left); 132 | postorder(root->right); 133 | std::cout << " key : " << root->_key << 134 | " <<<<>>>> val : " << root->_val << std::endl; 135 | } 136 | void preorder(Node * root) 137 | { 138 | if (root == NULL) 139 | return ; 140 | std::cout << " key : " << root->_key << 141 | " <<<<>>>> val : " << root->_val << std::endl; 142 | preorder(root->left); 143 | preorder(root->right); 144 | } 145 | void deleteTree(Node* node) 146 | { 147 | if (node == nullptr) 148 | return; 149 | 150 | deleteTree(node->left); 151 | deleteTree(node->right); 152 | 153 | delete node; 154 | node = NULL; 155 | } 156 | public : 157 | bst() : _root(NULL), _size(0) {} 158 | bst(const bst & other):_root(NULL),_size(0) 159 | { 160 | this->_size = other._size; 161 | if (other._root != NULL) copyNode(other._root); 162 | } 163 | bst & operator=(const bst & other) 164 | { 165 | this->~bst(); 166 | new(this)bst(other); 167 | return *this; 168 | } 169 | ~bst() 170 | { 171 | if (_root != NULL) { 172 | deleteTree(_root); 173 | _root = NULL; 174 | } 175 | } 176 | void inorder() 177 | { 178 | inorder(_root); 179 | } 180 | void postorder() 181 | { 182 | postorder(_root); 183 | } 184 | void preorder() 185 | { 186 | preorder(_root); 187 | } 188 | void insert(k key, v val) 189 | { 190 | Node *tmp = _root; 191 | if (tmp == NULL) 192 | { 193 | _root = new Node(key,val); 194 | _size++; 195 | } 196 | else 197 | { 198 | while(tmp) 199 | { 200 | if (tmp->_val > val) 201 | { 202 | if (tmp->left != NULL) 203 | tmp = tmp->left; 204 | else 205 | { 206 | tmp->left = new Node(key,val); 207 | _size++; 208 | break ; 209 | } 210 | 211 | } 212 | else 213 | { 214 | if (tmp->right != NULL) 215 | tmp = tmp->right; 216 | else 217 | { 218 | tmp->right = new Node(key,val); 219 | _size++; 220 | break; 221 | } 222 | } 223 | } 224 | } 225 | 226 | } 227 | void remove(k key) 228 | { 229 | _root = deleteNode(_root, key); 230 | } 231 | bool replace(const k& key, v value) 232 | { 233 | Node *root = _root; 234 | while(root) 235 | { 236 | if (root->_key== key) 237 | { 238 | root->_val = value; 239 | return true; 240 | } 241 | { 242 | if (key < root->_key) 243 | root = root->left; 244 | else 245 | root = root->right; 246 | } 247 | } 248 | return false; 249 | } 250 | bool empty() 251 | { 252 | return (_root == NULL); 253 | } 254 | v search (const k& key) 255 | { 256 | Node *root = _root; 257 | while(root) 258 | { 259 | if (root->_key== key) 260 | return root->_val; 261 | { 262 | if (key < root->_key) 263 | root = root->left; 264 | else 265 | root = root->right; 266 | } 267 | } 268 | throw std::runtime_error("error : not found"); 269 | return root->_val; 270 | } 271 | size_t size() 272 | { 273 | return _size; 274 | } 275 | void clear() 276 | { 277 | if (_root != NULL) 278 | deleteTree(_root); 279 | _root = NULL; 280 | _size = 0; 281 | } 282 | }; 283 | 284 | #endif 285 | -------------------------------------------------------------------------------- /tree/BST/Operations/Insert.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct TreeNode 4 | { 5 | int val; 6 | TreeNode *left; 7 | TreeNode *right; 8 | TreeNode() : val(0), left(nullptr), right(nullptr) {} 9 | TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 10 | TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 11 | }; 12 | 13 | // iterative 14 | TreeNode* insertIntoBST(TreeNode* root, int val) 15 | { 16 | TreeNode *tmp = root; 17 | if (!root) 18 | return new TreeNode(val); 19 | else 20 | { 21 | while(tmp) 22 | { 23 | if (tmp->val > val) 24 | { 25 | if (tmp->left) 26 | tmp = tmp->left; 27 | else 28 | { 29 | tmp->left = new TreeNode(val);; 30 | return root; 31 | } 32 | } 33 | else 34 | { 35 | if (tmp->right) 36 | tmp = tmp->right; 37 | else 38 | { 39 | tmp->right = new TreeNode(val); 40 | return root; 41 | } 42 | } 43 | } 44 | } 45 | return tmp; 46 | } 47 | 48 | // Recursive 49 | TreeNode* insertIntoBST(TreeNode* root, int val) 50 | { 51 | if(!root) 52 | return new TreeNode(val); 53 | if (root->val > val) 54 | root->left = insertIntoBST(root->left, val); 55 | else 56 | root->right = insertIntoBST(root->right, val); 57 | return root; 58 | } -------------------------------------------------------------------------------- /tree/BST/Operations/Search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct TreeNode 4 | { 5 | int val; 6 | TreeNode *left; 7 | TreeNode *right; 8 | TreeNode() : val(0), left(nullptr), right(nullptr) {} 9 | TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 10 | TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 11 | }; 12 | 13 | // iterative 14 | TreeNode* searchBST(TreeNode* root, int val) 15 | { 16 | while(root) 17 | { 18 | if (root->val == val) 19 | return root; 20 | { 21 | if (val < root->val) 22 | root = root->left; 23 | else 24 | root = root->right; 25 | } 26 | } 27 | return nullptr; 28 | } 29 | 30 | // Recursive 31 | TreeNode* searchBST(TreeNode* root, int val) 32 | { 33 | if (!root || root->val == val) 34 | return root; 35 | if (val < root->val) 36 | root = searchBST(root->left,val); 37 | else 38 | root = searchBST(root->right,val); 39 | return root; 40 | } -------------------------------------------------------------------------------- /tree/BST/Operations/delete.cpp: -------------------------------------------------------------------------------- 1 | struct TreeNode 2 | { 3 | int val; 4 | TreeNode *left; 5 | TreeNode *right; 6 | TreeNode() : val(0), left(nullptr), right(nullptr) {} 7 | TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 8 | TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 9 | }; 10 | 11 | TreeNode * FindMin(TreeNode *node) 12 | { 13 | TreeNode *root = node; 14 | while(root->left) 15 | root = root->left; 16 | return root; 17 | } 18 | 19 | TreeNode* deleteNode(TreeNode* root, int key) 20 | { 21 | if(!root) return root; 22 | else if (key < root->val) root->left = deleteNode(root->left, key); 23 | else if (key > root->val) root->right = deleteNode(root->right, key); 24 | else 25 | { 26 | // case : no child 27 | if (!root->right && !root->left) 28 | { 29 | delete root; 30 | root = nullptr; 31 | return root; 32 | } 33 | // case : one child in left 34 | else if (!root->right) 35 | { 36 | TreeNode *tmp = root; 37 | root = tmp->left; 38 | delete tmp; 39 | return root; 40 | } 41 | // case : one child in right 42 | else if (!root->left) 43 | { 44 | TreeNode *tmp = root; 45 | root = tmp->right; 46 | delete tmp; 47 | return root; 48 | } 49 | // case : two child 50 | else 51 | { 52 | TreeNode *tmp = FindMin(root->right); 53 | root->val = tmp->val; 54 | root->right = deleteNode(root->right, tmp->val); 55 | } 56 | } 57 | return root; 58 | } -------------------------------------------------------------------------------- /tree/BST/README.md: -------------------------------------------------------------------------------- 1 | # Binary Search Tree (BST) Implementation 2 | This is an implementation of a binary search tree (BST) in C++. A BST is a type of tree data structure that is used to store and organize data in a way that allows for efficient searching, insertion, and deletion. 3 | 4 | ## Usage 5 | 6 | ### The bst class provides several methods for traversing the tree and manipulating its contents: 7 | 8 | * inorder(): performs an inorder traversal of the tree, printing the key-value pairs of each node in sorted order 9 | * postorder(): performs a postorder traversal of the tree, printing the key-value pairs of each node 10 | * preorder(): performs a preorder traversal of the tree, printing the key-value pairs of each node 11 | * insert(key, value): inserts a new node with the given key-value pair into the tree 12 | * remove(key): removes the node with the given key from the tree 13 | * replace(key, value): replaces the value of the node with the given key with a new value 14 | * empty(): returns true if the tree is empty, false otherwise 15 | * size(): returns the number of nodes in the tree 16 | * clear() : This function calls 'deleteTree', which is used to recursively deallocate all nodes. 17 | 18 | ## Implementation Details 19 | 20 | The bst class is implemented using a private Node struct to represent each node in the tree. Each Node contains pointers to its left and right child nodes, as well as the key-value pair for that node. 21 | 22 | Insertion, deletion, and search operations are implemented using standard BST algorithms. In particular, insertion and deletion are implemented iteratively using a while loop, while search is implemented using a recursive function. 23 | 24 | The bst class is also designed to be memory-safe. Memory for each node is dynamically allocated using new and deallocated using delete when nodes are removed from the tree. The deleteTree function is used to recursively deallocate all nodes in the tree when the bst object is destroyed. 25 | 26 | -------------------------------------------------------------------------------- /tree/BST/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "BST.hpp" 5 | 6 | using namespace std; 7 | 8 | int main() { 9 | bst tree; 10 | 11 | tree.insert(5, 50); 12 | tree.insert(3, 30); 13 | tree.insert(7, 70); 14 | tree.insert(2, 20); 15 | tree.insert(4, 40); 16 | tree.insert(6, 60); 17 | tree.insert(8, 80); 18 | tree.insert(11, 110); 19 | tree.insert(9, 90); 20 | tree.insert(88, 880); 21 | tree.insert(13, 130); 22 | tree.insert(99, 990); 23 | 24 | cout << "In-order traversal: "<< std::endl; 25 | tree.inorder(); 26 | cout << endl; 27 | 28 | cout << "Pre-order traversal: "<< std::endl; 29 | tree.preorder(); 30 | cout << endl; 31 | 32 | cout << "Post-order traversal: "<< std::endl; 33 | tree.postorder(); 34 | cout << endl; 35 | 36 | cout << "Search for key=7: " << tree.search(7) << endl; 37 | cout << "Search for key=99: " << tree.search(99) << endl; 38 | 39 | tree.remove(7); 40 | tree.remove(2); 41 | tree.remove(9); 42 | cout << "remove keys : 7, 2, 9" << endl; 43 | cout << endl; 44 | cout << "In-order traversal after removing some nodes: " << std::endl; 45 | tree.inorder(); 46 | cout << endl; 47 | 48 | 49 | cout << "replace key : 88 with value : 8888 ? " << 50 | (tree.replace(88, 8888) ? "yes" : "no") << endl; 51 | 52 | cout << "replace key : 6 with value : 6666 ? " << 53 | (tree.replace(6, 6666) ? "yes" : "no") << endl; 54 | 55 | cout << "After replace:" << endl; 56 | tree.inorder(); 57 | cout << "Is the tree empty? " << (tree.empty() ? "yes" : "no") << endl; 58 | 59 | tree.clear(); 60 | 61 | cout << "Is the tree empty after clear()? " << (tree.empty() ? "yes" : "no") << endl; 62 | 63 | const int SIZE = 50; 64 | srand(time(NULL)); 65 | for (int i = 0; i < SIZE; i++) { 66 | int key = rand() % SIZE; 67 | int val = rand() % SIZE; 68 | tree.insert(key, val); 69 | } 70 | for (int i = 0; i < SIZE; i++) { 71 | int key = rand() % SIZE; 72 | try{ 73 | int value = tree.search(key); 74 | // std::cout << "key : " << key << " value : " << value << std::endl; 75 | } 76 | catch(...) 77 | { 78 | //std::cout << "key : " << key << " value : not found" << std::endl; 79 | continue; 80 | } 81 | } 82 | 83 | return 0; 84 | } -------------------------------------------------------------------------------- /tree/Red-blackTree/RBT.hpp: -------------------------------------------------------------------------------- 1 | #ifndef RBT_HPP 2 | #define RBT_HPP 3 | 4 | #include 5 | #include 6 | 7 | template 8 | class rbt 9 | { 10 | private: 11 | struct Node 12 | { 13 | Node *parent, *left, *right; 14 | bool isBlack; 15 | bool isLeftChild; 16 | k _key; 17 | v _value; 18 | Node(k key, v value) : parent(NULL), left(NULL), right(NULL), 19 | isBlack(false), isLeftChild(false), _key(key), _value(value) {} 20 | }; 21 | Node *_root; 22 | size_t _size; 23 | Node * findMin(Node *root) 24 | { 25 | while(root && root->left) 26 | root = root->left; 27 | return root; 28 | } 29 | Node * deleteNode(Node *root, const k &key) 30 | { 31 | if(root == NULL) return root; 32 | else if (root->_key > key) root->left = deleteNode(root->left,key); 33 | else if (root->_key < key) root->right= deleteNode(root->right,key); 34 | else 35 | { 36 | // One child 37 | if (!root->right && !root->left) 38 | { 39 | delete root; 40 | root = NULL; 41 | return root; 42 | } 43 | else if(!root->left) // One child in right 44 | { 45 | Node *tmp = root; 46 | root = root->right; 47 | delete tmp; 48 | return root; 49 | } 50 | else if (!root->right) // One child in left 51 | { 52 | Node *tmp = root; 53 | root = root->left; 54 | delete tmp; 55 | return root; 56 | } 57 | else 58 | { 59 | Node *tmp = findMin(root->right); 60 | root->_value = tmp->_value; 61 | root->_key = tmp->_key; 62 | deleteNode(root->right,tmp->_key); 63 | } 64 | } 65 | return root; 66 | } 67 | void copyNode(Node *root) 68 | { 69 | if (root == NULL) 70 | return ; 71 | copyNode(root->left); 72 | insert(root->_key,root->_value); 73 | copyNode(root->right); 74 | } 75 | public: 76 | rbt() : _root(NULL), _size(0) {} 77 | explicit rbt(const rbt & other):_root(NULL),_size(0) 78 | { 79 | this->_size = other._size; 80 | if (other._root != NULL) copyNode(other._root); 81 | } 82 | rbt & operator=(const rbt & other) 83 | { 84 | this->~rbt(); 85 | new(this)rbt(other); 86 | return *this; 87 | } 88 | ~rbt() 89 | { 90 | if (_root != NULL) { 91 | deleteTree(_root); 92 | _root = NULL; 93 | } 94 | } 95 | void deleteTree(Node* node) 96 | { 97 | if (node == nullptr) 98 | return; 99 | 100 | deleteTree(node->left); 101 | deleteTree(node->right); 102 | 103 | delete node; 104 | node = NULL; 105 | } 106 | void insert(k key, v value) 107 | { 108 | Node *newNode = new Node(key, value); 109 | newNode->isBlack = false; // New node is always colored red 110 | 111 | Node *parent = NULL; 112 | Node *current = _root; 113 | while (current != nullptr) 114 | { 115 | parent = current; 116 | if (key < current->_key) 117 | { 118 | current = current->left; 119 | newNode->isLeftChild = true; 120 | } 121 | else 122 | { 123 | current = current->right; 124 | newNode->isLeftChild = false; 125 | } 126 | } 127 | newNode->parent = parent; 128 | if (parent == NULL) // Tree was empty, new node becomes root 129 | { 130 | _root = newNode; 131 | _root->isBlack = true; // Root node must be colored black 132 | } 133 | else if (key < parent->_key) 134 | parent->left = newNode; 135 | else 136 | parent->right = newNode; 137 | _size++; 138 | } 139 | void erase(const k& key){_root = deleteNode(_root,key);} 140 | v & operator[] (const k& key) 141 | { 142 | Node *root = _root; 143 | while(root) 144 | { 145 | if (root->_key== key) 146 | return root->_value ; 147 | { 148 | if (key < root->_key) 149 | root = root->left; 150 | else 151 | root = root->right; 152 | } 153 | } 154 | throw std::runtime_error("error : not found"); 155 | return root->_value; 156 | } 157 | void traversal(){traversal(_root);} 158 | void traversal(Node *root) 159 | { 160 | if (root == NULL) 161 | return ; 162 | traversal(root->left); 163 | std::cout << " " << root->_value << std::endl;; 164 | traversal(root->right); 165 | } 166 | k &key() { return _root->_key; } 167 | v &value() { return _root->_value; } 168 | size_t size() { return _size; } 169 | bool empty(){ return _root == NULL; } 170 | }; 171 | #endif 172 | -------------------------------------------------------------------------------- /tree/Traversal/Inorder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct TreeNode 6 | { 7 | int val; 8 | TreeNode *left; 9 | TreeNode *right; 10 | TreeNode() : val(0), left(nullptr), right(nullptr) {} 11 | TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 12 | TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 13 | }; 14 | 15 | // iterative 16 | void inorderIterative(TreeNode* root) 17 | { 18 | std::stack tree; 19 | while(root || !tree.empty()) 20 | { 21 | while(root) 22 | { 23 | tree.push(root); 24 | root = root->left; 25 | } 26 | root = tree.top(); 27 | tree.pop(); 28 | std::cout << " " << root->val; 29 | root = root->right; 30 | } 31 | } 32 | 33 | // Recursive 34 | void inorderRecursive(TreeNode* root) 35 | { 36 | if (!root) return ; 37 | inorderRecursive(root->left); 38 | std::cout << " " << root->val; 39 | inorderRecursive(root->right); 40 | } 41 | -------------------------------------------------------------------------------- /tree/Traversal/LevelOrder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct TreeNode 6 | { 7 | int val; 8 | TreeNode *left; 9 | TreeNode *right; 10 | TreeNode() : val(0), left(nullptr), right(nullptr) {} 11 | TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 12 | TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 13 | }; 14 | // iterative 15 | void levelOrder(TreeNode* root) 16 | { 17 | std::queue tree; 18 | if(root) tree.push(root); 19 | int levels = 0; 20 | while(!tree.empty()) 21 | { 22 | levels = tree.size(); 23 | for(int i = 0; i < levels;i++) 24 | { 25 | TreeNode* current = tree.front(); 26 | tree.pop(); 27 | std::cout << current->val << " "; 28 | if(current->left) tree.push(current->left); 29 | if(current->right) tree.push(current->right); 30 | } 31 | std::cout << std::endl; 32 | } 33 | } -------------------------------------------------------------------------------- /tree/Traversal/Postorder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct TreeNode 6 | { 7 | int val; 8 | TreeNode *left; 9 | TreeNode *right; 10 | TreeNode() : val(0), left(nullptr), right(nullptr) {} 11 | TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 12 | TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 13 | }; 14 | 15 | // iterative 16 | void postorderIterative2(TreeNode* root) 17 | { 18 | std::stack tree; 19 | TreeNode *prev = nullptr; 20 | while(root || !tree.empty()) 21 | { 22 | while(root) 23 | { 24 | tree.push(root); 25 | root = root->left; 26 | } 27 | root = tree.top(); 28 | if (!root->right || root->right == prev) 29 | { 30 | std::cout << " " << root->val; 31 | tree.pop(); 32 | prev = root; 33 | root = nullptr; 34 | } 35 | else 36 | root = root->right; 37 | } 38 | 39 | } 40 | 41 | // Recursive 42 | void postorderRecursive(TreeNode* root) 43 | { 44 | if (root == nullptr) 45 | return ; 46 | postorderRecursive(root->left); 47 | postorderRecursive(root->right); 48 | std::cout << " " << root->val; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /tree/Traversal/Preorder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct TreeNode 6 | { 7 | int val; 8 | TreeNode *left; 9 | TreeNode *right; 10 | TreeNode() : val(0), left(nullptr), right(nullptr) {} 11 | TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 12 | TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 13 | }; 14 | 15 | 16 | // iterative with stack 17 | void preorderIterative1(TreeNode* root) 18 | { 19 | std::stack tmp; 20 | if (!root) return ; 21 | tmp.push(root); 22 | while(!tmp.empty()) 23 | { 24 | root = tmp.top(); 25 | tmp.pop(); 26 | std::cout << " " << root->val ; 27 | if(root->right) tmp.push(root->right); 28 | if(root->left) tmp.push(root->left); 29 | } 30 | } 31 | // iterative 32 | void preorderIterative2(TreeNode* root) 33 | { 34 | std::vector right; 35 | while(root) 36 | { 37 | std::cout << " " << root->val ; 38 | if (root->right != nullptr) 39 | right.push_back(root->right); 40 | root = root->left; 41 | if (!right.empty() && !root) 42 | { 43 | root = right.back(); 44 | right.pop_back(); 45 | } 46 | } 47 | } 48 | 49 | // Recursive 50 | void preorderRecursive(TreeNode* root) 51 | { 52 | if (root == nullptr) 53 | return ; 54 | std::cout << " " << root->val; 55 | preorderRecursive(root->left); 56 | preorderRecursive(root->right); 57 | } 58 | 59 | -------------------------------------------------------------------------------- /tree/Traversal/readme.md: -------------------------------------------------------------------------------- 1 | # Tree Traversal 2 | 3 | This function includes iterative and recursive implementations of the three types of tree traversal: inorder, postorder, and preorder. It takes a binary tree node as input and outputs the values of the nodes in the specified orde 4 | 5 | ## Iterative Implementations 6 | 7 | ### Inorder 8 | The iterative implementation of inorder traversal uses a stack to keep track of the nodes. It pushes the left child of each node onto the stack until it reaches a leaf node. It then pops the top node from the stack, prints its value, and sets the root to its right child. This process continues until the stack is empty. 9 | 10 | ### Postorder 11 | The iterative implementation of postorder traversal uses a stack and a pointer to the previously visited node. It pushes the left child of each node onto the stack until it reaches a leaf node. It then pops the top node from the stack and checks if it has a right child or if its right child has been visited. If not, it pushes the right child onto the stack and repeats the process for the right child. If yes, it prints the value of the node and sets the previously visited node to the current node. This process continues until the stack is empty. 12 | 13 | ### Preorder 14 | The iterative implementation of preorder traversal uses a stack and a vector to keep track of the right child nodes. It prints the value of each node, pushes its right child onto the vector if it exists, and sets the root to its left child. If there are nodes in the vector, it sets the root to the last node in the vector and removes it from the vector. This process continues until the root is null and the vector is empty. 15 | 16 | ### Level Order 17 | This implementation demonstrates a breadth-first traversal of a binary tree, also known as a level order traversal. It systematically traverses the tree level by level using a queue to keep track of nodes. 18 | 19 | ## Recursive Implementations 20 | 21 | ### Inorder 22 | The recursive implementation of inorder traversal first checks if the current node is null. If not, it recursively calls itself on the left child, prints the value of the current node, and recursively calls itself on the right child. 23 | 24 | ### Postorder 25 | The recursive implementation of postorder traversal first checks if the current node is null. If not, it recursively calls itself on the left child, recursively calls itself on the right child, and prints the value of the current node. 26 | 27 | ### Preorder 28 | The recursive implementation of preorder traversal first checks if the current node is null. If not, it prints the value of the current node, recursively calls itself on the left child, and recursively calls itself on the right child. 29 | --------------------------------------------------------------------------------