├── imports ├── test │ ├── input.txt │ └── output.txt ├── Elshorpagi.h ├── problem_solving.cpp └── include.h ├── .gitignore ├── header ├── Queue_LinkedList_Based.h ├── Circular_Queue.h ├── Deque.h ├── Stack_LinkedList_Based.h ├── Priority_Queue_Heap_Based.h ├── Stack_Array_Based.h ├── Min_Heap.h ├── Sparse_Array.h ├── Sparse_Matrix.h ├── Trie_Tree.h ├── Max_Heap.h ├── Sparse_Cube.h ├── AVL_Tree_v2.h ├── Binary_Search_Tree_v2.h ├── Priority_Queue_AVLT_Based.h ├── Vector.h ├── AVL_Tree.h ├── Binary_Search_Tree.h ├── Binary_Tree.h ├── Doubly_LinkedList.h └── Singly_LinkedList.h ├── main.cpp ├── tests ├── queue_linkedlist_based.cpp ├── deque_test.cpp ├── circular_queue_test.cpp ├── stack_linkedlist_based_test.cpp ├── priority_queue_avlt_based_test.cpp ├── stack_array_based_test.cpp ├── avl_tree_test.cpp ├── avl_tree_v2_test.cpp ├── min_heap_test.cpp ├── binary_search_tree_test.cpp ├── priority_queue_heap_based_test.cpp ├── binary_search_tree_v2_test.cpp ├── max_heap_test.cpp ├── singly_linkedlist_test.cpp ├── doubly_linkedlist_test.cpp ├── vector_test.cpp └── binary_tree_test.cpp ├── source ├── Queue_LinkedList_Based.cpp ├── Stack_LinkedList_Based.cpp ├── Circular_Queue.cpp ├── Deque.cpp ├── Sparse_Array.cpp ├── Priority_Queue_Heap_Based.cpp ├── Max_Heap.cpp ├── Hash_Table │ ├── Hash_Table_Chaining_LinkedList.cpp │ ├── Hash_Table_Quadratic_Probing.cpp │ ├── Hash_Table_Chaining_Vector.cpp │ └── Hash_Table_Linear_Probing.cpp ├── Sparse_Matrix.cpp ├── Trie_Tree.cpp ├── Sparse_Cube.cpp ├── Vector.cpp ├── Stack_Array_Based.cpp ├── Priority_Queue_AVLT_Based.cpp ├── Min_Heap.cpp ├── Binary_Search_Tree_v2.cpp ├── AVL_Tree_v2.cpp ├── Doubly_LinkedList.cpp ├── AVL_Tree.cpp ├── Binary_Search_Tree.cpp ├── Singly_LinkedList.cpp └── Binary_Tree.cpp └── README.md /imports/test/input.txt: -------------------------------------------------------------------------------- 1 | 2 2 | -------------------------------------------------------------------------------- /imports/test/output.txt: -------------------------------------------------------------------------------- 1 | Case #1 2 | 3 | DONE 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.vscode 3 | *tempCodeRunnerFile.cpp -------------------------------------------------------------------------------- /header/Queue_LinkedList_Based.h: -------------------------------------------------------------------------------- 1 | #ifndef QUEUE_LINKEDLIST_H 2 | #define QUEUE_LINKEDLIST_H 3 | 4 | #include "Singly_LinkedList.h" 5 | #include "../source/Singly_LinkedList.cpp" 6 | 7 | template 8 | class Queue_LinkedList_Based 9 | { 10 | Singly_LinkedList list; 11 | int size{}; 12 | 13 | public: 14 | Queue_LinkedList_Based(); 15 | ~Queue_LinkedList_Based(); 16 | const int get_size(); 17 | bool is_empty(); 18 | void enqueue(type val); 19 | type dequeue(); 20 | void print(); 21 | }; 22 | #endif -------------------------------------------------------------------------------- /imports/Elshorpagi.h: -------------------------------------------------------------------------------- 1 | 2 | // My Headers, and you can modify them 3 | 4 | // C 5 | #include 6 | #include 7 | #include 8 | 9 | // C++ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | // STL in C++ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include -------------------------------------------------------------------------------- /header/Circular_Queue.h: -------------------------------------------------------------------------------- 1 | #ifndef CIRCULAR_QUEUE_H 2 | #define CIRCULAR_QUEUE_H 3 | 4 | #include 5 | #include 6 | 7 | #define edl '\n' 8 | 9 | template 10 | class Circular_Queue 11 | { 12 | int front{}; 13 | int rear{}; 14 | int size{}; 15 | int added_elements{}; 16 | type *arr{}; 17 | int next(int pos); 18 | 19 | public: 20 | Circular_Queue(int sz); 21 | ~Circular_Queue(); 22 | bool is_full(); 23 | bool is_empty(); 24 | const int get_size(); 25 | void enqueue(type val); 26 | type dequeue(); 27 | void print(); 28 | }; 29 | #endif -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "imports/include.h" 2 | // this include.h for me,so u don't have to use it, but also u can modify them 3 | 4 | #define edl '\n' 5 | 6 | class Data_Structures 7 | { 8 | public: 9 | Data_Structures() { __elshorpagi__; } 10 | void TEST() 11 | { 12 | // test the Data Structures here; 13 | } 14 | }; 15 | 16 | int main() 17 | { 18 | Data_Structures DS; 19 | // freopen("imports/test/input.txt", "r", stdin); 20 | freopen("imports/test/output.txt", "w", stdout); 21 | int tc(1); 22 | // std::cin >> tc; 23 | while (tc--) 24 | std::cout << "Case #" << tc + 1 << edl, DS.TEST(); 25 | std::cout << edl << "DONE" << edl; 26 | return (0); 27 | } -------------------------------------------------------------------------------- /header/Deque.h: -------------------------------------------------------------------------------- 1 | #ifndef DEQUE_H 2 | #define DEQUE_H 3 | 4 | #include 5 | #include 6 | 7 | #define edl '\n' 8 | 9 | template 10 | class Deque 11 | { 12 | int size{}; 13 | int front{}; 14 | int rear{}; 15 | int added_elements{}; 16 | type *array{}; 17 | int next(int pos); 18 | int prev(int pos); 19 | 20 | public: 21 | Deque(int size); 22 | ~Deque(); 23 | const int get_size(); 24 | void enqueue_rear(type val); 25 | void enqueue_front(type val); 26 | type dequeue_front(); 27 | type dequeue_rear(); 28 | int is_empty(); 29 | bool is_full(); 30 | void print(); 31 | }; 32 | #endif -------------------------------------------------------------------------------- /header/Stack_LinkedList_Based.h: -------------------------------------------------------------------------------- 1 | #ifndef STACK_LINKEDLIST_BASED_H 2 | #define STACK_LINKEDLIST_BASED_H 3 | 4 | #include 5 | #include 6 | 7 | #define edl '\n' 8 | 9 | template 10 | struct SDL_Node 11 | { 12 | T data{}; 13 | SDL_Node *next{}; 14 | SDL_Node(T val) : data(val) {} 15 | }; 16 | 17 | template 18 | class Stack_LinkedList_Based 19 | { 20 | SDL_Node *head{}; 21 | int size{}; 22 | 23 | public: 24 | Stack_LinkedList_Based(); 25 | ~Stack_LinkedList_Based(); 26 | const int get_size(); 27 | type is_empty(); 28 | void push(type val); 29 | type pop(); 30 | type peek(); 31 | void print(); 32 | }; 33 | #endif -------------------------------------------------------------------------------- /header/Priority_Queue_Heap_Based.h: -------------------------------------------------------------------------------- 1 | #ifndef PRIORITY_QUEUE_HEAP_BASED_H 2 | #define PRIORITY_QUEUE_HEAP_BASED_H 3 | 4 | #include 5 | #include 6 | 7 | #define edl '\n' 8 | 9 | template 10 | class Priority_Queue_Heap_Based 11 | { 12 | int capacity{1}; 13 | type *key{}; 14 | type *value{}; 15 | int size{}; 16 | 17 | int left(int pos); 18 | int right(int pos); 19 | int parent(int pos); 20 | void heapify_up(int child_pos); 21 | void heapify_down(int parent_pos); 22 | void expand_capacity(); 23 | 24 | public: 25 | Priority_Queue_Heap_Based(); 26 | ~Priority_Queue_Heap_Based(); 27 | const int get_size(); 28 | bool is_empty(); 29 | void enqueue(type val, int priority); 30 | type dequeue(); 31 | type top(); 32 | }; 33 | #endif -------------------------------------------------------------------------------- /tests/queue_linkedlist_based.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/Queue_LinkedList_Based.cpp" 2 | 3 | Queue_LinkedList_Based list_queue; 4 | const void initializing() 5 | { 6 | 7 | for (int i(1); i < 11; ++i) 8 | list_queue.enqueue(i); 9 | } 10 | 11 | const void test_get_size() 12 | { 13 | assert(list_queue.get_size() == 10); 14 | } 15 | 16 | const void test_is_empty() 17 | { 18 | assert(list_queue.is_empty() == false); 19 | } 20 | 21 | const void test_dequeue() 22 | { 23 | int popped(list_queue.dequeue()); 24 | assert(popped == 1); 25 | int popped2(list_queue.dequeue()); 26 | assert(popped2 == 2); 27 | } 28 | 29 | int main() 30 | { 31 | freopen("../imports/test/output.txt", "w", stdout); 32 | initializing(); 33 | test_get_size(); 34 | test_is_empty(); 35 | test_dequeue(); 36 | std::cout << edl << "DONE" << edl; 37 | // you must see 'DONE' in output 38 | return (0); 39 | } 40 | -------------------------------------------------------------------------------- /header/Stack_Array_Based.h: -------------------------------------------------------------------------------- 1 | #ifndef STACK_ARRAY_BASED_H 2 | #define STACK_ARRAY_BASED_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define edl '\n' 9 | 10 | template 11 | class Stack_Array_Based 12 | { 13 | type *arr{}; 14 | int size{}; 15 | int top{}; 16 | 17 | public: 18 | Stack_Array_Based(int sz); 19 | ~Stack_Array_Based(); 20 | const int get_size(); 21 | bool is_full(); 22 | bool is_empty(); 23 | void push(type val); 24 | type pop(); 25 | type peek(); 26 | void print(); 27 | std::string reverse_subwords(std::string line); 28 | int reverse_num(int num); 29 | char get_open_match(char ch); 30 | bool valid_parentheses(std::string str); 31 | std::string remove_all_adjacent_duplicates(std::string str); 32 | void asteroid_collision(std::vector &asteroids); 33 | void insert_at_bottom(type val); 34 | void reverse(); 35 | }; 36 | #endif -------------------------------------------------------------------------------- /tests/deque_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/Deque.cpp" 2 | 3 | Deque deque(20); 4 | const void initializing() 5 | { 6 | for (int i(1); i < 21; ++i) 7 | deque.enqueue_rear(i); 8 | } 9 | 10 | const void test_get_size() 11 | { 12 | assert(deque.get_size() == 20); 13 | } 14 | 15 | const void test_is_full() 16 | { 17 | assert(deque.is_full() == true); 18 | } 19 | 20 | const void test_is_empty() 21 | { 22 | assert(deque.is_empty() == false); 23 | } 24 | 25 | const void test_dequeue() 26 | { 27 | deque.dequeue_rear(); 28 | assert(deque.get_size() == 19); 29 | 30 | deque.dequeue_front(); 31 | assert(deque.get_size() == 18); 32 | } 33 | 34 | int main() 35 | { 36 | freopen("../imports/test/output.txt", "w", stdout); 37 | initializing(); 38 | test_get_size(); 39 | test_is_full(); 40 | test_is_empty(); 41 | test_dequeue(); 42 | std::cout << edl << "DONE" << edl; 43 | // you must see 'DONE' in output 44 | return (0); 45 | } 46 | -------------------------------------------------------------------------------- /header/Min_Heap.h: -------------------------------------------------------------------------------- 1 | #ifndef MIN_HEAP_H 2 | #define MIN_HEAP_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define edl '\n' 9 | 10 | template 11 | class Min_Heap 12 | { 13 | type *array{}; 14 | int size{}; 15 | int capacity{1}; // we made capacity trick like vector; 16 | int left(int pos); 17 | int right(int pos); 18 | int parent(int pos); 19 | void heapify_up(int child_pos); 20 | void heapify_down(int parent_pos); 21 | void heapify(); 22 | bool is_heap(int parent_pos); 23 | void expand_capacity(); 24 | 25 | public: 26 | Min_Heap(); 27 | Min_Heap(const std::vector &vec); 28 | ~Min_Heap(); 29 | void push(type val); 30 | void pop(); 31 | type top(); 32 | const int get_size(); 33 | bool is_empty(); 34 | void print_less_than(type val, int pos = 0); 35 | bool is_heap_array(type *p, int n); 36 | void heap_sort(type *p, int n); 37 | bool search(type val); 38 | }; 39 | #endif -------------------------------------------------------------------------------- /tests/circular_queue_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/Circular_Queue.cpp" 2 | 3 | Circular_Queue c_queue(20); 4 | const void initializing() 5 | { 6 | for (int i(1); i < 21; ++i) 7 | c_queue.enqueue(i); 8 | } 9 | 10 | const void test_get_size() 11 | { 12 | assert(c_queue.get_size() == 20); 13 | } 14 | 15 | const void test_is_full() 16 | { 17 | assert(c_queue.is_full() == true); 18 | } 19 | 20 | const void test_is_empty() 21 | { 22 | assert(c_queue.is_empty() == false); 23 | } 24 | 25 | const void test_dequeue() 26 | { 27 | int popped(c_queue.dequeue()); 28 | assert(popped == 1); 29 | int popped2(c_queue.dequeue()); 30 | assert(popped2 == 2); 31 | } 32 | 33 | int main() 34 | { 35 | freopen("../imports/test/output.txt", "w", stdout); 36 | initializing(); 37 | test_get_size(); 38 | test_is_full(); 39 | test_is_empty(); 40 | test_dequeue(); 41 | std::cout << edl << "DONE" << edl; 42 | // you must see 'DONE' in output 43 | return (0); 44 | } 45 | -------------------------------------------------------------------------------- /header/Sparse_Array.h: -------------------------------------------------------------------------------- 1 | #ifndef SPARSE_ARRAY_H 2 | #define SPARSE_ARRAY_H 3 | 4 | #include 5 | #include 6 | 7 | #define edl '\n' 8 | 9 | template 10 | struct Col_Node 11 | { 12 | T data{}; 13 | int col{}; 14 | Col_Node *next{}; 15 | Col_Node *prev{}; 16 | Col_Node(T data, int col) : data(data), col(col) {} 17 | }; 18 | 19 | template 20 | class Sparse_Array 21 | { 22 | Col_Node *head{}; 23 | Col_Node *tail{}; 24 | int length{}; 25 | int cols{}; 26 | 27 | void link(Col_Node *first, Col_Node *second); 28 | Col_Node *add_node_between_node_and_next(Col_Node *node_before, type data, int col); 29 | Col_Node *get_col(int col, bool is_create_if_missing); 30 | 31 | public: 32 | Sparse_Array(int cols); 33 | ~Sparse_Array(); 34 | void print_row(); 35 | void print_row_nonzero(); 36 | void set_value(type data, int col); 37 | type get_value(int col); 38 | void add(Sparse_Array &other); 39 | }; 40 | #endif -------------------------------------------------------------------------------- /header/Sparse_Matrix.h: -------------------------------------------------------------------------------- 1 | #ifndef SPARSE_MATRIX_H 2 | #define SPARSE_MATRIX_H 3 | 4 | #include "../source/Sparse_Array.cpp" 5 | 6 | template 7 | struct Row_Node 8 | { 9 | int row; 10 | Sparse_Array list; 11 | Row_Node *next{}; 12 | Row_Node *prev{}; 13 | Row_Node(int r, int c) : row(r), list(c) {} 14 | }; 15 | 16 | template 17 | class Sparse_Matrix 18 | { 19 | Row_Node *head{}; 20 | Row_Node *tail{}; 21 | int length{}; 22 | int rows{}; 23 | int cols{}; 24 | 25 | Row_Node *get_row(int row, bool flag); 26 | void link(Row_Node *first, Row_Node *second); 27 | Row_Node *add_node_between_node_and_next(Row_Node *node_before, int row); 28 | 29 | public: 30 | Sparse_Matrix(int rows, int cols); 31 | ~Sparse_Matrix(); 32 | void set_value(type data, int row, int col); 33 | type get_value(int row, int col); 34 | void add(Sparse_Matrix &other); 35 | void print_matrix(); 36 | void print_matrix_nonzero(); 37 | }; 38 | #endif -------------------------------------------------------------------------------- /source/Queue_LinkedList_Based.cpp: -------------------------------------------------------------------------------- 1 | #ifndef QUEUE_LINKEDLIST_CPP 2 | #define QUEUE_LINKEDLIST_CPP 3 | 4 | #include "../header/Queue_LinkedList_Based.h" 5 | 6 | template 7 | Queue_LinkedList_Based::Queue_LinkedList_Based() {} 8 | 9 | template 10 | Queue_LinkedList_Based::~Queue_LinkedList_Based() 11 | { 12 | list.~Singly_LinkedList(); 13 | size = 0; 14 | } 15 | 16 | template 17 | const int Queue_LinkedList_Based::get_size() 18 | { 19 | return size; 20 | } 21 | 22 | template 23 | bool Queue_LinkedList_Based::is_empty() 24 | { 25 | return size == 0; 26 | } 27 | 28 | template 29 | void Queue_LinkedList_Based::enqueue(type val) 30 | { 31 | list.insert_end(val); 32 | ++size; 33 | } 34 | 35 | template 36 | type Queue_LinkedList_Based::dequeue() 37 | { 38 | --size; 39 | return list.pop_front(); 40 | } 41 | 42 | template 43 | void Queue_LinkedList_Based::print() 44 | { 45 | list.print(); 46 | } 47 | #endif -------------------------------------------------------------------------------- /header/Trie_Tree.h: -------------------------------------------------------------------------------- 1 | #ifndef TRIE_TREE_H 2 | #define TRIE_TREE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define sz(v) ((int)((v).size())) 9 | #define edl '\n' 10 | 11 | // if you need to build a Suffix Trie 12 | // it's same idea but just need to reverse the input 13 | 14 | class Trie_Tree 15 | { 16 | std::map child; 17 | bool is_leaf{}; 18 | 19 | public: 20 | Trie_Tree(); 21 | ~Trie_Tree(); 22 | void insert_recursive(std::string str, int idx = 0); 23 | void insert_iterative(std::string str); 24 | bool word_exist_recursive(std::string str, int idx = 0); 25 | bool word_exist_iterative(std::string str); 26 | bool prefix_exist(std::string str, int idx = 0); 27 | std::string first_word_prefix(const std::string &str); 28 | void get_all_strings(std::vector &res, std::string cur_str = ""); 29 | void auto_complete_0(const std::string &str, std::vector &res); 30 | void auto_complete_1(const std::string &str, std::vector &res); 31 | bool word_exist_with_1_change(std::string str); 32 | }; 33 | #endif -------------------------------------------------------------------------------- /tests/stack_linkedlist_based_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/Stack_LinkedList_Based.cpp" 2 | 3 | Stack_LinkedList_Based stack; 4 | const void initializing() 5 | { 6 | for (int i(11); i < 20; ++i) 7 | stack.push(i); 8 | } 9 | 10 | const void test_get_size() 11 | { 12 | assert(stack.get_size() == 9); 13 | } 14 | 15 | const void test_is_empty() 16 | { 17 | assert(stack.is_empty() == false); 18 | } 19 | 20 | const void test_pop() 21 | { 22 | int popped(stack.pop()); 23 | assert(popped == 19); 24 | stack.push(20); 25 | int popped2(stack.pop()); 26 | assert(popped2 == 20); 27 | } 28 | 29 | const void test_peek() 30 | { 31 | assert(stack.peek() == 18); 32 | stack.pop(); 33 | assert(stack.peek() == 17); 34 | stack.pop(); 35 | assert(stack.peek() == 16); 36 | } 37 | 38 | int main() 39 | { 40 | freopen("../imports/test/output.txt", "w", stdout); 41 | initializing(); 42 | test_get_size(); 43 | test_is_empty(); 44 | test_pop(); 45 | test_peek(); 46 | std::cout << edl << "DONE" << edl; 47 | // you must see 'DONE' in output 48 | return (0); 49 | } 50 | -------------------------------------------------------------------------------- /header/Max_Heap.h: -------------------------------------------------------------------------------- 1 | #ifndef MAX_HEAP_H 2 | #define MAX_HEAP_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define edl '\n' 9 | 10 | /* 11 | * we can build it using min heap by the following: 12 | * -1 create an object from Min_Heap; 13 | * -2 any element we choose will be multiplied by -1 before being pushed to the Min_heap; 14 | * -3 before printing the top, it will be multiplied by -1 to get back the real value; 15 | */ 16 | 17 | template 18 | class Max_Heap 19 | { 20 | type *array{}; 21 | int size{}; 22 | int capacity{1}; // we made capacity trick like vector; 23 | int left(int pos); 24 | int right(int pos); 25 | int parent(int pos); 26 | void heapify_up(int child_pos); 27 | void heapify_down(int parent_pos); 28 | void heapify(); 29 | void expand_capacity(); 30 | 31 | public: 32 | Max_Heap(); 33 | Max_Heap(const std::vector &vec); 34 | ~Max_Heap(); 35 | void push(type val); 36 | void pop(); 37 | type top(); 38 | const int get_size(); 39 | bool is_empty(); 40 | bool search(type val); 41 | }; 42 | #endif -------------------------------------------------------------------------------- /header/Sparse_Cube.h: -------------------------------------------------------------------------------- 1 | #ifndef SPARSE_CUBE_H 2 | #define SPARSE_CUBE_H 3 | 4 | #include "../source/Sparse_Matrix.cpp" 5 | 6 | template 7 | struct Height_Node 8 | { 9 | int height; 10 | Sparse_Matrix matrix; 11 | Height_Node *next{}; 12 | Height_Node *prev{}; 13 | Height_Node(int h, int r, int c) : height(h), matrix(r, c) {} 14 | }; 15 | 16 | template 17 | class Sparse_Cube 18 | { 19 | Height_Node *head{}; 20 | Height_Node *tail{}; 21 | int length{}; 22 | int rows{}; 23 | int cols{}; 24 | int heights{}; 25 | 26 | Height_Node *get_height(int height, bool flag); 27 | void link(Height_Node *first, Height_Node *second); 28 | Height_Node *add_node_between_node_and_next(Height_Node *node_before, int height); 29 | 30 | public: 31 | Sparse_Cube(int row, int col, int height); 32 | ~Sparse_Cube(); 33 | void set_value(type data, int row, int col, int height); 34 | type get_value(int row, int col, int height); 35 | void add(Sparse_Cube &other); 36 | void print_cube(); 37 | void print_cube_nonzero(); 38 | }; 39 | #endif -------------------------------------------------------------------------------- /tests/priority_queue_avlt_based_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/Priority_Queue_AVLT_Based.cpp" 2 | 3 | Priority_Queue_AVLT_Based Priority_Queue; 4 | 5 | const void initializing() 6 | { 7 | Priority_Queue.enqueue(12, 0); 8 | Priority_Queue.enqueue(21, 2); 9 | Priority_Queue.enqueue(35, 3); 10 | Priority_Queue.enqueue(42, 4); 11 | Priority_Queue.enqueue(55, 5); 12 | Priority_Queue.enqueue(77, 6); 13 | Priority_Queue.enqueue(89, 7); 14 | } 15 | 16 | const void test_is_empty() 17 | { 18 | assert(Priority_Queue.is_empty() == false); 19 | } 20 | 21 | const void test_dequeue_and_top() 22 | { 23 | int dequeued(Priority_Queue.dequeue()); 24 | assert(dequeued == 89); 25 | Priority_Queue.dequeue(), dequeued = Priority_Queue.dequeue(); 26 | assert(dequeued == 55); 27 | dequeued = Priority_Queue.dequeue(); 28 | assert(dequeued == 42); 29 | } 30 | 31 | int main() 32 | { 33 | freopen("../imports/test/output.txt", "w", stdout); 34 | initializing(); 35 | test_is_empty(); 36 | test_dequeue_and_top(); 37 | std::cout << edl << "DONE" << edl; 38 | // you must see 'DONE' in output 39 | return (0); 40 | } 41 | -------------------------------------------------------------------------------- /tests/stack_array_based_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/Stack_Array_Based.cpp" 2 | 3 | Stack_Array_Based stack(10); 4 | const void initializing() 5 | { 6 | for (int i(1); i < 11; ++i) 7 | stack.push(i); 8 | } 9 | 10 | const void test_get_size() 11 | { 12 | assert(stack.get_size() == 10); 13 | } 14 | 15 | const void test_is_full() 16 | { 17 | assert(stack.is_full() == true); 18 | } 19 | 20 | const void test_is_empty() 21 | { 22 | assert(stack.is_empty() == false); 23 | } 24 | 25 | const void test_pop() 26 | { 27 | int popped(stack.pop()); 28 | assert(popped == 10); 29 | stack.push(11); 30 | int popped2(stack.pop()); 31 | assert(popped2 == 11); 32 | } 33 | 34 | const void test_peek() 35 | { 36 | assert(stack.peek() == 9); 37 | stack.pop(); 38 | assert(stack.peek() == 8); 39 | stack.pop(); 40 | assert(stack.peek() == 7); 41 | } 42 | 43 | int main() 44 | { 45 | freopen("../imports/test/output.txt", "w", stdout); 46 | initializing(); 47 | test_get_size(); 48 | test_is_full(); 49 | test_is_empty(); 50 | test_pop(); 51 | test_peek(); 52 | std::cout << edl << "DONE" << edl; 53 | // you must see 'DONE' in output 54 | return (0); 55 | } 56 | -------------------------------------------------------------------------------- /header/AVL_Tree_v2.h: -------------------------------------------------------------------------------- 1 | #ifndef AVL_TREE_V2_H 2 | #define AVL_TREE_V2_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define edl '\n' 9 | 10 | template 11 | class AVL_Tree_v2 12 | { 13 | type data{}; 14 | int height{}; 15 | AVL_Tree_v2 *left{}; 16 | AVL_Tree_v2 *right{}; 17 | 18 | int ch_height(AVL_Tree_v2 *node); 19 | int update_height(); 20 | int balance_factor(); 21 | AVL_Tree_v2 *right_rotation(AVL_Tree_v2 *Q); 22 | AVL_Tree_v2 *left_rotation(AVL_Tree_v2 *P); 23 | AVL_Tree_v2 *balance(AVL_Tree_v2 *node); 24 | AVL_Tree_v2 *min_node(); 25 | AVL_Tree_v2 *max_node(); 26 | void special_delete(AVL_Tree_v2 *child); 27 | AVL_Tree_v2 *delete_node(type val, AVL_Tree_v2 *node); 28 | void re_root(AVL_Tree_v2 *node); 29 | void clear(); 30 | void verify(); 31 | 32 | public: 33 | AVL_Tree_v2(type data); 34 | ~AVL_Tree_v2(); 35 | void insert(type val); 36 | void delete_value(type val); 37 | void level_order_traversal(); 38 | bool is_bst(); 39 | type min_value(); 40 | type max_value(); 41 | bool search(type val); 42 | }; 43 | #endif -------------------------------------------------------------------------------- /header/Binary_Search_Tree_v2.h: -------------------------------------------------------------------------------- 1 | #ifndef BINARY_SEARCH_TREE_V2_H 2 | #define BINARY_SEARCH_TREE_V2_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define edl '\n' 12 | 13 | template 14 | struct BST_Node 15 | { 16 | T data{}; 17 | BST_Node *left{}; 18 | BST_Node *right{}; 19 | BST_Node(T data) : data(data) {} 20 | }; 21 | 22 | template 23 | class Binary_Search_Tree_v2 24 | { 25 | BST_Node *root{}; 26 | void insert_node(type val, BST_Node *node); 27 | bool search_node(type val, BST_Node *node); 28 | void print_in_order_node(BST_Node *node); 29 | void clear(BST_Node *node); 30 | BST_Node *min_node(BST_Node *node); 31 | BST_Node *max_node(BST_Node *node); 32 | BST_Node *delete_node(type target, BST_Node *node); 33 | bool is_bst(BST_Node *node); 34 | 35 | public: 36 | Binary_Search_Tree_v2(); 37 | ~Binary_Search_Tree_v2(); 38 | void insert_value(type val); 39 | bool search(type val); 40 | void print_in_order(); 41 | type min_value(); 42 | type max_value(); 43 | void delete_value(type val); 44 | void level_order_traversal(); 45 | }; 46 | #endif -------------------------------------------------------------------------------- /tests/avl_tree_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/AVL_Tree.cpp" 2 | 3 | AVL_Tree tree; 4 | 5 | const void initializing() 6 | { 7 | for (int i(0); i < 33; ++i) 8 | tree.insert_value(i); 9 | } 10 | 11 | const void test_search() 12 | { 13 | assert(tree.search(25) == true), assert(tree.search(17) == true); 14 | assert(tree.search(55) == false), assert(tree.search(35) == false); 15 | } 16 | 17 | const void test_max_and_min_value() 18 | { 19 | assert(tree.min_value() == 0), assert(tree.max_value() == 32); 20 | } 21 | 22 | const void test_delete_value() 23 | { 24 | assert(tree.search(32) == true); 25 | tree.delete_value(32); 26 | assert(tree.search(32) == false); 27 | 28 | assert(tree.search(28) == true); 29 | tree.delete_value(28); 30 | assert(tree.search(28) == false); 31 | 32 | assert(tree.search(18) == true); 33 | tree.delete_value(18); 34 | assert(tree.search(18) == false); 35 | 36 | assert(tree.search(5) == true); 37 | tree.delete_value(5); 38 | assert(tree.search(5) == false); 39 | } 40 | 41 | int main() 42 | { 43 | freopen("../imports/test/output.txt", "w", stdout); 44 | initializing(); 45 | test_search(); 46 | test_max_and_min_value(); 47 | test_delete_value(); 48 | std::cout << edl << "DONE" << edl; 49 | // you must see 'DONE' in output 50 | return (0); 51 | } 52 | -------------------------------------------------------------------------------- /tests/avl_tree_v2_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/AVL_Tree_v2.cpp" 2 | 3 | AVL_Tree_v2 tree(0); 4 | 5 | const void initializing() 6 | { 7 | for (int i(1); i < 33; ++i) 8 | tree.insert(i); 9 | } 10 | 11 | const void test_search() 12 | { 13 | assert(tree.search(25) == true), assert(tree.search(17) == true); 14 | assert(tree.search(55) == false), assert(tree.search(35) == false); 15 | } 16 | 17 | const void test_max_and_min_value() 18 | { 19 | assert(tree.min_value() == 0), assert(tree.max_value() == 32); 20 | } 21 | 22 | const void test_delete_value() 23 | { 24 | assert(tree.search(32) == true); 25 | tree.delete_value(32); 26 | assert(tree.search(32) == false); 27 | 28 | assert(tree.search(28) == true); 29 | tree.delete_value(28); 30 | assert(tree.search(28) == false); 31 | 32 | assert(tree.search(18) == true); 33 | tree.delete_value(18); 34 | assert(tree.search(18) == false); 35 | 36 | assert(tree.search(5) == true); 37 | tree.delete_value(5); 38 | assert(tree.search(5) == false); 39 | } 40 | 41 | int main() 42 | { 43 | freopen("../imports/test/output.txt", "w", stdout); 44 | initializing(); 45 | test_search(); 46 | test_max_and_min_value(); 47 | test_delete_value(); 48 | std::cout << edl << "DONE" << edl; 49 | // you must see 'DONE' in output 50 | return (0); 51 | } 52 | -------------------------------------------------------------------------------- /tests/min_heap_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/Min_Heap.cpp" 2 | 3 | std::vector vec{2, 17, 22, 10, 8, 37, 14, 19, 7, 6, 5, 12, 25, 30}; 4 | Min_Heap heap; 5 | 6 | const void initializing() 7 | { 8 | for (int i(0); i < (int)vec.size(); ++i) 9 | heap.push(vec[i]); 10 | } 11 | 12 | const void test_get_size() 13 | { 14 | assert(heap.get_size() == (int)vec.size()); 15 | } 16 | 17 | const void test_search() 18 | { 19 | assert(heap.search(17) == true), assert(heap.search(27) == false); 20 | assert(heap.search(7) == true), assert(heap.search(41) == false); 21 | } 22 | 23 | const void test_is_empty() 24 | { 25 | assert(heap.is_empty() == false); 26 | } 27 | 28 | const void test_pop_and_top() 29 | { 30 | heap.pop(); 31 | assert(heap.search(2) == false); 32 | assert(heap.top() == 5); 33 | heap.pop(), heap.pop(); 34 | assert(heap.search(5) == false), assert(heap.search(6) == false); 35 | assert(heap.top() == 7); 36 | heap.pop(); 37 | assert(heap.search(7) == false), assert(heap.top() == 8); 38 | } 39 | 40 | int main() 41 | { 42 | freopen("../imports/test/output.txt", "w", stdout); 43 | initializing(); 44 | test_get_size(); 45 | test_search(); 46 | test_is_empty(); 47 | test_pop_and_top(); 48 | std::cout << edl << "DONE" << edl; 49 | // you must see 'DONE' in output 50 | return (0); 51 | } 52 | -------------------------------------------------------------------------------- /tests/binary_search_tree_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/Binary_Search_Tree.cpp" 2 | 3 | Binary_Search_Tree *tree(new Binary_Search_Tree(50)); 4 | 5 | const void initializing() 6 | { 7 | tree->insert(20), tree->insert(60); 8 | tree->insert(15), tree->insert(45); 9 | tree->insert(70), tree->insert(35); 10 | tree->insert(73), tree->insert(14); 11 | tree->insert(16), tree->insert(36), tree->insert(58); 12 | } 13 | 14 | const void test_is_bst() 15 | { 16 | assert(tree->is_bst_0() == true), assert(tree->is_bst_1() == true); 17 | } 18 | 19 | const void test_search() 20 | { 21 | assert(tree->search_iterative(35) == true), assert(tree->search(70) == true); 22 | assert(tree->search_iterative(55) == false), assert(tree->search(25) == false); 23 | } 24 | 25 | const void test_max_and_min_value() 26 | { 27 | assert(tree->min_value() == 14), assert(tree->max_value() == 73); 28 | } 29 | 30 | const void test_LCA() 31 | { 32 | assert(tree->LCA(35, 60) == 50), assert(tree->LCA(14, 16) == 15); 33 | assert(tree->LCA(70, 73) == 70); 34 | } 35 | 36 | int main() 37 | { 38 | freopen("../imports/test/output.txt", "w", stdout); 39 | initializing(); 40 | test_is_bst(); 41 | test_search(); 42 | test_max_and_min_value(); 43 | test_LCA(); 44 | std::cout << edl << "DONE" << edl; 45 | // you must see 'DONE' in output 46 | return (0); 47 | } 48 | -------------------------------------------------------------------------------- /tests/priority_queue_heap_based_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/Priority_Queue_Heap_Based.cpp" 2 | 3 | Priority_Queue_Heap_Based Priority_Queue; 4 | 5 | const void initializing() 6 | { 7 | Priority_Queue.enqueue(12, 0); 8 | Priority_Queue.enqueue(21, 2); 9 | Priority_Queue.enqueue(35, 3); 10 | Priority_Queue.enqueue(42, 4); 11 | Priority_Queue.enqueue(55, 5); 12 | Priority_Queue.enqueue(77, 6); 13 | Priority_Queue.enqueue(89, 7); 14 | } 15 | 16 | const void test_get_size() 17 | { 18 | 19 | assert(Priority_Queue.get_size() == 7); 20 | } 21 | 22 | const void test_is_empty() 23 | { 24 | assert(Priority_Queue.is_empty() == false); 25 | } 26 | 27 | const void test_dequeue_and_top() 28 | { 29 | int dequeued(Priority_Queue.dequeue()); 30 | assert(dequeued == 89), assert(Priority_Queue.top() == 77); 31 | Priority_Queue.dequeue(), dequeued = Priority_Queue.dequeue(); 32 | assert(Priority_Queue.top() == 42), assert(dequeued == 55); 33 | dequeued = Priority_Queue.dequeue(); 34 | assert(Priority_Queue.top() == 35), assert(dequeued == 42); 35 | } 36 | 37 | int main() 38 | { 39 | freopen("../imports/test/output.txt", "w", stdout); 40 | initializing(); 41 | test_get_size(); 42 | test_is_empty(); 43 | test_dequeue_and_top(); 44 | std::cout << edl << "DONE" << edl; 45 | // you must see 'DONE' in output 46 | return (0); 47 | } -------------------------------------------------------------------------------- /tests/binary_search_tree_v2_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/Binary_Search_Tree_v2.cpp" 2 | 3 | Binary_Search_Tree_v2 *tree(new Binary_Search_Tree_v2()); 4 | 5 | const void initializing() 6 | { 7 | tree->insert_value(20), tree->insert_value(60); 8 | tree->insert_value(15), tree->insert_value(45); 9 | tree->insert_value(70), tree->insert_value(35); 10 | tree->insert_value(73), tree->insert_value(14); 11 | tree->insert_value(16), tree->insert_value(36), tree->insert_value(58); 12 | } 13 | 14 | const void test_search() 15 | { 16 | assert(tree->search(45) == true), assert(tree->search(70) == true); 17 | assert(tree->search(55) == false), assert(tree->search(17) == false); 18 | } 19 | 20 | const void test_max_and_min_value() 21 | { 22 | assert(tree->min_value() == 14), assert(tree->max_value() == 73); 23 | } 24 | 25 | const void test_delete_value() 26 | { 27 | assert(tree->search(15) == true), assert(tree->search(60) == true); 28 | tree->delete_value(15), tree->delete_value(60); 29 | assert(tree->search(15) == false), assert(tree->search(60) == false); 30 | } 31 | 32 | int main() 33 | { 34 | freopen("../imports/test/output.txt", "w", stdout); 35 | initializing(); 36 | test_search(); 37 | test_max_and_min_value(); 38 | test_delete_value(); 39 | std::cout << edl << "DONE" << edl; 40 | // you must see 'DONE' in output 41 | return (0); 42 | } 43 | -------------------------------------------------------------------------------- /tests/max_heap_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/Max_Heap.cpp" 2 | 3 | std::vector vec{2, 17, 22, 10, 8, 37, 14, 19, 7, 6, 5, 12, 25, 30}; 4 | Max_Heap heap; 5 | 6 | const void initializing() 7 | { 8 | for (int i(0); i < (int)vec.size(); ++i) 9 | heap.push(vec[i]); 10 | } 11 | 12 | const void test_get_size() 13 | { 14 | assert(heap.get_size() == (int)vec.size()); 15 | } 16 | 17 | const void test_search() 18 | { 19 | assert(heap.search(17) == true), assert(heap.search(27) == false); 20 | assert(heap.search(7) == true), assert(heap.search(41) == false); 21 | } 22 | 23 | const void test_is_empty() 24 | { 25 | assert(heap.is_empty() == false); 26 | } 27 | 28 | const void test_pop_and_top() 29 | { 30 | heap.pop(); 31 | assert(heap.search(37) == false); 32 | assert(heap.top() == 30); 33 | heap.pop(), heap.pop(); 34 | assert(heap.search(30) == false), assert(heap.search(30) == false); 35 | assert(heap.search(25) == false), assert(heap.top() == 22); 36 | heap.pop(); 37 | assert(heap.search(22) == false), assert(heap.top() == 19); 38 | } 39 | 40 | int main() 41 | { 42 | freopen("../imports/test/output.txt", "w", stdout); 43 | initializing(); 44 | test_get_size(); 45 | test_search(); 46 | test_is_empty(); 47 | test_pop_and_top(); 48 | std::cout << edl << "DONE" << edl; 49 | // you must see 'DONE' in output 50 | return (0); 51 | } 52 | -------------------------------------------------------------------------------- /source/Stack_LinkedList_Based.cpp: -------------------------------------------------------------------------------- 1 | #ifndef STACK_LINKEDLIST_BASED_CPP 2 | #define STACK_LINKEDLIST_BASED_CPP 3 | 4 | #include "../header/Stack_LinkedList_Based.h" 5 | 6 | template 7 | Stack_LinkedList_Based::Stack_LinkedList_Based() {} 8 | 9 | template 10 | Stack_LinkedList_Based::~Stack_LinkedList_Based() 11 | { 12 | while (is_empty()) 13 | pop(); 14 | head = nullptr; 15 | } 16 | 17 | template 18 | const int Stack_LinkedList_Based::get_size() 19 | { 20 | return size; 21 | } 22 | 23 | template 24 | type Stack_LinkedList_Based::is_empty() 25 | { 26 | return !head; 27 | } 28 | 29 | template 30 | void Stack_LinkedList_Based::push(type val) 31 | { 32 | SDL_Node *item(new SDL_Node(val)); 33 | item->next = head; 34 | head = item; 35 | ++size; 36 | } 37 | 38 | template 39 | type Stack_LinkedList_Based::pop() 40 | { 41 | assert(!is_empty()); 42 | type element(head->data); 43 | SDL_Node *tmp(head); 44 | head = head->next; 45 | delete tmp; 46 | return element; 47 | } 48 | 49 | template 50 | type Stack_LinkedList_Based::peek() 51 | { 52 | assert(!is_empty()); 53 | return head->data; 54 | } 55 | 56 | template 57 | void Stack_LinkedList_Based::print() 58 | { 59 | for (SDL_Node *cur(head); cur; cur = cur->next) 60 | std::cout << cur->data << ' '; 61 | std::cout << edl; 62 | } 63 | #endif -------------------------------------------------------------------------------- /header/Priority_Queue_AVLT_Based.h: -------------------------------------------------------------------------------- 1 | #ifndef PRIORITY_QUEUE_AVLT_BASED_H 2 | #define PRIORITY_QUEUE_AVLT_BASED_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define edl '\n' 9 | 10 | template 11 | struct PQ_Node 12 | { 13 | int priority{}; 14 | int height{}; 15 | std::vector task_ids{}; 16 | PQ_Node *left{}; 17 | PQ_Node *right{}; 18 | 19 | PQ_Node(T task_id, int priority) : priority(priority) 20 | { 21 | task_ids.push_back(task_id); 22 | } 23 | 24 | int ch_height(PQ_Node *node) 25 | { 26 | if (!node) 27 | return -1; 28 | return node->height; 29 | } 30 | int update_height() 31 | { 32 | return height = 1 + std::max(ch_height(left), ch_height(right)); 33 | } 34 | int balance_factor() 35 | { 36 | return ch_height(left) - ch_height(right); 37 | } 38 | }; 39 | 40 | template 41 | class Priority_Queue_AVLT_Based 42 | { 43 | PQ_Node *root{}; 44 | bool search(type target, PQ_Node *node); 45 | PQ_Node *right_rotation(PQ_Node *Q); 46 | PQ_Node *left_rotation(PQ_Node *P); 47 | PQ_Node *balance(PQ_Node *node); 48 | PQ_Node *insert_node(type task_id, int priority, PQ_Node *node); 49 | PQ_Node *min_node(PQ_Node *cur); 50 | PQ_Node *max_node(PQ_Node *cur); 51 | PQ_Node *delete_node(int priority, PQ_Node *node); 52 | void clear(PQ_Node *node); 53 | 54 | public: 55 | Priority_Queue_AVLT_Based(); 56 | ~Priority_Queue_AVLT_Based(); 57 | void enqueue(type task_id, int task_priority); 58 | type dequeue(); 59 | bool is_empty(); 60 | }; 61 | #endif -------------------------------------------------------------------------------- /imports/problem_solving.cpp: -------------------------------------------------------------------------------- 1 | // #include 2 | #include "Elshorpagi.h" 3 | 4 | using namespace std; 5 | 6 | typedef long long ll; 7 | typedef pair pii; 8 | typedef vector vi; 9 | typedef vector vvi; 10 | typedef vector vll; 11 | typedef vector vvll; 12 | typedef vector vpii; 13 | typedef vector vc; 14 | 15 | #define _CRT_SECURE_NO_DEPRECATE 16 | #define Sukuna (ios_base::sync_with_stdio(false), cin.tie(NULL)) 17 | #define all(v) ((v).begin()), ((v).end()) 18 | #define sz(v) ((int)((v).size())) 19 | #define cl(v) ((v).clear()) 20 | #define edl '\n' 21 | #define fr(i, x, n) for (int i(x); i < n; ++i) 22 | #define fl(i, x, n) for (int i(x); i > n; --i) 23 | #define fc(it, v) for (auto &(it) : (v)) 24 | #define sq(x) (x) * (x) 25 | #define yes cout << "YES\n" 26 | #define no cout << "NO\n" 27 | 28 | struct TreeNode 29 | { 30 | int val; 31 | TreeNode *left; 32 | TreeNode *right; 33 | TreeNode() : val(0), left(nullptr), right(nullptr) {} 34 | TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} 35 | TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} 36 | }; 37 | 38 | struct ListNode 39 | { 40 | int val; 41 | ListNode *next; 42 | ListNode() : val(0), next(nullptr) {} 43 | ListNode(int x) : val(x), next(nullptr) {} 44 | ListNode(int x, ListNode *next) : val(x), next(next) {} 45 | }; 46 | 47 | class Solution 48 | { 49 | public: 50 | Solution() { Sukuna; } 51 | void TEST() {} 52 | }; 53 | 54 | int main() 55 | { 56 | Solution sol; 57 | freopen("test/input.txt", "r", stdin); 58 | freopen("test/output.txt", "w", stdout); 59 | int tc(1); 60 | cin >> tc; 61 | while (tc--) 62 | cout << "Case #" << tc + 1 << edl, sol.TEST(); 63 | cout << edl << "DONE" << edl; 64 | return (0); 65 | } -------------------------------------------------------------------------------- /source/Circular_Queue.cpp: -------------------------------------------------------------------------------- 1 | #ifndef CIRCULAR_QUEUE_CPP 2 | #define CIRCULAR_QUEUE_CPP 3 | 4 | #include "../header/Circular_Queue.h" 5 | 6 | template 7 | Circular_Queue::Circular_Queue(int sz) : size(sz) 8 | { 9 | arr = new type[size]; 10 | } 11 | 12 | template 13 | Circular_Queue::~Circular_Queue() 14 | { 15 | delete[] arr; 16 | arr = nullptr; 17 | size = added_elements = 0; 18 | } 19 | 20 | template 21 | bool Circular_Queue::is_full() 22 | { 23 | return added_elements == size; 24 | } 25 | 26 | template 27 | bool Circular_Queue::is_empty() 28 | { 29 | return added_elements == 0; 30 | } 31 | 32 | template 33 | const int Circular_Queue::get_size() 34 | { 35 | return size; 36 | } 37 | 38 | template 39 | int Circular_Queue::next(int pos) 40 | { 41 | return (pos + 1) % size; 42 | } 43 | 44 | template 45 | void Circular_Queue::enqueue(type val) 46 | { 47 | assert(!is_full()); 48 | arr[rear] = val; 49 | rear = next(rear); 50 | ++added_elements; 51 | } 52 | 53 | template 54 | type Circular_Queue::dequeue() 55 | { 56 | assert(!is_empty()); 57 | type value(arr[front]); 58 | front = next(front); 59 | --added_elements; 60 | return value; 61 | } 62 | 63 | template 64 | void Circular_Queue::print() 65 | { 66 | std::cout << "Front " << front << " - Rear " << rear << '\t'; 67 | if (is_full()) 68 | std::cout << "Full" << edl; 69 | else if (is_empty()) 70 | { 71 | std::cout << "Empty" << edl << edl; 72 | return; 73 | } 74 | std::cout << edl; 75 | for (int cur(front), step(0); step < added_elements; ++step, cur = next(cur)) 76 | std::cout << arr[cur] << ' '; 77 | std::cout << edl << edl; 78 | } 79 | #endif -------------------------------------------------------------------------------- /header/Vector.h: -------------------------------------------------------------------------------- 1 | #ifndef VECTOR_H 2 | #define VECTOR_H 3 | 4 | #include 5 | #include 6 | 7 | #define edl '\n' 8 | 9 | template 10 | class Vector 11 | { 12 | type *arr{nullptr}; 13 | int size{}; 14 | int capacity{}; 15 | 16 | void expand_capacity(); 17 | 18 | public: 19 | Vector(int sz = 0); 20 | ~Vector(); 21 | type &operator[](const int idx); 22 | // Return the number of items stored in the vector 23 | const int get_size(); 24 | // Return the value stored at the given index 25 | const type get_value(int idx); 26 | // Return the value stored at the front of the vector 27 | const type get_front(); 28 | // Return the value stored at the back of the vector 29 | const type get_back(); 30 | // Check if the vector is empty or not 31 | const bool is_empty(); 32 | // Append the given value to the end of the vector 33 | void push_back(type val); 34 | // Delete the last item in the vector 35 | void pop_back(); 36 | // Delete item at the given index 37 | type pop(int idx); 38 | // Remove all instances of value from the vector 39 | void remove(type val); 40 | // Set the given value at the given index 41 | void set_value(int idx, type val); 42 | // Print all the elements in the vector 43 | const void print(); 44 | // search for value and returns first index with that value, -1 if not found 45 | const int find(type val); 46 | // Insert the given value at the given index 47 | void insert(int idx, type val); 48 | // rotate the last element to the front of the vector 49 | void right_rotate(); 50 | // rotate the first element to the back of the vector 51 | void left_rotate(); 52 | // rotate the last element to the front of the vector N times 53 | void right_rotate(int times); 54 | // search for value and it's index, but each time you find the value, you 55 | // shift it one step to the left 56 | int find_transposition(type val); 57 | }; 58 | #endif -------------------------------------------------------------------------------- /header/AVL_Tree.h: -------------------------------------------------------------------------------- 1 | #ifndef AVL_TREE_H 2 | #define AVL_TREE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define edl '\n' 9 | 10 | template 11 | struct AVL_Node 12 | { 13 | T data{}; 14 | int height{}; 15 | AVL_Node *left{}; 16 | AVL_Node *right{}; 17 | AVL_Node(T data) : data(data) {} 18 | int ch_height(AVL_Node *node) 19 | { 20 | if (!node) 21 | return -1; 22 | return node->height; 23 | } 24 | int update_height() 25 | { 26 | return height = 1 + std::max(ch_height(left), ch_height(right)); 27 | } 28 | int balance_factor() 29 | { 30 | return ch_height(left) - ch_height(right); 31 | } 32 | }; 33 | 34 | template 35 | class AVL_Tree 36 | { 37 | AVL_Node *root{}; 38 | bool search_node(type val, AVL_Node *node); 39 | AVL_Node *right_rotation(AVL_Node *Q); 40 | AVL_Node *left_rotation(AVL_Node *P); 41 | AVL_Node *balance(AVL_Node *node); 42 | AVL_Node *insert_node(type val, AVL_Node *node); 43 | bool is_bst(AVL_Node *node); 44 | void verify(); 45 | void print_in_order_node(AVL_Node *node); 46 | AVL_Node *min_node(AVL_Node *cur); 47 | AVL_Node *max_node(AVL_Node *cur); 48 | AVL_Node *delete_node(type val, AVL_Node *node); 49 | AVL_Node *lower_bound_node(type val, AVL_Node *node); 50 | AVL_Node *upper_bound_node(type val, AVL_Node *node); 51 | bool prefix_exist_node(std::string prefix, AVL_Node *node); 52 | void clear(AVL_Node *node); 53 | 54 | public: 55 | AVL_Tree(); 56 | ~AVL_Tree(); 57 | void insert_value(type val); 58 | bool search(type val); 59 | void print_in_order(); 60 | type min_value(); 61 | type max_value(); 62 | void delete_value(type val); 63 | void level_order_traversal(); 64 | std::pair lower_bound(type val); 65 | std::pair upper_bound(type val); 66 | int avl_nodes_recursive(int height); 67 | int avl_nodes_iterative(int height); 68 | bool prefix_exist(std::string prefix); 69 | }; 70 | #endif -------------------------------------------------------------------------------- /header/Binary_Search_Tree.h: -------------------------------------------------------------------------------- 1 | #ifndef BINARY_SEARCH_TREE_H 2 | #define BINARY_SEARCH_TREE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define edl '\n' 12 | 13 | template 14 | class Binary_Search_Tree 15 | { 16 | type data{}; 17 | Binary_Search_Tree *left{}; 18 | Binary_Search_Tree *right{}; 19 | void clear(); 20 | bool find_chain(std::vector *> &ancestors, type val); 21 | Binary_Search_Tree *get_next(std::vector *> &ancestors); 22 | bool next_between(std::deque &preorder, type min, type max); 23 | std::pair *, std::pair> range(Binary_Search_Tree *node, type mn, type mx); 24 | void special_delete(Binary_Search_Tree *child); 25 | Binary_Search_Tree *delete_node_s(type target, Binary_Search_Tree *node); 26 | Binary_Search_Tree *delete_node_p(type target, Binary_Search_Tree *node); 27 | Binary_Search_Tree *min_node(); 28 | Binary_Search_Tree *max_node(); 29 | 30 | public: 31 | // Binary_Search_Tree(type data); 32 | Binary_Search_Tree(std::deque &preorder, type min = INT_MIN, type max = INT_MAX); 33 | Binary_Search_Tree(std::deque level_order); 34 | Binary_Search_Tree(type d, Binary_Search_Tree *l = nullptr, Binary_Search_Tree *r = nullptr); 35 | ~Binary_Search_Tree(); 36 | void get_in_order(std::vector &inorder_values); 37 | void get_pre_order(std::deque &preorder_queue); 38 | void print_in_order(); 39 | void insert(type val); 40 | bool search(type val); 41 | std::deque level_order_traversal(); 42 | type min_value(); 43 | type max_value(); 44 | bool search_iterative(type val); 45 | bool is_bst_0(type mn = INT_MIN, type mx = INT_MAX); 46 | bool is_bst_1(); 47 | Binary_Search_Tree *build_balanced_bst_tree(std::vector &values, int str = 0, int end = -1); 48 | type kth_smallest_0(int &k); 49 | type kth_smallest_1(int &k); 50 | type LCA(type x, type y); 51 | std::pair successor(type val); 52 | void delete_value_successor(type val); 53 | void delete_value_predecessor(type val); 54 | }; 55 | #endif -------------------------------------------------------------------------------- /tests/singly_linkedlist_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/Singly_LinkedList.cpp" 2 | 3 | Singly_LinkedList list; 4 | const void initializing() 5 | { 6 | for (int i(1); i < 11; ++i) 7 | list.insert_end(i); 8 | } 9 | 10 | const void test_get_length() 11 | { 12 | assert(list.get_length() == 10); 13 | } 14 | 15 | const void test_pop_front() 16 | { 17 | int popped1(list.pop_front()); 18 | assert(popped1 == 1); 19 | list.insert_front(-4); 20 | int popped2(list.pop_front()); 21 | assert(popped2 == -4); 22 | } 23 | 24 | const void test_pop_back() 25 | { 26 | int popped1(list.pop_back()); 27 | assert(popped1 == 10); 28 | list.insert_end(-4); 29 | int popped2(list.pop_back()); 30 | assert(popped2 == -4); 31 | } 32 | 33 | const void test_get_value() 34 | { 35 | assert(list.get_value(0) == 2); 36 | assert(list.get_value(1) == 3); 37 | assert(list.get_value(2) == 4); 38 | assert(list.get_value(3) == 5); 39 | assert(list.get_value(4) == 6); 40 | } 41 | 42 | const void test_reverse() 43 | { 44 | list.reverse(); 45 | assert(list.get_value(0) == 9); 46 | assert(list.get_value(1) == 8); 47 | assert(list.get_value(2) == 7); 48 | assert(list.get_value(3) == 6); 49 | assert(list.get_value(4) == 5); 50 | } 51 | 52 | const void test_min_and_middle_and_max_value() 53 | { 54 | assert(list.min_value() == 2); 55 | assert(list.max_value() == 9); 56 | assert(list.middle_value() == 5); 57 | list.pop_front(), list.pop_back(); 58 | assert(list.min_value() == 3); 59 | assert(list.max_value() == 8); 60 | assert(list.middle_value() == 5); 61 | } 62 | 63 | const void test_is_palindrome() 64 | { 65 | assert(list.is_palindrome() == false); 66 | list.~Singly_LinkedList(); 67 | list.insert_end(1); 68 | list.insert_end(2); 69 | list.insert_end(2); 70 | list.insert_end(1); 71 | assert(list.is_palindrome() == true); 72 | } 73 | 74 | int main() 75 | { 76 | freopen("../imports/test/output.txt", "w", stdout); 77 | initializing(); 78 | test_get_length(); 79 | test_pop_front(); 80 | test_pop_back(); 81 | test_get_value(); 82 | test_reverse(); 83 | test_min_and_middle_and_max_value(); 84 | test_is_palindrome(); 85 | std::cout << edl << "DONE" << edl; 86 | // you must see 'DONE' in output 87 | return (0); 88 | } -------------------------------------------------------------------------------- /header/Binary_Tree.h: -------------------------------------------------------------------------------- 1 | #ifndef BINARY_TREE_H 2 | #define BINARY_TREE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include // ostringstream 13 | #include 14 | 15 | #define edl '\n' 16 | 17 | template 18 | class Binary_Tree 19 | { 20 | type data{}; 21 | Binary_Tree *left{}; 22 | Binary_Tree *right{}; 23 | std::string to_str(type n); 24 | void clear(); 25 | 26 | public: 27 | Binary_Tree(type data); 28 | ~Binary_Tree(); 29 | void add(std::vector values, std::vector direction); 30 | void print_in_order(); 31 | void print_pre_order(); 32 | void print_post_order(); 33 | const void get_in_order(std::vector &inorder_values); 34 | type max_value(); 35 | int tree_height_0(); 36 | int tree_height_1(); 37 | int total_nodes(); 38 | int no_leaf_nodes(); 39 | bool is_exists(type value); 40 | bool is_perfect(int h = -1); 41 | bool is_perfect_fomula(); 42 | void print_inorder_iterative_0(); 43 | void print_inorder_iterative_1(); 44 | void traverse_left_boundry(); 45 | std::pair tree_diameter(); 46 | void level_order_traversal_0(); 47 | void level_order_traversal_1(); 48 | void level_order_traversal_sorted(); 49 | void print_level_nodes(int level); 50 | void level_order_traversal_recursive(); 51 | void level_order_traversal_spiral(); 52 | bool is_complete(); 53 | Binary_Tree(std::deque &preorder, std::deque &inorder, int inorder_start = 0, int inorder_end = -1); 54 | Binary_Tree(std::queue> &preorder_queue); 55 | void build_preorder(std::queue> &preorder_queue); 56 | 57 | void print_preorder_complete(); 58 | std::string parenthesize_0(bool left_first = true); 59 | std::string parenthesize_canonical(); 60 | bool is_mirror(Binary_Tree *first, Binary_Tree *second); 61 | bool is_symmetric(); 62 | bool is_flip_equiv_0(Binary_Tree *other); 63 | bool is_flip_equiv_1(Binary_Tree *first, Binary_Tree *second); 64 | 65 | std::string parenthesize_1(std::vector &all_repres); 66 | void print_duplicate_subtrees(); 67 | }; 68 | #endif -------------------------------------------------------------------------------- /source/Deque.cpp: -------------------------------------------------------------------------------- 1 | #ifndef BDEQUE_CPP 2 | #define DEQUE_CPP 3 | 4 | #include "../header/Deque.h" 5 | 6 | template 7 | Deque::Deque(int sz) : size(sz) 8 | { 9 | array = new type[size]; 10 | } 11 | 12 | template 13 | Deque::~Deque() 14 | { 15 | delete[] array; 16 | array = nullptr; 17 | size = added_elements = 0; 18 | } 19 | 20 | template 21 | int Deque::next(int pos) 22 | { 23 | return (pos + 1) % size; 24 | } 25 | 26 | template 27 | int Deque::prev(int pos) 28 | { 29 | return (pos - 1 + size) % size; 30 | } 31 | 32 | template 33 | const int Deque::get_size() 34 | { 35 | return added_elements; 36 | } 37 | 38 | template 39 | void Deque::enqueue_rear(type val) 40 | { 41 | assert(!is_full()); 42 | array[rear] = val; 43 | rear = next(rear); 44 | ++added_elements; 45 | } 46 | 47 | template 48 | void Deque::enqueue_front(type val) 49 | { 50 | assert(!is_full()); 51 | front = prev(front); 52 | array[front] = val; 53 | ++added_elements; 54 | } 55 | 56 | template 57 | type Deque::dequeue_front() 58 | { 59 | assert(!is_empty()); 60 | type value(array[front]); 61 | front = next(front); 62 | --added_elements; 63 | return value; 64 | } 65 | 66 | template 67 | type Deque::dequeue_rear() 68 | { 69 | assert(!is_empty()); 70 | rear = prev(rear); 71 | type value(array[rear]); 72 | --added_elements; 73 | return value; 74 | } 75 | 76 | template 77 | int Deque::is_empty() 78 | { 79 | return added_elements == 0; 80 | } 81 | 82 | template 83 | bool Deque::is_full() 84 | { 85 | return added_elements == size; 86 | } 87 | 88 | template 89 | void Deque::print() 90 | { 91 | std::cout << "Front " << front << " - rear " << rear << '\t'; 92 | if (is_full()) 93 | std::cout << "Full"; 94 | else if (is_empty()) 95 | { 96 | std::cout << "Empty" << edl << edl; 97 | return; 98 | } 99 | std::cout << edl; 100 | for (int cur(front), step(0); step < added_elements; ++step, cur = next(cur)) 101 | std::cout << array[cur] << ' '; 102 | std::cout << edl << edl; 103 | } 104 | #endif -------------------------------------------------------------------------------- /imports/include.h: -------------------------------------------------------------------------------- 1 | // #include "Elshorpagi.h" 2 | #include 3 | 4 | #ifdef DS_AVL_TREE_V2 5 | #include "../source/AVL_Tree_v2.cpp" 6 | #endif 7 | #ifdef DS_AVL_TREE 8 | #include "../source/AVL_Tree.cpp" 9 | #endif 10 | #ifdef DS_BINARY_SEARCH_TREE_V2 11 | #include "../source/Binary_Search_Tree_v2.cpp" 12 | #endif 13 | #ifdef DS_BINARY_SEARCH_TREE 14 | #include "../source/Binary_Search_Tree.cpp" 15 | #endif 16 | #ifdef DS_BINARY_TREE 17 | #include "../source/Binary_Tree.cpp" 18 | #endif 19 | #ifdef DS_CIRCULAR_QUEUE 20 | #include "../source/Circular_Queue.cpp" 21 | #endif 22 | #ifdef DS_DEQUE 23 | #include "../source/Deque.cpp" 24 | #endif 25 | #ifdef DS_DOUBLY_LINKEDLIST 26 | #include "../source/Doubly_Linkedlist.cpp" 27 | #endif 28 | #ifdef DS_TRIE_TREE 29 | #include "../source/Trie_Tree.cpp" 30 | #endif 31 | #ifdef DS_MAX_HEAP 32 | #include "../source/Max_Heap.cpp" 33 | #endif 34 | #ifdef DS_MIN_HEAP 35 | #include "../source/Min_Heap.cpp" 36 | #endif 37 | #ifdef DS_PRIORITY_QUEUE_AVLT_BASED 38 | #include "../source/Priority_Queue_AVLT_Based.cpp" 39 | #endif 40 | #ifdef DS_PRIORITY_QUEUE_HEAP_BASED 41 | #include "../source/Priority_Queue_Heap_Based.cpp" 42 | #endif 43 | #ifdef DS_QUEUE_LINKEDLIST_BASED 44 | #include "../source/Queue_Linkedlist_Based.cpp" 45 | #endif 46 | #ifdef DS_SINGLY_LINKEDLIST 47 | #include "../source/Singly_Linkedlist.cpp" 48 | #endif 49 | #ifdef DS_SPARSE_ARRAY 50 | #include "../source/Sparse_Array.cpp" 51 | #endif 52 | #ifdef DS_SPARSE_CUBE 53 | #include "../source/Sparse_Cube.cpp" 54 | #endif 55 | #ifdef DS_SPARSE_MATRIX 56 | #include "../source/Sparse_Matrix.cpp" 57 | #endif 58 | #ifdef DS_STACK_ARRAY_BASED 59 | #include "../source/Stack_Array_Based.cpp" 60 | #endif 61 | #ifdef DS_STACK_LINKIEDLIST_BASED 62 | #include "../source/Stack_Linkedlist_Based.cpp" 63 | #endif 64 | #ifdef DS_VECTOR 65 | #include "../source/Vector.cpp" 66 | #endif 67 | 68 | // some macros to test faster, and you can modify them 69 | #define _CRT_SECURE_NO_DEPRECATE 70 | #define __elshorpagi__ (std::ios_base::sync_with_stdio(false), std::cin.tie(NULL)) 71 | #define all(v) ((v).begin()), ((v).end()) 72 | #define sz(v) ((int)((v).size())) 73 | #define cl(v) ((v).clear()) 74 | #define edl '\n' 75 | #define fr(i, x, n) for (int i(x); i < n; ++i) 76 | #define fl(i, x, n) for (int i(x); i > n; --i) 77 | #define fc(it, v) for (auto &(it) : (v)) 78 | #define sq(x) (x) * (x) 79 | #define yes std::cout << "YES\n" 80 | #define no std::cout << "NO\n" -------------------------------------------------------------------------------- /tests/doubly_linkedlist_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/Doubly_LinkedList.cpp" 2 | 3 | Doubly_LinkedList list; 4 | const void initializing() 5 | { 6 | for (int i(1); i < 21; ++i) 7 | list.insert_end(i); 8 | } 9 | 10 | const void test_get_length() 11 | { 12 | assert(list.get_length() == 20); 13 | } 14 | 15 | const void test_pop_front() 16 | { 17 | int popped1(list.pop_front()); 18 | assert(popped1 == 1); 19 | list.insert_front(-4); 20 | int popped2(list.pop_front()); 21 | assert(popped2 == -4); 22 | } 23 | 24 | const void test_pop_back() 25 | { 26 | int popped1(list.pop_back()); 27 | assert(popped1 == 20); 28 | list.insert_end(-4); 29 | int popped2(list.pop_back()); 30 | assert(popped2 == -4); 31 | } 32 | 33 | const void test_get_value() 34 | { 35 | assert(list.get_value(0) == 2); 36 | assert(list.get_value(1) == 3); 37 | assert(list.get_value(2) == 4); 38 | assert(list.get_value(3) == 5); 39 | assert(list.get_value(4) == 6); 40 | } 41 | 42 | const void test_delete_all_nodes_with_key() 43 | { 44 | list.insert_front(-1); 45 | list.insert_front(-1); 46 | list.insert_end(-1); 47 | list.delete_all_nodes_with_key(-1); 48 | assert(list.get_value(0) == 2); 49 | assert(list.get_value(1) == 3); 50 | } 51 | 52 | const void test_reverse() 53 | { 54 | Doubly_LinkedList list1; 55 | for (int i(1); i < 6; ++i) 56 | list1.insert_end(i); 57 | list1.reverse(); 58 | assert(list1.get_value(0) == 5); 59 | assert(list1.get_value(1) == 4); 60 | assert(list1.get_value(2) == 3); 61 | assert(list1.get_value(3) == 2); 62 | assert(list1.get_value(4) == 1); 63 | } 64 | 65 | const void test_middle_value() 66 | { 67 | assert(list.middle_value_0() == 11); 68 | list.pop_back(), list.pop_back(); 69 | assert(list.middle_value_1() == 10); 70 | } 71 | 72 | const void test_is_palindrome() 73 | { 74 | assert(list.is_palindrome() == false); 75 | list.~Doubly_LinkedList(); 76 | list.insert_end(1); 77 | list.insert_end(2); 78 | list.insert_end(2); 79 | list.insert_end(1); 80 | assert(list.is_palindrome() == true); 81 | } 82 | 83 | int main() 84 | { 85 | freopen("../imports/test/output.txt", "w", stdout); 86 | initializing(); 87 | test_get_length(); 88 | test_pop_front(); 89 | test_pop_back(); 90 | test_get_value(); 91 | test_delete_all_nodes_with_key(); 92 | test_reverse(); 93 | test_middle_value(); 94 | test_is_palindrome(); 95 | std::cout << edl << "DONE" << edl; 96 | // you must see 'DONE' in output 97 | return (0); 98 | } -------------------------------------------------------------------------------- /tests/vector_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/Vector.cpp" 2 | 3 | Vector vec; 4 | const void initializing() 5 | { 6 | for (int i(0); i < 20; ++i) 7 | vec.push_back(i); 8 | } 9 | 10 | const void test_get_size() 11 | { 12 | assert(vec.get_size() == 20); 13 | int elements_added(5); 14 | for (int i(0); i < elements_added; ++i) 15 | vec.push_back(i); 16 | assert(vec.get_size() == 25); 17 | } 18 | 19 | const void test_is_empty() 20 | { 21 | assert(vec.is_empty() == false); 22 | } 23 | 24 | const void test_get_value() 25 | { 26 | assert(vec.get_value(10) == 10); 27 | assert(vec.get_value(15) == 15); 28 | assert(vec.get_value(2) == 2); 29 | } 30 | 31 | const void test_get_front() 32 | { 33 | assert(vec.get_front() == 0); 34 | } 35 | 36 | const void test_get_back() 37 | { 38 | assert(vec.get_back() == 4); 39 | } 40 | 41 | const void test_pop_back() 42 | { 43 | vec.pop_back(); 44 | assert(vec.get_back() == 3); 45 | vec.push_back(-5); 46 | assert(vec.get_size() == 25); 47 | 48 | vec.pop_back(), vec.pop_back(); 49 | assert(vec.get_back() == 2); 50 | assert(vec.get_size() == 23); 51 | } 52 | 53 | const void test_pop() 54 | { 55 | int popped(vec.pop(1)); 56 | assert(popped == 1); 57 | assert(vec.get_size() == 22); 58 | int popped2(vec.pop(4)); 59 | assert(popped2 == 5); 60 | assert(vec.get_size() == 21); 61 | } 62 | 63 | const void test_remove() 64 | { 65 | vec.push_back(-1), vec.push_back(-1), vec.push_back(-1); 66 | vec.remove(-1); 67 | assert(vec.get_size() == 21); 68 | assert(vec.get_value(1) == 2); 69 | assert(vec.get_value(5) == 7); 70 | } 71 | 72 | const void test_set_value() 73 | { 74 | vec.set_value(0, 4); 75 | assert(vec.get_value(0) == 4); 76 | assert(vec.get_value(1) == 2); 77 | assert(vec.get_value(4) == 6); 78 | vec.set_value(2, 8); 79 | assert(vec.get_value(2) == 8); 80 | } 81 | 82 | const void test_find() 83 | { 84 | assert(vec.find(5) == -1); 85 | assert(vec.find(4) == 0); 86 | assert(vec.find(7) == 5); 87 | assert(vec.find(-5) == -1); 88 | } 89 | 90 | const void test_insert() 91 | { 92 | vec.insert(0, -2); 93 | assert(vec.get_value(0) == -2); 94 | assert(vec.get_value(1) == 4); 95 | assert(vec.get_value(7) == 8); 96 | assert(vec.get_value(5) == 6); 97 | vec.insert(3, 8); 98 | assert(vec.get_value(3) == 8); 99 | assert(vec.get_value(5) == 4); 100 | } 101 | 102 | int main() 103 | { 104 | freopen("../imports/test/output.txt", "w", stdout); 105 | initializing(); 106 | test_get_size(); 107 | test_is_empty(); 108 | test_get_value(); 109 | test_get_front(); 110 | test_get_back(); 111 | test_pop_back(); 112 | test_pop(); 113 | test_remove(); 114 | test_set_value(); 115 | test_find(); 116 | test_insert(); 117 | std::cout << edl << "DONE" << edl; 118 | // you must see 'DONE' in output 119 | return (0); 120 | } 121 | -------------------------------------------------------------------------------- /header/Doubly_LinkedList.h: -------------------------------------------------------------------------------- 1 | #ifndef DOUBLY_LINKEDLIST_H 2 | #define DOUBLY_LINKEDLIST_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define edl '\n' 10 | 11 | template 12 | struct D_Node 13 | { 14 | T data{}; 15 | D_Node *next{}; 16 | D_Node *prev{}; 17 | D_Node(T data) : data(data) {} 18 | void set(D_Node *next, D_Node *prev) 19 | { 20 | this->next = next; 21 | this->prev = prev; 22 | } 23 | // ~D_Node() { std::cout << "Destroy value: " << data << " at address " << this << edl; } 24 | }; 25 | 26 | template 27 | class Doubly_LinkedList 28 | { 29 | D_Node *head{}; 30 | D_Node *tail{}; 31 | int length{}; 32 | 33 | void delete_node(D_Node *node); 34 | void link(D_Node *first, D_Node *second); 35 | void add_node_between_node_and_next(D_Node *node_before, type val); 36 | D_Node *delete_and_link(D_Node *cur); 37 | void delete_and_link_v2(D_Node *cur); 38 | 39 | public: 40 | Doubly_LinkedList(); 41 | ~Doubly_LinkedList(); 42 | Doubly_LinkedList(const Doubly_LinkedList &) = delete; 43 | Doubly_LinkedList &operator=(const Doubly_LinkedList &another) = delete; 44 | // Returns the length (number of nodes) of the doubly linked list. 45 | const int get_length(); 46 | // Returns the value at the given index. 47 | const type get_value(int idx); 48 | // Inserts a new node with the given value at the end of the doubly linked list. 49 | void insert_end(type val); 50 | // Inserts a new node with the given value at the beginning of the doubly linked list. 51 | void insert_front(type val); 52 | // Inserts a new node with the given value into the list while maintaining sorted order. 53 | void insert_sorted(type val); 54 | // Prints the values of all nodes in the doubly linked list 55 | void print(); 56 | // Prints the values of nodes in reverse order 57 | void print_reversed(); 58 | // Removes and returns the value of the node at the front of the doubly linked list. 59 | type pop_front(); 60 | // Removes and returns the value of the node at the end of the doubly linked list. 61 | type pop_back(); 62 | // Deletes the first occurrence of the node containing the specified value from the doubly linked list. 63 | void delete_node_with_key(type val); 64 | // Deletes all nodes with a specific value from the doubly linked list. 65 | void delete_all_nodes_with_key(type val); 66 | // Deletes nodes at even positions (0-based index) from the doubly linked list. 67 | void delete_even_positions(); 68 | // Deletes nodes at odd positions (0-based index) from the doubly linked list. 69 | void delete_odd_positions(); 70 | // Checks if the doubly linked list is a palindrome. 71 | bool is_palindrome(); 72 | // Returns the middle value of the doubly linked list. 73 | type middle_value_0(); 74 | type middle_value_1(); 75 | // Reverses the order of nodes in the doubly linked list. 76 | void reverse(); 77 | }; 78 | #endif -------------------------------------------------------------------------------- /source/Sparse_Array.cpp: -------------------------------------------------------------------------------- 1 | #ifndef SPARSE_ARRAY_CPP 2 | #define SPARSE_ARRAY_CPP 3 | 4 | #include "../header/Sparse_Array.h" 5 | 6 | template 7 | Sparse_Array::Sparse_Array(int cols) : cols(cols) 8 | { 9 | tail = head = new Col_Node(0, -1); 10 | ++length; 11 | } 12 | 13 | template 14 | Sparse_Array::~Sparse_Array() 15 | { 16 | while (head) 17 | { 18 | Col_Node *current(head->next); 19 | delete head; 20 | head = current; 21 | } 22 | head = tail = nullptr; 23 | } 24 | 25 | template 26 | void Sparse_Array::link(Col_Node *first, Col_Node *second) 27 | { 28 | if (first) 29 | first->next = second; 30 | if (second) 31 | second->prev = first; 32 | } 33 | 34 | template 35 | Col_Node *Sparse_Array::add_node_between_node_and_next(Col_Node *node_before, type data, int col) 36 | { 37 | Col_Node *middle(new Col_Node(data, col)); 38 | ++length; 39 | Col_Node *node_after(node_before->next); 40 | link(node_before, middle); 41 | if (!node_after) 42 | tail = middle; 43 | else 44 | link(middle, node_after); 45 | return middle; 46 | } 47 | 48 | template 49 | Col_Node *Sparse_Array::get_col(int col, bool is_create_if_missing) 50 | { 51 | Col_Node *prev_col(head); 52 | while (prev_col->next && prev_col->next->col < col) 53 | prev_col = prev_col->next; 54 | bool found(prev_col->next && (prev_col->next->col == col)); 55 | if (found) 56 | return prev_col->next; 57 | if (!is_create_if_missing) 58 | return nullptr; 59 | return add_node_between_node_and_next(prev_col, 0, col); 60 | } 61 | 62 | template 63 | void Sparse_Array::print_row() 64 | { 65 | Col_Node *cur(head->next); 66 | for (int c(0); c < cols; ++c) 67 | { 68 | if (cur && cur->col == c) 69 | { 70 | std::cout << cur->data << ' '; 71 | cur = cur->next; 72 | } 73 | else 74 | std::cout << "0 "; 75 | } 76 | std::cout << edl; 77 | } 78 | 79 | template 80 | void Sparse_Array::print_row_nonzero() 81 | { 82 | for (Col_Node *cur(head->next); cur; cur = cur->next) 83 | std::cout << cur->data << ' '; 84 | std::cout << edl; 85 | } 86 | 87 | template 88 | void Sparse_Array::set_value(type data, int col) 89 | { 90 | get_col(col, true)->data = data; 91 | } 92 | 93 | template 94 | type Sparse_Array::get_value(int col) 95 | { 96 | Col_Node *node(get_col(col, false)); 97 | if (!node) 98 | return 0; 99 | return node->data; 100 | } 101 | 102 | template 103 | void Sparse_Array::add(Sparse_Array &other) 104 | { 105 | assert(cols == other.cols); 106 | for (Col_Node *other_cur(other.head->next); other_cur; other_cur = other_cur->next) 107 | { 108 | Col_Node *this_col(get_col(other_cur->col, true)); 109 | this_col->data += other_cur->data; 110 | } 111 | } 112 | #endif -------------------------------------------------------------------------------- /source/Priority_Queue_Heap_Based.cpp: -------------------------------------------------------------------------------- 1 | #ifndef PRIORITY_QUEUE_HEAP_BASED_CPP 2 | #define PRIORITY_QUEUE_HEAP_BASED_CPP 3 | 4 | #include "../header/Priority_Queue_Heap_Based.h" 5 | 6 | template 7 | Priority_Queue_Heap_Based::Priority_Queue_Heap_Based() 8 | { 9 | key = new type[capacity]{}; 10 | value = new type[capacity]{}; 11 | } 12 | 13 | template 14 | Priority_Queue_Heap_Based::~Priority_Queue_Heap_Based() 15 | { 16 | delete[] key, delete[] value; 17 | key = value = nullptr; 18 | } 19 | 20 | template 21 | void Priority_Queue_Heap_Based::expand_capacity() 22 | { 23 | capacity <<= 1; 24 | type *tmp1(new type[capacity]{}); 25 | type *tmp2(new type[capacity]{}); 26 | for (int i(0); i < size; ++i) 27 | tmp1[i] = key[i], tmp2[i] = value[i]; 28 | std::swap(key, tmp1), std::swap(value, tmp2); 29 | delete[] tmp1, delete[] tmp2; 30 | } 31 | 32 | template 33 | int Priority_Queue_Heap_Based::left(int pos) 34 | { 35 | int p((pos << 1) + 1); 36 | return p >= size ? -1 : p; 37 | } 38 | 39 | template 40 | int Priority_Queue_Heap_Based::right(int pos) 41 | { 42 | int p((pos << 1) + 2); 43 | return p >= size ? -1 : p; 44 | } 45 | 46 | template 47 | int Priority_Queue_Heap_Based::parent(int pos) 48 | { 49 | return (!pos ? -1 : ((pos - 1) >> 1)); 50 | } 51 | 52 | template 53 | void Priority_Queue_Heap_Based::heapify_up(int child_pos) 54 | { 55 | int par_pos(parent(child_pos)); 56 | if (!child_pos || key[par_pos] > key[child_pos]) 57 | return; 58 | std::swap(key[child_pos], key[par_pos]); 59 | std::swap(value[child_pos], value[par_pos]); 60 | heapify_up(par_pos); 61 | } 62 | 63 | template 64 | void Priority_Queue_Heap_Based::heapify_down(int parent_pos) // O(logn) 65 | { 66 | int child_pos(left(parent_pos)), right_child(right(parent_pos)); 67 | 68 | if (child_pos == -1) 69 | return; 70 | 71 | if (right_child != -1 && key[right_child] > key[child_pos]) 72 | child_pos = right_child; 73 | 74 | if (key[parent_pos] < key[child_pos]) 75 | { 76 | std::swap(key[parent_pos], key[child_pos]); 77 | std::swap(value[parent_pos], value[child_pos]); 78 | heapify_down(child_pos); 79 | } 80 | } 81 | 82 | template 83 | const int Priority_Queue_Heap_Based::get_size() 84 | { 85 | return size; 86 | } 87 | 88 | template 89 | bool Priority_Queue_Heap_Based::is_empty() 90 | { 91 | return size == 0; 92 | } 93 | 94 | template 95 | void Priority_Queue_Heap_Based::enqueue(type val, int priority) 96 | { 97 | if (size == capacity) 98 | expand_capacity(); 99 | value[size] = val; 100 | key[size++] = priority; 101 | heapify_up(size - 1); 102 | } 103 | 104 | template 105 | type Priority_Queue_Heap_Based::dequeue() 106 | { 107 | assert(!is_empty()); 108 | type ret(value[0]); 109 | key[0] = key[--size]; 110 | value[0] = value[size]; 111 | heapify_down(0); 112 | return ret; 113 | } 114 | 115 | template 116 | type Priority_Queue_Heap_Based::top() 117 | { 118 | assert(!is_empty()); 119 | return value[0]; 120 | } 121 | #endif -------------------------------------------------------------------------------- /source/Max_Heap.cpp: -------------------------------------------------------------------------------- 1 | #ifndef MAX_HEAP_CPP 2 | #define MAX_HEAP_CPP 3 | 4 | #include "../header/Max_Heap.h" 5 | 6 | template 7 | Max_Heap::Max_Heap() 8 | { 9 | array = new type[capacity]{}; 10 | } 11 | 12 | template 13 | Max_Heap::Max_Heap(const std::vector &vec) 14 | { 15 | if ((int)vec.size() >= capacity) 16 | expand_capacity(); 17 | array = new type[capacity]{}; 18 | size = (int)vec.size(); 19 | for (int i(0); i < (int)vec.size(); ++i) 20 | array[i] = vec[i]; 21 | heapify(); 22 | } 23 | 24 | template 25 | void Max_Heap::expand_capacity() 26 | { 27 | capacity <<= 1; 28 | type *tmp(new type[capacity]{}); 29 | for (int i(0); i < size; ++i) 30 | tmp[i] = array[i]; 31 | std::swap(array, tmp); 32 | delete[] tmp; 33 | } 34 | 35 | template 36 | Max_Heap::~Max_Heap() 37 | { 38 | delete[] array; 39 | array = nullptr; 40 | } 41 | 42 | template 43 | int Max_Heap::left(int pos) 44 | { 45 | int p((pos << 1) + 1); 46 | return p >= size ? -1 : p; 47 | } 48 | 49 | template 50 | int Max_Heap::right(int pos) 51 | { 52 | int p((pos << 1) + 2); 53 | return p >= size ? -1 : p; 54 | } 55 | 56 | template 57 | int Max_Heap::parent(int pos) 58 | { 59 | return (!pos ? -1 : ((pos - 1) >> 1)); 60 | } 61 | 62 | template 63 | void Max_Heap::heapify_up(int child_pos) 64 | { 65 | int par_pos(parent(child_pos)); 66 | if (!child_pos || array[par_pos] > array[child_pos]) 67 | return; 68 | std::swap(array[child_pos], array[par_pos]); 69 | heapify_up(par_pos); 70 | } 71 | 72 | template 73 | void Max_Heap::heapify_down(int parent_pos) // O(logn) 74 | { 75 | int child_pos(left(parent_pos)), right_child(right(parent_pos)); 76 | 77 | if (child_pos == -1) 78 | return; 79 | 80 | if (right_child != -1 && array[right_child] > array[child_pos]) 81 | child_pos = right_child; 82 | 83 | if (array[parent_pos] < array[child_pos]) 84 | { 85 | std::swap(array[parent_pos], array[child_pos]); 86 | heapify_down(child_pos); 87 | } 88 | } 89 | 90 | template 91 | void Max_Heap::heapify() // O(n) 92 | { 93 | for (int i((size >> 1) - 1); i > -1; --i) 94 | heapify_down(i); 95 | } 96 | 97 | template 98 | void Max_Heap::push(type val) 99 | { 100 | if (size == capacity) 101 | expand_capacity(); 102 | array[size++] = val; 103 | heapify_up(size - 1); 104 | } 105 | 106 | template 107 | void Max_Heap::pop() 108 | { 109 | assert(!is_empty()); 110 | array[0] = array[--size]; 111 | heapify_down(0); 112 | } 113 | 114 | template 115 | type Max_Heap::top() 116 | { 117 | assert(!is_empty()); 118 | return array[0]; 119 | } 120 | 121 | template 122 | const int Max_Heap::get_size() 123 | { 124 | return size; 125 | } 126 | 127 | template 128 | bool Max_Heap::is_empty() 129 | { 130 | return size == 0; 131 | } 132 | 133 | template 134 | bool Max_Heap::search(type val) 135 | { 136 | for (int i(0); i < size; ++i) 137 | { 138 | if (array[i] == val) 139 | return true; 140 | } 141 | return false; 142 | } 143 | #endif -------------------------------------------------------------------------------- /source/Hash_Table/Hash_Table_Chaining_LinkedList.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define edl '\n' 5 | 6 | int hash_num(int value, int n = 65407) 7 | { 8 | long long m(n); 9 | return (value % m + m) % m; 10 | } 11 | 12 | int hash_string(std::string str, int n) 13 | { 14 | long long m(n), sum(0); 15 | for (int i(0); i < (int)str.size(); ++i) 16 | sum = (sum * 26 + str[i] - 'a') % m; 17 | return sum % m; 18 | } 19 | 20 | int hash_string_lower_upper_digits(std::string str, int n = 65407) 21 | { 22 | int base(2 * 26 + 10); // 26-lower, 26-upper and 10-digits 23 | long long m(n), sum(0); 24 | 25 | for (int i(0); i < (int)str.size(); ++i) 26 | { 27 | // lowers from [0-25], upper [26-51] and digits [52-61] 28 | int value(0); 29 | if (islower(str[i])) 30 | value = str[i] - 'a'; // [0, 25] 31 | else if (isupper(str[i])) 32 | value = 26 + str[i] - 'A'; // [26, 51] 33 | else if (isdigit(str[i])) 34 | value = 26 + 26 + str[i] - '0'; // [52, 61] 35 | else 36 | assert(false); // invalid input 37 | sum = sum * base + value; 38 | sum %= m; // reduce to minimize overflows 39 | } 40 | return sum; 41 | } 42 | 43 | struct Hash_Node 44 | { 45 | // can change 46 | const static int INTERNAL_LIMIT = 2147483647; 47 | std::string key; 48 | std::string data; 49 | Hash_Node(std::string k, std::string d) : key(k), data(d) {} 50 | 51 | int hash() 52 | { 53 | return hash_string_lower_upper_digits(key, INTERNAL_LIMIT); 54 | } 55 | void print() 56 | { 57 | std::cout << "(" << key << ", " << data << ") "; 58 | } 59 | }; 60 | 61 | class Hash_Table 62 | { 63 | private: 64 | struct LinkedHashEntry 65 | { 66 | Hash_Node item; 67 | LinkedHashEntry *next{}; 68 | LinkedHashEntry(Hash_Node item) : item(item) {} 69 | }; 70 | int table_size; 71 | LinkedHashEntry **table{}; 72 | 73 | public: 74 | Hash_Table(int sz) : table_size(sz) 75 | { 76 | table = new LinkedHashEntry *[table_size] {}; 77 | } 78 | ~Hash_Table() 79 | { 80 | for (int i(0); i < table_size; ++i) 81 | delete[] table[i]; 82 | delete[] table; 83 | } 84 | void put(Hash_Node phone) 85 | { 86 | int idx(phone.hash() % table_size); 87 | if (!table[idx]) // first item (head) 88 | table[idx] = new LinkedHashEntry(phone); 89 | else 90 | { 91 | int flag(0); 92 | LinkedHashEntry *cur(table[idx]); 93 | while (cur->next) 94 | { 95 | if (cur->item.key == phone.key) 96 | { 97 | cur->item = phone; 98 | return; 99 | } 100 | cur = cur->next; 101 | } 102 | if (cur->item.key == phone.key) 103 | cur->item = phone; 104 | else 105 | cur->next = new LinkedHashEntry(phone); 106 | } 107 | } 108 | void print_all() 109 | { 110 | for (int hash(0); hash < table_size; ++hash) 111 | { 112 | if (!table[hash]) 113 | continue; 114 | std::cout << "Hash " << hash << ": "; 115 | LinkedHashEntry *tmp(table[hash]); 116 | while (tmp) 117 | { 118 | tmp->item.print(); 119 | tmp = tmp->next; 120 | } 121 | std::cout << edl; 122 | } 123 | } 124 | }; -------------------------------------------------------------------------------- /source/Sparse_Matrix.cpp: -------------------------------------------------------------------------------- 1 | #ifndef SPARSE_MATRIX_CPP 2 | #define SPARSE_MATRIX_CPP 3 | 4 | #include "../header/Sparse_Matrix.h" 5 | 6 | template 7 | Sparse_Matrix::Sparse_Matrix(int rows, int cols) : rows(rows), cols(cols) 8 | { 9 | tail = head = new Row_Node(-1, cols); 10 | ++length; 11 | } 12 | 13 | template 14 | Sparse_Matrix::~Sparse_Matrix() 15 | { 16 | for (Row_Node *cur(head->next); cur; cur = cur->next) 17 | cur->list.~Sparse_Array(); 18 | head = nullptr, tail = nullptr; 19 | } 20 | 21 | template 22 | Row_Node *Sparse_Matrix::get_row(int row, bool flag) 23 | { 24 | Row_Node *prev_row(head); 25 | while (prev_row->next && prev_row->next->row < row) 26 | prev_row = prev_row->next; 27 | bool found(prev_row->next && (prev_row->next->row == row)); 28 | if (found) 29 | return prev_row->next; 30 | if (!flag) 31 | return nullptr; 32 | return add_node_between_node_and_next(prev_row, row); 33 | } 34 | 35 | template 36 | void Sparse_Matrix::link(Row_Node *first, Row_Node *second) 37 | { 38 | if (first) 39 | first->next = second; 40 | if (second) 41 | second->prev = first; 42 | } 43 | 44 | template 45 | Row_Node *Sparse_Matrix::add_node_between_node_and_next(Row_Node *node_before, int row) 46 | { 47 | Row_Node *middle(new Row_Node(row, cols)); 48 | ++length; 49 | Row_Node *node_after(node_before->next); 50 | link(node_before, middle); 51 | if (!node_after) 52 | tail = middle; 53 | else 54 | link(middle, node_after); 55 | return middle; 56 | } 57 | 58 | template 59 | void Sparse_Matrix::set_value(type data, int row, int col) 60 | { 61 | assert(-1 < row && row < rows); 62 | assert(-1 < col && col < cols); 63 | Row_Node *item(get_row(row, true)); 64 | item->list.set_value(data, col); 65 | } 66 | 67 | template 68 | type Sparse_Matrix::get_value(int row, int col) 69 | { 70 | assert(-1 < row && row < rows); 71 | assert(-1 < col && col < cols); 72 | Row_Node *item(get_row(row, false)); 73 | if (!item) 74 | return 0; 75 | return item->list.get_col(col); 76 | } 77 | 78 | template 79 | void Sparse_Matrix::add(Sparse_Matrix &other) 80 | { 81 | assert(rows == other.rows && cols == other.cols); 82 | for (Row_Node *other_cur(other.head->next); other_cur; other_cur = other_cur->next) 83 | { 84 | Row_Node *this_row(get_row(other_cur->row, true)); 85 | this_row->list.add(other_cur->list); 86 | } 87 | } 88 | 89 | template 90 | void Sparse_Matrix::print_matrix() 91 | { 92 | std::cout << edl << "Print Matrix: " << rows << " x " << cols << edl; 93 | Row_Node *cur(head->next); 94 | for (int i(0); i < rows; ++i) 95 | { 96 | if (cur && cur->row == i) 97 | { 98 | cur->list.print_row(); 99 | cur = cur->next; 100 | } 101 | else 102 | { 103 | for (int j(0); j < cols; ++j) 104 | std::cout << "0 "; 105 | std::cout << edl; 106 | } 107 | } 108 | } 109 | 110 | template 111 | void Sparse_Matrix::print_matrix_nonzero() 112 | { 113 | std::cout << edl << "Print Matrix: " << rows << " x " << cols << edl; 114 | for (Row_Node *cur(head->next); cur; cur = cur->next) 115 | cur->list.print_row_nonzero(); 116 | } 117 | #endif -------------------------------------------------------------------------------- /source/Trie_Tree.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TRIE_TREE_CPP 2 | #define TRIE_TREE_CPP 3 | 4 | #include "../header/Trie_Tree.h" 5 | 6 | Trie_Tree::Trie_Tree() {} 7 | 8 | Trie_Tree::~Trie_Tree() 9 | { 10 | for (auto &it : child) 11 | { 12 | delete it.second; 13 | it.second = nullptr; 14 | } 15 | } 16 | 17 | void Trie_Tree::insert_recursive(std::string str, int idx) 18 | { 19 | if (idx == sz(str)) 20 | is_leaf = 1; 21 | else 22 | { 23 | int cur(str[idx] - 'a'); 24 | if (!child[cur]) 25 | child[cur] = new Trie_Tree(); 26 | child[cur]->insert_recursive(str, idx + 1); 27 | } 28 | } 29 | 30 | void Trie_Tree::insert_iterative(std::string str) 31 | { 32 | Trie_Tree *cur(this); 33 | for (auto &it : str) 34 | { 35 | int idx(it - 'a'); 36 | if (!cur->child[idx]) 37 | cur->child[idx] = new Trie_Tree(); 38 | cur = cur->child[idx]; 39 | } 40 | cur->is_leaf = true; 41 | } 42 | 43 | bool Trie_Tree::word_exist_recursive(std::string str, int idx) 44 | { 45 | if (idx == sz(str)) 46 | return is_leaf; 47 | 48 | int cur(str[idx] - 'a'); 49 | if (!child[cur]) 50 | return false; 51 | 52 | return child[cur]->word_exist_recursive(str, idx + 1); 53 | } 54 | 55 | bool Trie_Tree::word_exist_iterative(std::string str) 56 | { 57 | Trie_Tree *cur(this); 58 | for (auto &it : str) 59 | { 60 | int idx(it - 'a'); 61 | if (!cur->child[idx]) 62 | return false; 63 | cur = cur->child[idx]; 64 | } 65 | return cur->is_leaf; 66 | } 67 | 68 | bool Trie_Tree::prefix_exist(std::string str, int idx) 69 | { 70 | if (idx == sz(str)) 71 | return true; 72 | 73 | int cur(str[idx] - 'a'); 74 | if (!child[cur]) 75 | return false; 76 | 77 | return child[cur]->prefix_exist(str, idx + 1); 78 | } 79 | 80 | std::string Trie_Tree::first_word_prefix(const std::string &str) 81 | { 82 | Trie_Tree *cur(this); 83 | int len(sz(str)); 84 | for (int i(0); i < len; ++i) 85 | { 86 | int ch(str[i] - 'a'); 87 | if (!cur->child[ch]) 88 | break; 89 | 90 | if (cur->child[ch]->is_leaf) 91 | return str.substr(0, i + 1); 92 | cur = cur->child[ch]; 93 | } 94 | return str; 95 | } 96 | 97 | void Trie_Tree::get_all_strings(std::vector &res, std::string cur_str) 98 | { 99 | if (is_leaf) 100 | res.emplace_back(cur_str); 101 | for (auto &it : child) 102 | { 103 | if (it.second) 104 | it.second->get_all_strings(res, cur_str + (char)(it.first + 'a')); 105 | } 106 | } 107 | 108 | void Trie_Tree::auto_complete_0(const std::string &str, std::vector &res) 109 | { 110 | std::vector tmp; 111 | get_all_strings(tmp); 112 | int len(sz(str)); 113 | for (auto &it : tmp) 114 | { 115 | std::string s(it.substr(0, len)); 116 | if (s == str) 117 | res.emplace_back(it); 118 | } 119 | } 120 | 121 | void Trie_Tree::auto_complete_1(const std::string &str, std::vector &res) 122 | { 123 | Trie_Tree *cur(this); 124 | int len(sz(str)); 125 | for (auto &it : str) 126 | { 127 | int idx(it - 'a'); 128 | if (!cur->child[idx]) 129 | return; 130 | cur = cur->child[idx]; 131 | } 132 | cur->get_all_strings(res, str); 133 | } 134 | 135 | bool Trie_Tree::word_exist_with_1_change(std::string str) 136 | { 137 | for (auto &it : str) 138 | { 139 | char cpy(it); 140 | for (char ch('a'); ch <= 'z'; ++ch) 141 | { 142 | if (ch == cpy) // must do a change 143 | continue; 144 | it = ch; 145 | if (word_exist_iterative(str)) 146 | return true; 147 | } 148 | it = cpy; 149 | } 150 | return false; 151 | } 152 | #endif -------------------------------------------------------------------------------- /source/Sparse_Cube.cpp: -------------------------------------------------------------------------------- 1 | #ifndef SPARSE_CUBE_CPP 2 | #define SPARSE_CUBE_CPP 3 | 4 | #include "../header/Sparse_Cube.h" 5 | 6 | template 7 | Sparse_Cube::Sparse_Cube(int row, int col, int height) : rows(row), cols(col), heights(height) 8 | { 9 | tail = head = new Height_Node(0, 0, -1); 10 | ++length; 11 | } 12 | 13 | template 14 | Sparse_Cube::~Sparse_Cube() 15 | { 16 | for (Height_Node *cur(head->next); cur; cur = cur->next) 17 | cur->matrix.~Sparse_Matrix(); 18 | head = tail = nullptr; 19 | } 20 | 21 | template 22 | Height_Node *Sparse_Cube::get_height(int height, bool flag) 23 | { 24 | Height_Node *prev_row(head); 25 | while (prev_row->next && prev_row->next->height < height) 26 | prev_row = prev_row->next; 27 | bool found(prev_row->next && (prev_row->next->height == height)); 28 | if (found) 29 | return prev_row->next; 30 | if (!flag) 31 | return nullptr; 32 | return add_node_between_node_and_next(prev_row, height); 33 | } 34 | 35 | template 36 | void Sparse_Cube::link(Height_Node *first, Height_Node *second) 37 | { 38 | if (first) 39 | first->next = second; 40 | if (second) 41 | second->prev = first; 42 | } 43 | 44 | template 45 | Height_Node *Sparse_Cube::add_node_between_node_and_next(Height_Node *node_before, int height) 46 | { 47 | Height_Node *middle(new Height_Node(height, rows, cols)); 48 | ++length; 49 | Height_Node *node_after(node_before->next); 50 | link(node_before, middle); 51 | if (!node_after) 52 | tail = middle; 53 | else 54 | link(middle, node_after); 55 | return middle; 56 | } 57 | 58 | template 59 | void Sparse_Cube::set_value(type data, int row, int col, int height) 60 | { 61 | assert(-1 < row && row < rows); 62 | assert(-1 < col && col < cols); 63 | assert(-1 < height && height < heights); 64 | Height_Node *item(get_height(height, true)); 65 | item->matrix.set_value(data, row, col); 66 | } 67 | 68 | template 69 | type Sparse_Cube::get_value(int row, int col, int height) 70 | { 71 | assert(-1 < row && row < rows); 72 | assert(-1 < col && col < cols); 73 | assert(-1 < height && height < heights); 74 | Height_Node *item(get_height(height, false)); 75 | if (!item) 76 | return 0; 77 | return item->matrix.get_value(row, col); 78 | } 79 | 80 | template 81 | void Sparse_Cube::add(Sparse_Cube &other) 82 | { 83 | assert(heights == other.heights && rows == other.rows && cols == other.cols); 84 | for (Height_Node *other_cur(other.head->next); other_cur; other_cur = other_cur->next) 85 | { 86 | Height_Node *this_height(get_height(other_cur->height, true)); 87 | this_height->matrix.add(other_cur->matrix); 88 | } 89 | } 90 | 91 | template 92 | void Sparse_Cube::print_cube() 93 | { 94 | std::cout << edl << "Print Cube: " << rows << " x " << cols << " x " << heights << edl; 95 | Height_Node *cur(head->next); 96 | for (int i(0); i < heights; ++i) 97 | { 98 | if (cur && cur->height == i) 99 | { 100 | cur->matrix.print_matrix(); 101 | cur = cur->next; 102 | } 103 | else 104 | { 105 | for (int j(0); j < rows; ++j) 106 | { 107 | for (int k(0); k < cols; ++k) 108 | std::cout << "0 "; 109 | std::cout << edl; 110 | } 111 | } 112 | } 113 | } 114 | 115 | template 116 | void Sparse_Cube::print_cube_nonzero() 117 | { 118 | std::cout << edl << "Print Cube: " << rows << " x " << cols << " x " << heights << edl; 119 | for (Height_Node *cur(head->next); cur; cur = cur->next) 120 | cur->matrix.print_matrix_nonzero(); 121 | } 122 | #endif -------------------------------------------------------------------------------- /source/Vector.cpp: -------------------------------------------------------------------------------- 1 | #ifndef VECTOR_CPP 2 | #define VECTOR_CPP 3 | 4 | #include "../header/Vector.h" 5 | 6 | template 7 | Vector::Vector(int sz) : size(sz) 8 | { 9 | if (size < 0) 10 | size = 1; 11 | capacity = size + 10; 12 | arr = new type[capacity]{}; 13 | } 14 | 15 | template 16 | Vector::~Vector() 17 | { 18 | delete[] arr; 19 | arr = nullptr; 20 | } 21 | 22 | template 23 | void Vector::expand_capacity() 24 | { 25 | capacity <<= 1; 26 | type *tmp(new type[capacity]{}); 27 | for (int i(0); i < size; ++i) 28 | tmp[i] = arr[i]; 29 | std::swap(arr, tmp); 30 | delete[] tmp; 31 | } 32 | 33 | template 34 | type &Vector::operator[](const int idx) 35 | { 36 | assert(idx > -1 && idx < size); 37 | return arr[idx]; 38 | } 39 | 40 | template 41 | const int Vector::get_size() 42 | { 43 | return size; 44 | } 45 | 46 | template 47 | const type Vector::get_value(int idx) 48 | { 49 | assert(idx > -1 && idx < size); 50 | return arr[idx]; 51 | } 52 | 53 | template 54 | const type Vector::get_front() 55 | { 56 | return arr[0]; 57 | } 58 | 59 | template 60 | const type Vector::get_back() 61 | { 62 | return arr[size - 1]; 63 | } 64 | 65 | template 66 | const bool Vector::is_empty() 67 | { 68 | return size == 0; 69 | } 70 | 71 | template 72 | void Vector::set_value(int idx, type val) 73 | { 74 | assert(idx > -1 && idx < size); 75 | arr[idx] = val; 76 | } 77 | 78 | template 79 | const void Vector::print() 80 | { 81 | for (int i(0); i < size; ++i) 82 | std::cout << arr[i] << ' '; 83 | std::cout << edl; 84 | } 85 | 86 | template 87 | const int Vector::find(type val) 88 | { 89 | for (int i(0); i < size; ++i) 90 | if (arr[i] == val) 91 | return i; 92 | return -1; 93 | } 94 | 95 | template 96 | void Vector::push_back(type val) 97 | { 98 | if (size == capacity) 99 | expand_capacity(); 100 | arr[size++] = val; 101 | } 102 | 103 | template 104 | void Vector::pop_back() 105 | { 106 | assert(size > 0); 107 | --size; 108 | arr[size].~type(); 109 | } 110 | 111 | template 112 | type Vector::pop(int idx) 113 | { 114 | assert(idx > -1 && idx < size); 115 | type val(arr[idx]); 116 | for (int i(idx + 1); i < size; ++i) 117 | arr[i - 1] = arr[i]; 118 | --size; 119 | return val; 120 | } 121 | 122 | template 123 | void Vector::remove(type val) 124 | { 125 | for (int i(0); i < size; ++i) 126 | { 127 | if (arr[i] == val) 128 | pop(i), --i; // since items will shift, recheck this index 129 | } 130 | } 131 | 132 | template 133 | void Vector::insert(int idx, type val) 134 | { 135 | assert(idx > -1 && idx < size); 136 | if (size == capacity) 137 | expand_capacity(); 138 | for (int i(size - 1); i >= idx; --i) 139 | arr[i + 1] = arr[i]; 140 | arr[idx] = val; 141 | ++size; 142 | } 143 | 144 | template 145 | void Vector::right_rotate() 146 | { 147 | type last_element(arr[size - 1]); 148 | for (int i(size - 2); i > -1; --i) 149 | arr[i + 1] = arr[i]; 150 | arr[0] = last_element; 151 | } 152 | 153 | template 154 | void Vector::left_rotate() 155 | { 156 | type first_element(arr[0]); 157 | for (int i(1); i < size; ++i) 158 | arr[i - 1] = arr[i]; 159 | arr[size - 1] = first_element; 160 | } 161 | 162 | template 163 | void Vector::right_rotate(int times) 164 | { 165 | times %= size; 166 | while (times--) 167 | right_rotate(); 168 | } 169 | 170 | template 171 | int Vector::find_transposition(type val) 172 | { 173 | for (int i(0); i < size; ++i) 174 | if (arr[i] == val) 175 | { 176 | if (!i) 177 | return 0; 178 | std::swap(arr[i], arr[i - 1]); 179 | return i - 1; 180 | } 181 | return -1; 182 | } 183 | #endif -------------------------------------------------------------------------------- /source/Hash_Table/Hash_Table_Quadratic_Probing.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define edl '\n' 7 | 8 | int hash_string_lower_upper_digits(std::string str, int n = 65407) 9 | { 10 | int base(2 * 26 + 10); // 26-lower, 26-upper and 10-digits 11 | long long m(n), sum(0); 12 | 13 | for (int i(0); i < (int)str.size(); ++i) 14 | { 15 | // lowers from [0-25], upper [26-51] and digits [52-61] 16 | int value(0); 17 | if (islower(str[i])) 18 | value = str[i] - 'a'; // [0, 25] 19 | else if (isupper(str[i])) 20 | value = 26 + str[i] - 'A'; // [26, 51] 21 | else if (isdigit(str[i])) 22 | value = 26 + 26 + str[i] - '0'; // [52, 61] 23 | else 24 | assert(false); // invalid input 25 | sum = sum * base + value; 26 | sum %= m; // reduce to minimize overflows 27 | } 28 | return sum; 29 | } 30 | 31 | struct Hash_Node 32 | { 33 | const static int INTERNAL_LIMIT = 65407; 34 | std::string key; 35 | std::string data; 36 | 37 | int hash() 38 | { 39 | return hash_string_lower_upper_digits(key, INTERNAL_LIMIT); 40 | } 41 | 42 | Hash_Node(std::string key, std::string data) : key(key), data(data) {} 43 | void print() 44 | { 45 | std::cout << "(" << key << ", " << data << ") "; 46 | } 47 | }; 48 | 49 | class Hash_Table 50 | { 51 | private: 52 | int table_size; 53 | std::vector table; 54 | // to mark a cell as deleted 55 | Hash_Node *deleted{}; 56 | 57 | public: 58 | Hash_Table(int table_size) : table_size(table_size) 59 | { 60 | table.resize(table_size); 61 | deleted = new Hash_Node("", ""); 62 | } 63 | void put(Hash_Node phone) 64 | { 65 | int idx(phone.hash() % table_size), step(0), original_idx(idx); 66 | do 67 | { 68 | if (table[idx] == deleted || !table[idx]) 69 | { 70 | table[idx] = new Hash_Node(phone.key, phone.data); 71 | return; 72 | } 73 | else if (table[idx]->key == phone.key) 74 | { 75 | table[idx]->data = phone.data; // update 76 | return; 77 | } 78 | ++step; 79 | idx = (original_idx + step * step) % table_size; 80 | } while (idx != original_idx); // catch that we repeated 81 | 82 | // If we failed: rehash to increase size, then add this element 83 | rehashing(); 84 | put(phone); 85 | } 86 | 87 | bool remove(Hash_Node phone) 88 | { 89 | int idx(phone.hash() % table_size), step(0), original_idx(idx); 90 | do 91 | { 92 | if (!table[idx]) 93 | break; 94 | if (table[idx] != deleted && table[idx]->key == phone.key) 95 | { 96 | delete table[idx]; 97 | table[idx] = deleted; 98 | return true; 99 | } 100 | ++step; 101 | idx = (original_idx + step * step) % table_size; 102 | } while (idx != original_idx); // catch that we repeated 103 | return false; 104 | } 105 | 106 | bool get(Hash_Node &phone) 107 | { 108 | int idx(phone.hash() % table_size), step(0), original_idx(idx); 109 | do 110 | { 111 | if (!table[idx]) 112 | break; 113 | if (table[idx] != deleted && table[idx]->key == phone.key) 114 | { 115 | phone.data = table[idx]->data; 116 | return true; 117 | } 118 | ++step; 119 | idx = (original_idx + step * step) % table_size; 120 | } while (idx != original_idx); // catch that we repeated 121 | return false; 122 | } 123 | 124 | void rehashing() 125 | { 126 | std::cout << "Rehashing..." << edl; 127 | Hash_Table tmp(2 * table_size); 128 | for (int hash(0); hash < table_size; ++hash) 129 | { 130 | if (table[hash] == deleted || !table[hash]) 131 | continue; 132 | tmp.put(*table[hash]); 133 | } 134 | table_size *= 2; 135 | table = tmp.table; 136 | } 137 | 138 | void print_all() 139 | { 140 | for (int hash(0); hash < table_size; ++hash) 141 | { 142 | std::cout << hash << " "; 143 | if (table[hash] == deleted) 144 | std::cout << " X "; 145 | else if (!table[hash]) 146 | std::cout << " E "; 147 | else 148 | table[hash]->print(); 149 | std::cout << edl; 150 | } 151 | std::cout << "******************" << edl; 152 | } 153 | }; -------------------------------------------------------------------------------- /source/Hash_Table/Hash_Table_Chaining_Vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define edl '\n' 8 | 9 | int hash_num(int value, int n = 65407) 10 | { 11 | long long m(n); 12 | return (value % m + m) % m; 13 | } 14 | 15 | int hash_string(std::string str, int n) 16 | { 17 | long long m(n), sum(0); 18 | for (int i(0); i < (int)str.size(); ++i) 19 | sum = (sum * 26 + str[i] - 'a') % m; 20 | return sum % m; 21 | } 22 | 23 | int hash_string_lower_upper_digits(std::string str, int n = 65407) 24 | { 25 | int base(2 * 26 + 10); // 26-lower, 26-upper and 10-digits 26 | long long m(n), sum(0); 27 | 28 | for (int i(0); i < (int)str.size(); ++i) 29 | { 30 | // lowers from [0-25], upper [26-51] and digits [52-61] 31 | int value(0); 32 | if (islower(str[i])) 33 | value = str[i] - 'a'; // [0, 25] 34 | else if (isupper(str[i])) 35 | value = 26 + str[i] - 'A'; // [26, 51] 36 | else if (isdigit(str[i])) 37 | value = 26 + 26 + str[i] - '0'; // [52, 61] 38 | else 39 | assert(false); // invalid input 40 | sum = sum * base + value; 41 | sum %= m; // reduce to minimize overflows 42 | } 43 | return sum; 44 | } 45 | 46 | int hash_string_folding(std::string str, int n = 65407) 47 | { 48 | long long m(n), sum(0); 49 | for (int i(0); i < (int)str.size(); i += 4) 50 | { 51 | std::string block(str.substr(i, 4)); 52 | sum += hash_string_lower_upper_digits(block); 53 | sum %= m; 54 | } 55 | return sum; 56 | } 57 | 58 | struct Hash_Node 59 | { 60 | const static int INTERNAL_LIMIT = 65407; 61 | std::string key; 62 | std::string data; 63 | 64 | Hash_Node(std::string key, std::string data) : key(key), data(data) {} 65 | int hash() 66 | { 67 | return hash_string_lower_upper_digits(key, INTERNAL_LIMIT); 68 | } 69 | void print() 70 | { 71 | std::cout << "(" << key << ", " << data << ") "; 72 | } 73 | }; 74 | 75 | class Hash_Table 76 | { 77 | private: 78 | int table_size{}; 79 | int added_elements{}; 80 | double limit_load_factor{}; 81 | std::vector> table; 82 | // we can use others: e.g. list 83 | public: 84 | Hash_Table(int sz, double llf) : table_size(sz), limit_load_factor(llf) 85 | { 86 | table.resize(table_size); 87 | } 88 | 89 | bool get(Hash_Node &phone) 90 | { 91 | int idx(phone.hash() % table_size); 92 | for (int i(0); i < (int)table[idx].size(); ++i) 93 | { 94 | if (table[idx][i].key == phone.key) 95 | { 96 | phone = table[idx][i]; 97 | return true; 98 | } 99 | } 100 | return false; 101 | } 102 | void put(Hash_Node phone) 103 | { 104 | int idx(phone.hash() % table_size); 105 | for (int i(0); i < (int)table[idx].size(); ++i) 106 | { 107 | if (table[idx][i].key == phone.key) 108 | { 109 | table[idx][i] = phone; 110 | return; 111 | } 112 | } 113 | ++added_elements; 114 | rehashing(); 115 | table[idx].push_back(phone); 116 | } 117 | void rehashing() 118 | { 119 | double cur_load_factor((double)added_elements / table_size); 120 | // cout << cur_load_factor << edl; 121 | if (cur_load_factor < limit_load_factor) 122 | return; 123 | 124 | Hash_Table tmp(2 * table_size, limit_load_factor); 125 | for (int i(0); i < table_size; ++i) 126 | { 127 | if (!table[i].size()) 128 | continue; 129 | for (auto &it : table[i]) 130 | tmp.put(it); 131 | } 132 | table_size <<= 1; 133 | table = tmp.table; 134 | } 135 | bool remove(Hash_Node phone) 136 | { 137 | int idx(phone.hash() % table_size); 138 | for (int i(0); i < (int)table[idx].size(); ++i) 139 | { 140 | if (table[idx][i].key == phone.key) 141 | { 142 | std::swap(table[idx][i], table[idx].back()); 143 | table[idx].pop_back(); 144 | --added_elements; 145 | rehashing(); 146 | return true; 147 | } 148 | } 149 | return false; 150 | } 151 | void print_all() 152 | { 153 | for (int i(0); i < table_size; ++i) 154 | { 155 | if (!table[i].size()) 156 | continue; 157 | 158 | std::cout << "Hash " << i << ": "; 159 | for (int j(0); j < (int)table[i].size(); ++j) 160 | table[i][j].print(); 161 | std::cout << edl; 162 | } 163 | } 164 | }; -------------------------------------------------------------------------------- /source/Stack_Array_Based.cpp: -------------------------------------------------------------------------------- 1 | #ifndef STACK_ARRAY_BASED_CPP 2 | #define STACK_ARRAY_BASED_CPP 3 | 4 | #include "../header/Stack_Array_Based.h" 5 | 6 | template 7 | Stack_Array_Based::Stack_Array_Based(int sz) : size(sz), top(-1) 8 | { 9 | arr = new type[size]; 10 | } 11 | 12 | template 13 | Stack_Array_Based::~Stack_Array_Based() 14 | { 15 | delete[] arr; 16 | arr = nullptr; 17 | } 18 | 19 | template 20 | const int Stack_Array_Based::get_size() 21 | { 22 | return size; 23 | } 24 | 25 | template 26 | bool Stack_Array_Based::is_full() 27 | { 28 | return top == size - 1; 29 | } 30 | 31 | template 32 | bool Stack_Array_Based::is_empty() 33 | { 34 | return top == -1; 35 | } 36 | 37 | template 38 | void Stack_Array_Based::push(type val) 39 | { 40 | assert(!is_full()); 41 | arr[++top] = val; 42 | } 43 | 44 | template 45 | type Stack_Array_Based::pop() 46 | { 47 | assert(!is_empty()); 48 | return arr[top--]; 49 | } 50 | 51 | template 52 | type Stack_Array_Based::peek() 53 | { 54 | assert(!is_empty()); 55 | return arr[top]; 56 | } 57 | 58 | template 59 | void Stack_Array_Based::print() 60 | { 61 | for (int i(top); i > -1; --i) 62 | std::cout << arr[i] << ' '; 63 | std::cout << edl; 64 | } 65 | 66 | template 67 | std::string Stack_Array_Based::reverse_subwords(std::string line) 68 | { 69 | line += ' '; 70 | std::string ans(""); 71 | int len((int)line.size()); 72 | Stack_Array_Based st(len); 73 | for (int i(0); i < len; ++i) 74 | { 75 | if (line[i] == ' ') 76 | { 77 | while (!st.is_empty()) 78 | ans += st.pop(); 79 | ans += ' '; 80 | } 81 | else 82 | st.push(line[i]); 83 | } 84 | return ans; 85 | } 86 | 87 | template 88 | int Stack_Array_Based::reverse_num(int num) 89 | { 90 | if (!num) 91 | return 0; 92 | Stack_Array_Based st(51); 93 | while (num) 94 | st.push(num % 10), num /= 10; 95 | int ans(0), i(1); 96 | while (!st.is_empty()) 97 | ans = st.pop() * i + ans, i *= 10; 98 | return ans; 99 | } 100 | 101 | template 102 | char Stack_Array_Based::get_open_match(char ch) 103 | { 104 | if (ch == ')') 105 | return '('; 106 | if (ch == ']') 107 | return '['; 108 | return '{'; 109 | } 110 | 111 | template 112 | bool Stack_Array_Based::valid_parentheses(std::string str) 113 | { 114 | int len(str.size()); 115 | Stack_Array_Based st(len); 116 | for (int i(0); i < len; ++i) 117 | { 118 | if (str[i] == '(' || str[i] == '[' || str[i] == '{') 119 | st.push(str[i]); 120 | else if (st.is_empty() || st.pop() != st.get_open_match(str[i])) 121 | return false; 122 | } 123 | return st.is_empty(); 124 | } 125 | 126 | template 127 | std::string Stack_Array_Based::remove_all_adjacent_duplicates(std::string str) 128 | { 129 | int len(str.size()); 130 | Stack_Array_Based st(len); 131 | for (int i(0); i < len; ++i) 132 | { 133 | if (!st.is_empty() && st.peek() == str[i]) 134 | st.pop(); 135 | else 136 | st.push(str[i]); 137 | } 138 | str = ""; 139 | while (!st.is_empty()) 140 | str = st.pop() + str; 141 | return str; 142 | } 143 | 144 | template 145 | void Stack_Array_Based::asteroid_collision(std::vector &asteroids) 146 | { 147 | int len(asteroids.size()); 148 | Stack_Array_Based st(len); 149 | for (int i(0); i < len; ++i) 150 | { 151 | int flag(0); 152 | while (!st.is_empty() && asteroids[i] < 0 && st.peek() > -1) 153 | { 154 | if (st.peek() < -asteroids[i]) 155 | { 156 | st.pop(); 157 | continue; 158 | } 159 | else if (st.peek() == -asteroids[i]) 160 | st.pop(); 161 | flag = 1; 162 | break; 163 | } 164 | if (!flag) 165 | st.push(asteroids[i]); 166 | } 167 | for (int i(0); i <= top; ++i) 168 | std::cout << st.arr[i] << ' '; 169 | std::cout << edl; 170 | } 171 | 172 | template 173 | void Stack_Array_Based::insert_at_bottom(type val) 174 | { 175 | if (is_empty()) 176 | push(val); 177 | else 178 | { 179 | type cur(pop()); 180 | insert_at_bottom(val); 181 | push(cur); 182 | } 183 | } 184 | 185 | template 186 | void Stack_Array_Based::reverse() 187 | { 188 | if (is_empty()) 189 | return; 190 | type cur(pop()); 191 | reverse(); 192 | insert_at_bottom(cur); 193 | } 194 | #endif -------------------------------------------------------------------------------- /header/Singly_LinkedList.h: -------------------------------------------------------------------------------- 1 | #ifndef SINGLY_LINKEDLIST_H 2 | #define SINGLY_LINKEDLIST_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define edl '\n' 9 | 10 | template 11 | struct S_Node 12 | { 13 | T data{}; 14 | S_Node *next{}; 15 | S_Node(T data) : data(data) {} 16 | // ~Node() { std::cout << "Value Deleted: " << data << " at Address: " << this << edl; } 17 | }; 18 | 19 | template 20 | class Singly_LinkedList 21 | { 22 | S_Node *head{}; 23 | S_Node *tail{}; 24 | int length{}; 25 | 26 | S_Node *find(type val); 27 | void delete_node(S_Node *node); 28 | S_Node *get_previous(S_Node *node); 29 | S_Node *move_to_end(S_Node *cur, S_Node *prv); 30 | S_Node *move_and_delete(S_Node *node); 31 | S_Node *max_node(S_Node *h); 32 | S_Node *min_node(S_Node *h); 33 | S_Node *get_nth(int n); 34 | S_Node *get_nth_from_back(int idx); 35 | bool recursive_check(S_Node *cur_head); 36 | S_Node *frontptr{}; // used in palindrome function 37 | public: 38 | // Below 2 deletes prevent copy and assign to avoid this mistake 39 | Singly_LinkedList(const Singly_LinkedList &) = delete; 40 | Singly_LinkedList &operator=(const Singly_LinkedList &another) = delete; 41 | 42 | Singly_LinkedList(); 43 | ~Singly_LinkedList(); 44 | // Returns the value at the given index. 45 | const type get_value(int idx); 46 | // Returns the length (number of nodes) of the linked list. 47 | const int get_length(); 48 | // Inserts a new node with the given value at the end of the linked list. 49 | void insert_end(type val); 50 | // Inserts a new node with the given value at the beginning of the linked list. 51 | void insert_front(type val); 52 | // Inserts a new node with the given value after a specific node (`src`) in the linked list. 53 | void insert_after(S_Node *src, S_Node *target); 54 | // Inserts a new node with the given value into the list while maintaining sorted order. 55 | void insert_sorted(type val); 56 | // Prints the values of all nodes in the linked list 57 | void print(); 58 | // Recursively prints the values of nodes in the linked list 59 | void print_recr(S_Node *h); 60 | // Recursively prints the values of nodes in reverse order 61 | void print_recr_rever(S_Node *h); 62 | // Returns the index of the node containing the value, or -1 if not found. 63 | int search(type val); 64 | int search_improved(type val); 65 | int search_improved_v2(type val); 66 | // Returns `true` if the lists are the same, otherwise `false`. 67 | bool is_same(const Singly_LinkedList &list); 68 | // Removes and returns the value of the node at the front of the linked list. 69 | type pop_front(); 70 | // Removes and returns the value of the node at the end of the linked list. 71 | type pop_back(); 72 | // Deletes the node at the specified index `n` in the linked list. 73 | void delete_nth_node(int n); 74 | // Deletes the node that is the next ot the given node `node` in the linked list. 75 | void delete_next_node(S_Node *node); 76 | // Deletes the first occurrence of the node containing the specified value from the linked list. 77 | void delete_node_with_key(type val); 78 | // Deletes nodes at even positions (0-based index) from the linked list. 79 | void delete_even_positions(); 80 | // Deletes the last occurrence of the specified value from the linked list. 81 | void delete_last_occurrence_not_sorted(type key); 82 | // Removes duplicate values from the linked list, which is not necessarily sorted. 83 | void remove_duplicates_not_sorted(); 84 | // Swaps adjacent elements in the linked list, effectively repairing it. 85 | void swap_repairs(); 86 | // Reverses the order of nodes in the linked list. 87 | void reverse(); 88 | void swap_head_tail(); 89 | void left_rotate(int key); 90 | void move_key_occurance_to_end_not_sorted(type key); 91 | // Returns the maximum value present in the linked list. 92 | type max_value(); 93 | // Returns the minimum value present in the linked list. 94 | type min_value(); 95 | // Returns the middle value of the linked list. 96 | type middle_value(); 97 | // Rearranges nodes in such a way that odd-positioned nodes appear before even-positioned nodes. 98 | void arrange_odd_pos_even_pos(); 99 | // Inserts nodes from another linked list at alternate positions in the current linked list. 100 | void insert_alternate(Singly_LinkedList &other); 101 | // Merges two sorted linked lists iteratively into a single sorted linked list. 102 | S_Node *merge_two_lists_iterative(S_Node &head1, S_Node &head2); 103 | // Merges two sorted linked lists recursively into a single sorted linked list. 104 | S_Node *merge_two_lists_recursive(S_Node &head1, S_Node &head2); 105 | // Checks if the linked list is a palindrome. 106 | bool is_palindrome(); 107 | }; 108 | #endif -------------------------------------------------------------------------------- /tests/binary_tree_test.cpp: -------------------------------------------------------------------------------- 1 | #include "../source/Binary_Tree.cpp" 2 | 3 | const void test_in_order() 4 | { 5 | Binary_Tree tree(1); 6 | tree.add({2, 4, 7}, {'L', 'L', 'L'}), tree.add({2, 4, 8}, {'L', 'L', 'R'}); 7 | tree.add({2, 5, 9}, {'L', 'R', 'R'}), tree.add({3, 6, 10}, {'R', 'R', 'L'}); 8 | std::vector inorder_valuse; 9 | tree.get_in_order(inorder_valuse); 10 | assert(inorder_valuse[0] == 7), assert(inorder_valuse[1] == 4); 11 | assert(inorder_valuse[2] == 8), assert(inorder_valuse[3] == 2); 12 | assert(inorder_valuse[4] == 5), assert(inorder_valuse[5] == 9); 13 | } 14 | 15 | const void test_tree_max() 16 | { 17 | Binary_Tree tree(1); 18 | tree.add({2, 4, 7}, {'L', 'L', 'L'}), tree.add({2, 4, 8}, {'L', 'L', 'R'}); 19 | tree.add({2, 5, 9}, {'L', 'R', 'R'}), tree.add({3, 6, 10}, {'R', 'R', 'L'}); 20 | assert(tree.max_value() == 10); 21 | } 22 | 23 | const void test_is_exists() 24 | { 25 | Binary_Tree tree(1); 26 | tree.add({2, 4, 7}, {'L', 'L', 'L'}), tree.add({2, 4, 8}, {'L', 'L', 'R'}); 27 | tree.add({2, 5, 9}, {'L', 'R', 'R'}), tree.add({3, 6, 15}, {'R', 'R', 'L'}); 28 | 29 | assert(tree.total_nodes() == 10), assert(tree.no_leaf_nodes() == 4); 30 | assert(tree.is_exists(1) == true), assert(tree.is_exists(15) == true); 31 | assert(tree.is_exists(4) == true), assert(tree.is_exists(61) == false); 32 | } 33 | 34 | const void test_tree_height() 35 | { 36 | Binary_Tree tree(1); 37 | tree.add({2, 4, 7}, {'L', 'L', 'L'}), tree.add({2, 4, 8}, {'L', 'L', 'R'}); 38 | tree.add({2, 5, 9}, {'L', 'R', 'R'}), tree.add({3, 6, 10}, {'R', 'R', 'L'}); 39 | assert(tree.tree_height_0() == 3), assert(tree.tree_height_1() == 3); 40 | } 41 | 42 | const void test_is_perfect() 43 | { 44 | Binary_Tree tree(1); 45 | assert(tree.is_perfect() == true), assert(tree.is_perfect_fomula() == true); 46 | tree.add({2}, {'L'}); 47 | tree.add({3}, {'R'}); 48 | assert(tree.is_perfect() == true), assert(tree.is_perfect_fomula() == true); 49 | tree.add({2, 4, 7}, {'L', 'L', 'L'}); 50 | tree.add({2, 4, 8}, {'L', 'L', 'R'}); 51 | tree.add({2, 5, 9}, {'L', 'R', 'R'}); 52 | tree.add({3, 6, 15}, {'R', 'R', 'L'}); 53 | assert(tree.is_perfect() == 0), assert(tree.is_perfect_fomula() == false); 54 | tree.add({2, 5, 13}, {'L', 'R', 'L'}); 55 | tree.add({3, 6, 12}, {'R', 'R', 'R'}); 56 | tree.add({3, 14, 15}, {'R', 'L', 'L'}); 57 | tree.add({3, 14, 16}, {'R', 'L', 'R'}); 58 | assert(tree.is_perfect() == true), assert(tree.is_perfect_fomula() == true); 59 | } 60 | 61 | const void test_tree_diameter() 62 | { 63 | Binary_Tree tree(1); 64 | assert(tree.tree_diameter().first == 0); 65 | tree.add({2}, {'L'}); 66 | tree.add({3}, {'R'}); 67 | assert(tree.tree_diameter().first == 2); 68 | tree.add({2, 4, 7}, {'L', 'L', 'L'}), tree.add({2, 4, 8}, {'L', 'L', 'R'}); 69 | tree.add({2, 5, 9}, {'L', 'R', 'R'}), tree.add({3, 6, 15}, {'R', 'R', 'L'}); 70 | tree.add({2, 5, 13}, {'L', 'R', 'L'}), tree.add({3, 6, 12}, {'R', 'R', 'R'}); 71 | tree.add({3, 14, 15}, {'R', 'L', 'L'}), tree.add({3, 14, 16}, {'R', 'L', 'R'}); 72 | assert(tree.tree_diameter().first == 6); 73 | } 74 | 75 | const void test_is_complete() 76 | { 77 | Binary_Tree tree(1); 78 | assert(tree.is_complete() == true); 79 | tree.add({2, 4}, {'L', 'L'}); 80 | tree.add({2, 5}, {'L', 'R'}); 81 | tree.add({3}, {'R'}); 82 | assert(tree.is_complete() == true); 83 | tree.add({3, 7}, {'R', 'R'}); 84 | assert(tree.is_complete() == false); 85 | tree.add({2, 4, 8}, {'L', 'L', 'L'}); 86 | tree.add({2, 4, 9}, {'L', 'L', 'R'}); 87 | tree.add({2, 5, 10}, {'L', 'R', 'L'}); 88 | tree.add({2, 5, 11}, {'L', 'R', 'R'}); 89 | assert(tree.is_complete() == false); 90 | tree.add({3, 6, 12}, {'R', 'L', 'L'}); 91 | tree.add({3, 6, 13}, {'R', 'L', 'R'}); 92 | tree.add({3, 7, 14}, {'R', 'R', 'L'}); 93 | tree.add({3, 7, 15}, {'R', 'R', 'R'}); 94 | assert(tree.is_complete() == true); 95 | } 96 | 97 | const void test_is_symmetric() 98 | { 99 | Binary_Tree tree(1); 100 | assert(tree.is_symmetric() == true); 101 | tree.add({2}, {'L'}); 102 | tree.add({2}, {'R'}); 103 | assert(tree.is_symmetric() == true); 104 | tree.add({2, 3, 5}, {'L', 'L', 'L'}); 105 | tree.add({2, 3, 6}, {'L', 'L', 'R'}); 106 | tree.add({2, 4, 7}, {'L', 'R', 'L'}); 107 | tree.add({2, 4, 8}, {'L', 'R', 'R'}); 108 | assert(tree.is_symmetric() == false); 109 | tree.add({2, 4, 8}, {'R', 'L', 'L'}); 110 | tree.add({2, 4, 7}, {'R', 'L', 'R'}); 111 | tree.add({2, 3, 6}, {'R', 'R', 'L'}); 112 | assert(tree.is_symmetric() == false); 113 | tree.add({2, 3, 5}, {'R', 'R', 'R'}); 114 | assert(tree.is_symmetric() == true); 115 | } 116 | 117 | int main() 118 | { 119 | freopen("../imports/test/output.txt", "w", stdout); 120 | test_in_order(); 121 | test_tree_max(); 122 | test_is_exists(); 123 | test_tree_height(); 124 | test_is_perfect(); 125 | test_tree_diameter(); 126 | test_is_complete(); 127 | test_is_symmetric(); 128 | std::cout << edl << "DONE" << edl; 129 | // you must see 'DONE' in output 130 | return (0); 131 | } 132 | -------------------------------------------------------------------------------- /source/Priority_Queue_AVLT_Based.cpp: -------------------------------------------------------------------------------- 1 | #ifndef PRIORITY_QUEUE_AVLT_BASED_CPP 2 | #define PRIORITY_QUEUE_AVLT_BASED_CPP 3 | 4 | #include "../header/Priority_Queue_AVLT_Based.h" 5 | 6 | template 7 | Priority_Queue_AVLT_Based::Priority_Queue_AVLT_Based() {} 8 | 9 | template 10 | Priority_Queue_AVLT_Based::~Priority_Queue_AVLT_Based() 11 | { 12 | clear(root); 13 | } 14 | 15 | template 16 | void Priority_Queue_AVLT_Based::clear(PQ_Node *node) 17 | { 18 | if (node) 19 | { 20 | clear(node->left); 21 | clear(node->right); 22 | delete node; 23 | } 24 | } 25 | 26 | template 27 | bool Priority_Queue_AVLT_Based::search(type target, PQ_Node *node) 28 | { 29 | if (!node) 30 | return false; 31 | if (target == node->priority) 32 | return true; 33 | if (target < node->priority) 34 | return search(target, node->left); 35 | return search(target, node->right); 36 | } 37 | 38 | template 39 | PQ_Node *Priority_Queue_AVLT_Based::right_rotation(PQ_Node *Q) 40 | { 41 | PQ_Node *P(Q->left); 42 | Q->left = P->right; 43 | P->right = Q; 44 | Q->update_height(); 45 | P->update_height(); 46 | return P; 47 | } 48 | 49 | template 50 | PQ_Node *Priority_Queue_AVLT_Based::left_rotation(PQ_Node *P) 51 | { 52 | PQ_Node *Q(P->right); 53 | P->right = Q->left; 54 | Q->left = P; 55 | P->update_height(); 56 | Q->update_height(); 57 | return Q; 58 | } 59 | 60 | template 61 | PQ_Node *Priority_Queue_AVLT_Based::balance(PQ_Node *node) 62 | { 63 | if (node->balance_factor() == 2) 64 | { 65 | if (node->left->balance_factor() == -1) 66 | node->left = left_rotation(node->left); 67 | node = right_rotation(node); 68 | } 69 | else if (node->balance_factor() == -2) 70 | { 71 | if (node->right->balance_factor() == 1) 72 | node->right = right_rotation(node->right); 73 | node = left_rotation(node); 74 | } 75 | return node; 76 | } 77 | 78 | template 79 | PQ_Node *Priority_Queue_AVLT_Based::insert_node(type task_id, int priority, PQ_Node *node) 80 | { 81 | if (priority < node->priority) 82 | { 83 | if (!node->left) 84 | node->left = new PQ_Node(task_id, priority); 85 | else 86 | node->left = insert_node(task_id, priority, node->left); 87 | } 88 | else if (priority > node->priority) 89 | { 90 | if (!node->right) 91 | node->right = new PQ_Node(task_id, priority); 92 | else 93 | node->right = insert_node(task_id, priority, node->right); 94 | } 95 | else 96 | node->task_ids.push_back(task_id); 97 | node->update_height(); 98 | return balance(node); 99 | } 100 | 101 | template 102 | PQ_Node *Priority_Queue_AVLT_Based::min_node(PQ_Node *cur) 103 | { 104 | while (cur && cur->left) 105 | cur = cur->left; 106 | return cur; 107 | } 108 | 109 | template 110 | PQ_Node *Priority_Queue_AVLT_Based::max_node(PQ_Node *cur) 111 | { 112 | while (cur && cur->right) 113 | cur = cur->right; 114 | return cur; 115 | } 116 | 117 | template 118 | PQ_Node *Priority_Queue_AVLT_Based::delete_node(int priority, PQ_Node *node) 119 | { 120 | if (!node) 121 | return nullptr; 122 | if (priority < node->priority) 123 | node->left = delete_node(priority, node->left); 124 | else if (priority > node->priority) 125 | node->right = delete_node(priority, node->right); 126 | else 127 | { 128 | PQ_Node *tmp(node); 129 | if (!node->left && !node->right) // case 1: no child 130 | node = nullptr; 131 | else if (!node->right) // case 2: has left only 132 | node = node->left; // connect with child 133 | else if (!node->left) // case 2: has right only 134 | node = node->right; 135 | else // 2 children: Use successor 136 | { 137 | PQ_Node *mn(min_node(node->right)); 138 | node->priority = mn->priority; // copy & go delete 139 | node->right = delete_node(node->priority, node->right); 140 | tmp = nullptr; // Don't delete me. Successor will be deleted 141 | } 142 | if (tmp) 143 | delete tmp; 144 | } 145 | if (node) 146 | { 147 | node->update_height(); 148 | node = balance(node); 149 | } 150 | return node; 151 | } 152 | 153 | template 154 | void Priority_Queue_AVLT_Based::enqueue(type task_id, int task_priority) 155 | { 156 | if (!root) 157 | root = new PQ_Node(task_id, task_priority); 158 | else 159 | root = insert_node(task_id, task_priority, root); 160 | } 161 | 162 | template 163 | type Priority_Queue_AVLT_Based::dequeue() 164 | { 165 | assert(!is_empty()); 166 | PQ_Node *mx(max_node(root)); 167 | assert(mx->task_ids.size() > 0); 168 | type ret(mx->task_ids.back()); 169 | mx->task_ids.pop_back(); 170 | if (mx->task_ids.size() == 0) 171 | root = delete_node(mx->priority, root); 172 | 173 | return ret; 174 | } 175 | 176 | template 177 | bool Priority_Queue_AVLT_Based::is_empty() 178 | { 179 | return root == nullptr; 180 | } 181 | #endif -------------------------------------------------------------------------------- /source/Min_Heap.cpp: -------------------------------------------------------------------------------- 1 | #ifndef MIN_HEAP_CPP 2 | #define MIN_HEAP_CPP 3 | 4 | #include "../header/Min_Heap.h" 5 | 6 | template 7 | Min_Heap::Min_Heap() 8 | { 9 | array = new type[capacity]{}; 10 | } 11 | 12 | template 13 | Min_Heap::Min_Heap(const std::vector &vec) // Floyd Algorithm 14 | { 15 | if ((int)vec.size() >= capacity) 16 | expand_capacity(); 17 | array = new type[capacity]{}; 18 | size = (int)vec.size(); 19 | for (int i(0); i < (int)vec.size(); ++i) 20 | array[i] = vec[i]; 21 | heapify(); 22 | } 23 | 24 | template 25 | Min_Heap::~Min_Heap() 26 | { 27 | delete[] array; 28 | array = nullptr; 29 | } 30 | 31 | template 32 | void Min_Heap::expand_capacity() 33 | { 34 | capacity <<= 1; 35 | type *tmp(new type[capacity]{}); 36 | for (int i(0); i < size; ++i) 37 | tmp[i] = array[i]; 38 | std::swap(array, tmp); 39 | delete[] tmp; 40 | } 41 | 42 | template 43 | int Min_Heap::left(int pos) 44 | { 45 | // pos = parent's pos 46 | // p_left = (2 * pos) + 1; 47 | int p_left((pos << 1) + 1); 48 | return p_left >= size ? -1 : p_left; 49 | } 50 | 51 | template 52 | int Min_Heap::right(int pos) 53 | { 54 | // pos = parent's pos 55 | // p_right = (2 * pos) + 2; 56 | int p_right((pos << 1) + 2); 57 | return p_right >= size ? -1 : p_right; 58 | } 59 | 60 | template 61 | int Min_Heap::parent(int pos) 62 | { 63 | // pos = child's pos 64 | // p_parent = floor((pos - 1) / 2); 65 | // we don't need floor cus the integer; 66 | return (!pos ? -1 : ((pos - 1) >> 1)); 67 | } 68 | 69 | template 70 | void Min_Heap::heapify_up(int child_pos) 71 | { 72 | int par_pos(parent(child_pos)); 73 | if (!child_pos || array[par_pos] < array[child_pos]) 74 | return; 75 | std::swap(array[child_pos], array[par_pos]); 76 | heapify_up(par_pos); 77 | } 78 | 79 | template 80 | void Min_Heap::heapify_down(int parent_pos) // O(logn) 81 | { 82 | int child_pos(left(parent_pos)), right_child(right(parent_pos)); 83 | 84 | if (child_pos == -1) // no children 85 | return; 86 | 87 | if (right_child != -1 && array[right_child] < array[child_pos]) // is right smaller than left? 88 | child_pos = right_child; 89 | 90 | if (array[parent_pos] > array[child_pos]) 91 | { 92 | std::swap(array[parent_pos], array[child_pos]); 93 | heapify_down(child_pos); 94 | } 95 | } 96 | 97 | template 98 | void Min_Heap::heapify() // O(n) 99 | { 100 | // if we have N nodes, so clearly we have floor(N / 2) non-leaf nodes; 101 | // so the formula wil be (N / 2 - 1) cus it 's 0-based and integer so we don' t need floor; 102 | for (int i((size >> 1) - 1); i > -1; --i) 103 | heapify_down(i); 104 | } 105 | 106 | template 107 | bool Min_Heap::is_heap(int parent_pos) // O(n) 108 | { 109 | if (parent_pos == -1) 110 | return true; 111 | 112 | int left_child(left(parent_pos)), right_child(right(parent_pos)); 113 | 114 | if (left_child != -1 && array[parent_pos] > array[left_child]) 115 | return false; 116 | 117 | if (right_child != -1 && array[parent_pos] > array[right_child]) 118 | return false; 119 | 120 | return is_heap(left_child) && is_heap(right_child); 121 | } 122 | 123 | template 124 | void Min_Heap::push(type val) 125 | { 126 | if (size == capacity) 127 | expand_capacity(); 128 | array[size++] = val; 129 | heapify_up(size - 1); 130 | } 131 | 132 | template 133 | void Min_Heap::pop() 134 | { 135 | assert(!is_empty()); 136 | array[0] = array[--size]; 137 | heapify_down(0); 138 | } 139 | 140 | template 141 | type Min_Heap::top() 142 | { 143 | assert(!is_empty()); 144 | return array[0]; 145 | } 146 | 147 | template 148 | const int Min_Heap::get_size() 149 | { 150 | return size; 151 | } 152 | 153 | template 154 | bool Min_Heap::is_empty() 155 | { 156 | return size == 0; 157 | } 158 | 159 | template 160 | void Min_Heap::print_less_than(type val, int pos) 161 | { 162 | if (array[pos] >= val || pos == -1) 163 | return; 164 | std::cout << array[pos] << ' '; 165 | print_less_than(val, left(pos)); 166 | print_less_than(val, right(pos)); 167 | } 168 | 169 | template 170 | bool Min_Heap::is_heap_array(type *p, int n) 171 | { 172 | type *old_arr(array); 173 | int old_size(size); 174 | array = p, size = n; 175 | bool result(is_heap(0)); 176 | size = old_size, array = old_arr; 177 | return result; 178 | } 179 | 180 | template 181 | void Min_Heap::heap_sort(type *p, int n) // O(N* log(N)) time 182 | { 183 | if (n < 2) 184 | return; 185 | 186 | type *old_arr(array); 187 | int old_size(size); 188 | size = n, array = p; 189 | 190 | heapify(); // O(n) 191 | while (size--) // O(nlogn) 192 | { 193 | std::swap(array[0], array[size]); 194 | heapify_down(0); 195 | } 196 | 197 | for (int i(0); i < (n >> 1); ++i) // reverse the array 198 | std::swap(array[i], array[n - i - 1]); 199 | 200 | size = old_size, array = old_arr; 201 | } 202 | 203 | template 204 | bool Min_Heap::search(type val) 205 | { 206 | for (int i(0); i < size; ++i) 207 | { 208 | if (array[i] == val) 209 | return true; 210 | } 211 | return false; 212 | } 213 | #endif -------------------------------------------------------------------------------- /source/Binary_Search_Tree_v2.cpp: -------------------------------------------------------------------------------- 1 | #ifndef BINARY_SEARCH_TREE_V2_CPP 2 | #define BINARY_SEARCH_TREE_V2_CPP 3 | 4 | #include "../header/Binary_Search_Tree_v2.h" 5 | 6 | template 7 | Binary_Search_Tree_v2::Binary_Search_Tree_v2() {} 8 | 9 | template 10 | Binary_Search_Tree_v2::~Binary_Search_Tree_v2() 11 | { 12 | clear(root); 13 | } 14 | 15 | template 16 | void Binary_Search_Tree_v2::clear(BST_Node *node) 17 | { 18 | if (node) 19 | { 20 | clear(node->left); 21 | clear(node->right); 22 | delete node; 23 | } 24 | } 25 | 26 | template 27 | BST_Node *Binary_Search_Tree_v2::delete_node(type target, BST_Node *node) 28 | { 29 | if (!node) 30 | return nullptr; 31 | if (target < node->data) 32 | node->left = delete_node(target, node->left); 33 | else if (target > node->data) 34 | node->right = delete_node(target, node->right); 35 | else 36 | { 37 | BST_Node *tmp(node); 38 | if (!node->left && !node->right) // case 1: no child 39 | node = nullptr; 40 | else if (!node->right) // case 2: has left only 41 | node = node->left; // connect with child 42 | else if (!node->left) // case 2: has right only 43 | node = node->right; 44 | else // 2 children: Use successor 45 | { 46 | BST_Node *mn(min_node(node->right)); 47 | node->data = mn->data; // copy & go delete 48 | node->right = delete_node(node->data, node->right); 49 | tmp = nullptr; // Don't delete me. Successor will be deleted 50 | } 51 | if (tmp) 52 | delete tmp; 53 | } 54 | return node; 55 | } 56 | 57 | template 58 | BST_Node *Binary_Search_Tree_v2::min_node(BST_Node *node) 59 | { 60 | while (node && node->left) 61 | node = node->left; 62 | return node; 63 | } 64 | 65 | template 66 | BST_Node *Binary_Search_Tree_v2::max_node(BST_Node *node) 67 | { 68 | while (node && node->right) 69 | node = node->right; 70 | return node; 71 | } 72 | 73 | template 74 | void Binary_Search_Tree_v2::insert_node(type val, BST_Node *node) 75 | { 76 | if (val < node->data) 77 | { 78 | if (!node->left) 79 | node->left = new BST_Node(val); 80 | else 81 | insert_node(val, node->left); 82 | } 83 | else if (val > node->data) 84 | { 85 | if (!node->right) 86 | node->right = new BST_Node(val); 87 | else 88 | insert_node(val, node->right); 89 | } 90 | } 91 | 92 | template 93 | bool Binary_Search_Tree_v2::search_node(type val, BST_Node *node) 94 | { 95 | if (!node) 96 | return false; 97 | if (val == node->data) 98 | return true; 99 | if (val < node->data) 100 | return search_node(val, node->left); 101 | return search_node(val, node->right); 102 | } 103 | 104 | template 105 | void Binary_Search_Tree_v2::print_in_order_node(BST_Node *node) 106 | { 107 | if (!node) 108 | return; 109 | print_in_order_node(node->left); 110 | std::cout << node->data << ' '; 111 | print_in_order_node(node->right); 112 | } 113 | 114 | template 115 | bool Binary_Search_Tree_v2::is_bst(BST_Node *node) 116 | { 117 | bool left_bst(!node->left || (node->data > node->left->data) && is_bst(node->left)); 118 | if (!left_bst) 119 | return false; 120 | bool right_bst(!node->right || (node->data < node->right->data) && is_bst(node->right)); 121 | return right_bst; 122 | } 123 | 124 | template 125 | void Binary_Search_Tree_v2::insert_value(type val) 126 | { 127 | if (!root) 128 | root = new BST_Node(val); 129 | else 130 | insert_node(val, root); 131 | is_bst(root); 132 | } 133 | 134 | template 135 | bool Binary_Search_Tree_v2::search(type val) 136 | { 137 | return search_node(val, root); 138 | } 139 | 140 | template 141 | void Binary_Search_Tree_v2::print_in_order() 142 | { 143 | print_in_order_node(root); 144 | } 145 | 146 | template 147 | type Binary_Search_Tree_v2::min_value() 148 | { 149 | return min_node(root)->data; 150 | } 151 | 152 | template 153 | type Binary_Search_Tree_v2::max_value() 154 | { 155 | return max_node(root)->data; 156 | } 157 | 158 | template 159 | void Binary_Search_Tree_v2::delete_value(type val) 160 | { 161 | if (root) 162 | root = delete_node(val, root), is_bst(root); 163 | } 164 | 165 | template 166 | void Binary_Search_Tree_v2::level_order_traversal() 167 | { 168 | if (!root) 169 | return; 170 | std::cout << "********************" << edl; 171 | std::queue *> nodes_queue; 172 | nodes_queue.push(root); 173 | int level(0); 174 | while (!nodes_queue.empty()) 175 | { 176 | int sze(nodes_queue.size()); 177 | std::cout << "Level " << level << ": "; 178 | while (sze--) 179 | { 180 | BST_Node *cur(nodes_queue.front()); 181 | nodes_queue.pop(); 182 | std::cout << cur->data << ' '; 183 | if (cur->left) 184 | nodes_queue.push(cur->left); 185 | if (cur->right) 186 | nodes_queue.push(cur->right); 187 | } 188 | ++level; 189 | std::cout << edl; 190 | } 191 | } 192 | #endif -------------------------------------------------------------------------------- /source/Hash_Table/Hash_Table_Linear_Probing.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define edl '\n' 8 | 9 | /* Probing techniques: 10 | * Linear Probing : index = (init_hash + i) % table_size 11 | * Quadratic Probing : index = (init_hash + i*i) % table_size 12 | * Double Hashing (use 2 independent hash functions) : index = (init_hash1 + init_hash2 * i) % table_size 13 | */ 14 | 15 | int hash_string_lower_upper_digits(std::string str, int n = 65407) 16 | { 17 | int base(2 * 26 + 10); // 26-lower, 26-upper and 10-digits 18 | long long m(n), sum(0); 19 | 20 | for (int i(0); i < (int)str.size(); ++i) 21 | { 22 | // lowers from [0-25], upper [26-51] and digits [52-61] 23 | int value(0); 24 | if (islower(str[i])) 25 | value = str[i] - 'a'; // [0, 25] 26 | else if (isupper(str[i])) 27 | value = 26 + str[i] - 'A'; // [26, 51] 28 | else if (isdigit(str[i])) 29 | value = 26 + 26 + str[i] - '0'; // [52, 61] 30 | else 31 | assert(false); // invalid input 32 | sum = sum * base + value; 33 | sum %= m; // reduce to minimize overflows 34 | } 35 | return sum; 36 | } 37 | 38 | struct Hash_Node 39 | { 40 | const static int INTERNAL_LIMIT = 65407; 41 | std::string key; 42 | std::string data; 43 | 44 | Hash_Node(std::string key, std::string data) : key(key), data(data) {} 45 | int hash() 46 | { 47 | return hash_string_lower_upper_digits(key, INTERNAL_LIMIT); 48 | } 49 | void print() 50 | { 51 | std::cout << "(" << key << ", " << data << ") "; 52 | } 53 | }; 54 | 55 | class Hash_Table 56 | { 57 | private: 58 | int table_size; 59 | std::vector table; 60 | // to mark a cell as deleted 61 | Hash_Node *deleted{}; 62 | 63 | public: 64 | Hash_Table(int sz) : table_size(sz) 65 | { 66 | table.resize(table_size); 67 | deleted = new Hash_Node("", ""); 68 | } 69 | bool put(Hash_Node phone) 70 | { 71 | int idx(phone.hash() % table_size); 72 | // We max move table_size steps 73 | for (int step(0); step < table_size; ++step) 74 | { 75 | if (table[idx] == deleted || !table[idx]) // empty 76 | { 77 | table[idx] = new Hash_Node(phone.key, phone.data); 78 | return true; 79 | } 80 | else if (table[idx]->key == phone.key) 81 | { 82 | table[idx]->data = phone.data; // update 83 | return true; 84 | } 85 | idx = (idx + 1) % table_size; // move next 86 | } 87 | return false; // can't insert. Full table 88 | } 89 | 90 | bool remove(Hash_Node phone) 91 | { 92 | int idx(phone.hash() % table_size); 93 | 94 | for (int step(0); step < table_size; ++step) 95 | { 96 | if (!table[idx]) 97 | break; 98 | if (table[idx] != deleted && table[idx]->key == phone.key) 99 | { 100 | delete table[idx]; 101 | table[idx] = deleted; 102 | return true; 103 | } 104 | idx = (idx + 1) % table_size; // move next 105 | } 106 | return false; 107 | } 108 | 109 | bool get(Hash_Node &phone) 110 | { 111 | int idx(phone.hash() % table_size); 112 | 113 | for (int step(0); step < table_size; ++step) 114 | { 115 | if (!table[idx]) 116 | break; 117 | if (table[idx] != deleted && table[idx]->key == phone.key) 118 | { 119 | phone.data = table[idx]->data; 120 | return true; 121 | } 122 | idx = (idx + 1) % table_size; // move next 123 | } 124 | return false; 125 | } 126 | 127 | void print_all() 128 | { 129 | for (int hash(0); hash < table_size; ++hash) 130 | { 131 | std::cout << hash << " "; 132 | if (table[hash] == deleted) 133 | std::cout << " X "; 134 | else if (!table[hash]) 135 | std::cout << " E "; 136 | else 137 | table[hash]->print(); 138 | std::cout << edl; 139 | } 140 | std::cout << "******************" << edl; 141 | } 142 | }; 143 | 144 | int count_unique_substrings(const std::string &str, std::unordered_set &us) // O(L^2 * log(L)) 145 | { 146 | for (int i(0); i < (int)str.size(); ++i) 147 | { 148 | std::string ans(""); 149 | for (int j(i); j < (int)str.size(); ++j) 150 | ans = ans + str[j], us.insert(ans); // O(log(L) 151 | } 152 | return (int)us.size(); 153 | 154 | /* Another Solution Using Letter Tree */ 155 | // Note: Using a trie: we can efficiently solve it in O(L^2) 156 | // Don't create the string and add to trie 157 | // For every stating position: let the second loop keep inserting 158 | // In trie letter by letter and mark as leaf 159 | // Hence overall only 2 loops 160 | } 161 | 162 | int count_substrings_match(const std::string &str1, const std::string &str2) 163 | { 164 | std::unordered_set us1, us2; 165 | count_unique_substrings(str1, us1); 166 | count_unique_substrings(str2, us2); 167 | int cnt(0); 168 | for (auto &it : us1) 169 | cnt += us2.count(it); 170 | return cnt; 171 | } 172 | 173 | int count_anagram_substrings(const std::string &str) // O(L^3 * log(L)) 174 | { 175 | std::unordered_set us; 176 | for (int i(0); i < (int)str.size(); ++i) 177 | { 178 | std::string ans(""); 179 | for (int j(i); j < (int)str.size(); ++j) 180 | { 181 | ans = ans + str[j]; 182 | std::sort(ans.begin(), ans.end()); // O(L* log(L)) 183 | us.insert(ans); // O(log(L)) 184 | } 185 | } 186 | return (int)us.size(); 187 | // can be implemented in O(L^3) by representing each string as a freq of letters; 188 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Data Structures in `C++` 2 | 3 | ***Note :***
4 | `main.cpp in this repo use an include file that needs to be compiled manually so`
5 | `If you will use the main.cpp included in the repo so Use the command below to compile and run`
6 | `you must compile the code in terminal manually to work` 7 | 8 | ```python 9 | # to compile the file 10 | $ g++ main.cpp -o main -D FILENAME # FILENAME is the file (specific data sturcture from include.h file) you want to use 11 | # to run 12 | $ ./main.exe 13 | ``` 14 | 15 | ```python 16 | - All of these Data Structures were built using Templates 17 | - Functions in README are the basic functions only 18 | ``` 19 | 20 |

Hope you find this repository helpful, Have a nice time diving in 21 | 22 | 24 |

You can have a look to my Algorithms also 25 | 26 | 27 | 28 | 29 | ## Table of Contents: 30 | 1. [Vector](#1) 31 | 1. [Singly LinkedList](#2) 32 | 1. [Doubly LinkedList](#3) 33 | 1. [Sparse Array Using LinkedList](#4) 34 | 1. [Sparse Matrix Using LinkedList](#5) 35 | 1. [Sparse Cube Using LinkedList](#6) 36 | 1. [Stack Array Based](#7) 37 | 1. [Stack LinkedList Based](#8) 38 | 1. [Circular Queue](#9) 39 | 1. [Queue LinkedList Based](#10) 40 | 1. [Deque](#11) 41 | 1. [Binary Tree](#12) 42 | 1. [Binary Search Tree ( Binary Node )](#13) 43 | 1. [Binary Search Tree](#14) 44 | 1. [Min Binary Heap](#15) 45 | 1. [Max Binary Heap](#16) 46 | 1. [AVL Tree ( Binary Node )](#17) 47 | 1. [AVL Tree](#18) 48 | 1. [Priority Queue Heap Based](#19) 49 | 1. [Priority Queue AVL Tree Based](#20) 50 | 1. [Trie Tree ( Letter )](#21) 51 | 1. [Hash Table](#22) 52 | 53 | ## Contents: 54 | 55 | - > [**Vector**](header/Vector.h) 56 | - Push Back 57 | - Insert 58 | - Pop 59 | - Rotate (Left - Right) 60 | - Find 61 | - Find Transposition 62 | - > [**Singly LinkedList**](header/Singly_LinkedList.h) 63 | - Insert (End - Front - After - Alternative) 64 | - Search 65 | - Delete (First - Last) 66 | - > [**Doubly LinkedList**](header/Doubly_LinkedList.h) 67 | - Insert (End - Front - Sorted) 68 | - Delete (Front - End) 69 | - Is Palindrom 70 | - Middle Value 71 | - > [**Sparse Array Using LinkedList**](header/Sparse_Array.h) 72 | - Print Row 73 | - Print Row Non zero 74 | - > [**Sparse Matrix Using LinkedList**](header/Sparse_Matrix.h) 75 | - Print Matrix 76 | - Print Matrix Non zero 77 | - > [**Sparse Cube Using LinkedList**](header/Sparse_Cube.h) 78 | - Print Cube 79 | - Print Cube Non zero 80 | - > [**Stack Array Based**](header/Stack_Array_Based.h) 81 | - Is Full 82 | - Is Empty 83 | - Push 84 | - Pop 85 | - Peek 86 | - Reverse (Subwords - Num) 87 | - Remove Adjacent Duplicates 88 | - Reverse 89 | - Insert at Bottom 90 | - > [**Stack LinkedList Based**](header/Stack_LinkedList_Based.h) 91 | - Push 92 | - Pop 93 | - Peek 94 | - > [**Circular Queue**](header/Circular_Queue.h) 95 | - Is Full 96 | - Is Empty 97 | - Next 98 | - Enqueue 99 | - Dequeue 100 | - > [**Queue LinkedList Based**](header/Queue_LinkedList_Based.h) 101 | - Is Empty 102 | - Enqueue 103 | - Dequeue 104 | - > [**Deque**](header/Deque.h) 105 | - Next 106 | - Prev 107 | - Enqueue (Rear - Front) 108 | - Dequeue (Rear - Front) 109 | - Is Empty 110 | - Is Full 111 | - > [**Binary Tree**](header/Binary_Tree.h) 112 | - Print (Pre order - Post order - In order) 113 | - Tree max 114 | - Tree Height 115 | - Is exists 116 | - Is Perfect 117 | - Traverse 118 | - Level order Traversal 119 | - Is Mirror 120 | - Is symmetric 121 | - Is Flip 122 | - > [**Binary Search Tree ( Binary Node )**](header/Binary_Search_Tree_v2.h) 123 | - Insert 124 | - Search 125 | - Level Order Traversal 126 | - > [**Binary Search Tree**](header/Binary_Search_Tree.h) 127 | - Insert 128 | - Search 129 | - Delete 130 | - Get (In Order - Pre Order) 131 | - > [**Min Binary Heap**](header/Min_Heap.h) 132 | - Push 133 | - Pop 134 | - Is empty 135 | - Heap Sort 136 | - > [**Max Binary Heap**](header/Max_Heap.h) 137 | - Push 138 | - Pop 139 | - Top 140 | - Is Empty 141 | - > [**AVL Tree ( Binary Node )**](header/AVL_Tree.h) 142 | - Insert 143 | - Search 144 | - Delete 145 | - Level Order Traversal 146 | - Lower Bound 147 | - Upper Bound 148 | - Prefix Exist 149 | - > [**AVL Tree**](header/AVL_Tree_v2.h) 150 | - Insert 151 | - Delete 152 | - Level Order Traversal 153 | - > [**Priority Queue Heap Based**](header/Priority_Queue_Heap_Based.h) 154 | - Is Empty 155 | - Enqueue 156 | - Dequeue 157 | - > [**Priority Queue AVL Tree Based**](header/Priority_Queue_AVLT_Based.h) 158 | - Is Empty 159 | - Enqueue 160 | - Dequeue 161 | - > [**Trie Tree ( Letter )**](header/Trie_Tree.h) 162 | - Insert 163 | - Word Exist 164 | - Prefix Exist 165 | - > [**Hash Table**](https://github.com/Ali-Elshorpagi/Data_Structures/tree/main/source/Hash_Table) 166 | - Hash Table LinkedList Based ( Chaining Technique ) 167 | - Hash Table Vector Based ( Chaining Technique ) 168 | - Hash Table Vector Based ( Linear Probing Technique ) 169 | - Hash Table Vector Based ( Quadratic Probing Technique ) 170 | -------------------------------------------------------------------------------- /source/AVL_Tree_v2.cpp: -------------------------------------------------------------------------------- 1 | #ifndef AVL_TREE_V2_CPP 2 | #define AVL_TREE_V2_CPP 3 | 4 | #include "../header/AVL_Tree_v2.h" 5 | 6 | template 7 | AVL_Tree_v2::AVL_Tree_v2(type data) : data(data) {} 8 | 9 | template 10 | AVL_Tree_v2::~AVL_Tree_v2() 11 | { 12 | clear(); 13 | } 14 | 15 | template 16 | void AVL_Tree_v2::clear() 17 | { 18 | if (left) 19 | delete left, left = nullptr; 20 | if (right) 21 | delete right, left = right; 22 | } 23 | 24 | template 25 | int AVL_Tree_v2::ch_height(AVL_Tree_v2 *node) 26 | { 27 | if (!node) 28 | return -1; 29 | return node->height; 30 | } 31 | 32 | template 33 | int AVL_Tree_v2::update_height() 34 | { 35 | return height = 1 + std::max(ch_height(left), ch_height(right)); 36 | } 37 | 38 | template 39 | int AVL_Tree_v2::balance_factor() 40 | { 41 | return ch_height(left) - ch_height(right); 42 | } 43 | 44 | template 45 | AVL_Tree_v2 *AVL_Tree_v2::right_rotation(AVL_Tree_v2 *Q) 46 | { 47 | // std::cout << "right_rotation " << Q->data << edl; 48 | AVL_Tree_v2 *P(Q->left); 49 | Q->left = P->right; 50 | P->right = Q; 51 | Q->update_height(); 52 | P->update_height(); 53 | return P; 54 | } 55 | 56 | template 57 | AVL_Tree_v2 *AVL_Tree_v2::left_rotation(AVL_Tree_v2 *P) 58 | { 59 | // std::cout << "left_rotation " << P->data << edl; 60 | AVL_Tree_v2 *Q(P->right); 61 | P->right = Q->left; 62 | Q->left = P; 63 | P->update_height(); 64 | Q->update_height(); 65 | return Q; 66 | } 67 | 68 | template 69 | AVL_Tree_v2 *AVL_Tree_v2::balance(AVL_Tree_v2 *node) 70 | { 71 | if (node->balance_factor() == 2) // Left 72 | { 73 | if (node->left->balance_factor() == -1) // Left Right? 74 | node->left = left_rotation(node->left); // To Left Left 75 | node = right_rotation(node); // Balance Left Left 76 | } 77 | else if (node->balance_factor() == -2) 78 | { 79 | if (node->right->balance_factor() == 1) 80 | node->right = right_rotation(node->right); 81 | 82 | node = left_rotation(node); 83 | } 84 | return node; 85 | } 86 | 87 | template 88 | AVL_Tree_v2 *AVL_Tree_v2::min_node() 89 | { 90 | AVL_Tree_v2 *cur(this); 91 | while (cur && cur->left) 92 | cur = cur->left; 93 | return cur; 94 | } 95 | 96 | template 97 | AVL_Tree_v2 *AVL_Tree_v2::max_node() 98 | { 99 | AVL_Tree_v2 *cur(this); 100 | while (cur && cur->right) 101 | cur = cur->right; 102 | return cur; 103 | } 104 | 105 | template 106 | void AVL_Tree_v2::special_delete(AVL_Tree_v2 *child) 107 | { 108 | data = child->data; 109 | left = child->left; 110 | right = child->right; 111 | delete child; 112 | } 113 | 114 | template 115 | AVL_Tree_v2 *AVL_Tree_v2::delete_node(type val, AVL_Tree_v2 *node) 116 | { 117 | if (!node) 118 | return nullptr; 119 | if (val < node->data) 120 | node->left = delete_node(val, node->left); 121 | else if (val > node->data) 122 | node->right = delete_node(val, node->right); 123 | else 124 | { 125 | if (!node->left && !node->right) 126 | { 127 | delete node; 128 | node = nullptr; 129 | } 130 | else if (!node->right) // case 2: has left only 131 | node->special_delete(node->left); // connect with child 132 | else if (!node->left) // case 2: has right only 133 | node->special_delete(node->right); 134 | else 135 | { 136 | AVL_Tree_v2 *mn(node->right->min_node()); 137 | node->data = mn->data; 138 | node->right = delete_node(node->data, node->right); 139 | } 140 | } 141 | if (node) 142 | { 143 | node->update_height(); 144 | node = balance(node); 145 | } 146 | return node; 147 | } 148 | 149 | template 150 | void AVL_Tree_v2::re_root(AVL_Tree_v2 *node) 151 | { 152 | if (node == this) 153 | return; 154 | 155 | std::swap(this->data, node->data); 156 | std::swap(this->height, node->height); 157 | 158 | if (this == node->left) 159 | { 160 | std::swap(node->right, this->right); 161 | node->left = this->left; 162 | this->left = node; 163 | } 164 | else if (this == node->right) 165 | { 166 | std::swap(node->left, this->left); 167 | node->right = this->right; 168 | this->right = node; 169 | } 170 | } 171 | 172 | template 173 | void AVL_Tree_v2::level_order_traversal() 174 | { 175 | std::queue *> nodes_queue; 176 | nodes_queue.push(this); 177 | int level(0); 178 | while (!nodes_queue.empty()) 179 | { 180 | int sze(nodes_queue.size()); 181 | std::cout << "Level " << level << ": "; 182 | while (sze--) 183 | { 184 | AVL_Tree_v2 *cur(nodes_queue.front()); 185 | nodes_queue.pop(); 186 | std::cout << cur->data << " "; 187 | if (cur->left) 188 | nodes_queue.push(cur->left); 189 | if (cur->right) 190 | nodes_queue.push(cur->right); 191 | } 192 | ++level; 193 | std::cout << edl; 194 | } 195 | } 196 | 197 | template 198 | void AVL_Tree_v2::insert(type val) 199 | { 200 | if (val < data) 201 | { 202 | if (!left) 203 | left = new AVL_Tree_v2(val); 204 | else 205 | left->insert(val); 206 | } 207 | else if (val > data) 208 | { 209 | if (!right) 210 | right = new AVL_Tree_v2(val); 211 | else 212 | right->insert(val); 213 | } 214 | update_height(); 215 | re_root(balance(this)); 216 | } 217 | 218 | template 219 | void AVL_Tree_v2::delete_value(type val) 220 | { 221 | if (val == data && !left && !right) 222 | return; // can't remove root in this structure 223 | re_root(delete_node(val, this)); 224 | } 225 | 226 | template 227 | bool AVL_Tree_v2::is_bst() 228 | { 229 | bool left_bst(!left || data > left->data && left->is_bst()); 230 | 231 | if (!left_bst) 232 | return false; 233 | 234 | bool right_bst(!right || data < right->data && right->is_bst()); 235 | return right_bst; 236 | } 237 | 238 | template 239 | void AVL_Tree_v2::verify() 240 | { 241 | assert(abs(balance_factor()) < 2); 242 | assert(is_bst()); 243 | } 244 | 245 | template 246 | type AVL_Tree_v2::min_value() 247 | { 248 | return min_node()->data; 249 | } 250 | 251 | template 252 | type AVL_Tree_v2::max_value() 253 | { 254 | return max_node()->data; 255 | } 256 | 257 | template 258 | bool AVL_Tree_v2::search(type val) 259 | { 260 | AVL_Tree_v2 *cur(this); 261 | while (cur) 262 | { 263 | if (cur->data == val) 264 | return true; 265 | else if (val < cur->data) 266 | cur = cur->left; 267 | else 268 | cur = cur->right; 269 | } 270 | return false; 271 | } 272 | #endif -------------------------------------------------------------------------------- /source/Doubly_LinkedList.cpp: -------------------------------------------------------------------------------- 1 | #ifndef DOUBLY_LINKEDLIST_CPP 2 | #define DOUBLY_LINKEDLIST_CPP 3 | 4 | #include "../header/Doubly_LinkedList.h" 5 | 6 | template 7 | Doubly_LinkedList::Doubly_LinkedList() {} 8 | 9 | template 10 | Doubly_LinkedList::~Doubly_LinkedList() 11 | { 12 | while (head) 13 | { 14 | D_Node *current(head->next); 15 | delete head; 16 | head = current; 17 | } 18 | head = tail = nullptr; 19 | length = 0; 20 | } 21 | 22 | template 23 | void Doubly_LinkedList::link(D_Node *first, D_Node *second) 24 | { 25 | if (first) 26 | first->next = second; 27 | if (second) 28 | second->prev = first; 29 | } 30 | 31 | template 32 | void Doubly_LinkedList::add_node_between_node_and_next(D_Node *node_before, type val) 33 | { 34 | D_Node *middle(new D_Node(val)); 35 | ++length; 36 | D_Node *node_after(node_before->next); 37 | link(node_before, middle); 38 | if (!node_after) 39 | tail = middle; 40 | else 41 | link(middle, node_after); 42 | } 43 | 44 | template 45 | void Doubly_LinkedList::delete_node(D_Node *node) 46 | { 47 | --length; 48 | delete node; 49 | } 50 | 51 | template 52 | D_Node *Doubly_LinkedList::delete_and_link(D_Node *cur) 53 | { 54 | D_Node *ret(cur->prev); 55 | link(cur->prev, cur->next); 56 | delete_node(cur); 57 | return ret; 58 | } 59 | 60 | template 61 | void Doubly_LinkedList::delete_and_link_v2(D_Node *cur) 62 | { 63 | link(cur->prev, cur->next); 64 | delete_node(cur); 65 | } 66 | 67 | template 68 | const int Doubly_LinkedList::get_length() 69 | { 70 | return length; 71 | } 72 | 73 | template 74 | const type Doubly_LinkedList::get_value(int idx) 75 | { 76 | assert(idx >= 0 || idx < length); 77 | D_Node *cur(head); 78 | int cur_idx(0); 79 | while (cur_idx < idx) 80 | cur = cur->next, ++cur_idx; 81 | return cur->data; 82 | } 83 | 84 | template 85 | void Doubly_LinkedList::insert_end(type val) 86 | { 87 | D_Node *item(new D_Node(val)); 88 | ++length; 89 | if (!head) 90 | head = tail = item; 91 | else 92 | { 93 | link(tail, item); 94 | tail = item; 95 | } 96 | // tail->next = nullptr; // it depends on the compiler 97 | } 98 | 99 | template 100 | void Doubly_LinkedList::insert_front(type val) 101 | { 102 | D_Node *item(new D_Node(val)); 103 | ++length; 104 | if (!head) 105 | head = tail = item; 106 | else 107 | { 108 | link(item, head); 109 | head = item; 110 | } 111 | // head->prev = nullptr; // it depends on the compiler 112 | } 113 | 114 | template 115 | void Doubly_LinkedList::insert_sorted(type val) 116 | { 117 | if (!length || val <= head->data) 118 | insert_front(val); 119 | else if (tail->data <= val) 120 | insert_end(val); 121 | else 122 | { 123 | for (D_Node *cur(head); cur; cur = cur->next) 124 | { 125 | if (val <= cur->data) 126 | { 127 | add_node_between_node_and_next(cur->prev, val); 128 | break; 129 | } 130 | } 131 | } 132 | } 133 | 134 | template 135 | void Doubly_LinkedList::print() 136 | { 137 | for (D_Node *cur(head); cur; cur = cur->next) 138 | std::cout << cur->data << ' '; 139 | std::cout << edl; 140 | } 141 | 142 | template 143 | void Doubly_LinkedList::print_reversed() 144 | { 145 | for (D_Node *cur(tail); cur; cur = cur->prev) 146 | std::cout << cur->data << ' '; 147 | std::cout << edl; 148 | } 149 | 150 | template 151 | type Doubly_LinkedList::pop_front() 152 | { 153 | assert(head); 154 | type val(head->data); 155 | D_Node *cur(head->next); 156 | delete_node(head); 157 | head = cur; 158 | if (head) 159 | head->prev = nullptr; 160 | else if (!length) 161 | tail = nullptr; 162 | return val; 163 | } 164 | 165 | template 166 | type Doubly_LinkedList::pop_back() 167 | { 168 | assert(head); 169 | type val(tail->data); 170 | D_Node *cur(tail->prev); 171 | delete_node(tail); 172 | tail = cur; 173 | if (tail) 174 | tail->next = nullptr; 175 | else if (!length) 176 | head = nullptr; 177 | return val; 178 | } 179 | 180 | template 181 | void Doubly_LinkedList::delete_node_with_key(type val) 182 | { 183 | if (!length) 184 | return; 185 | if (head->data == val) 186 | pop_front(); 187 | else 188 | { 189 | for (D_Node *cur(head); cur; cur = cur->next) 190 | { 191 | if (cur->data == val) 192 | { 193 | cur = delete_and_link(cur); 194 | if (!cur->next) 195 | tail = cur; 196 | break; 197 | } 198 | } 199 | } 200 | } 201 | 202 | template 203 | void Doubly_LinkedList::delete_all_nodes_with_key(type val) 204 | { 205 | if (!length) 206 | return; 207 | insert_front(-val); 208 | for (D_Node *cur(head); cur;) 209 | { 210 | if (cur->data == val) 211 | { 212 | cur = delete_and_link(cur); 213 | if (!cur->next) 214 | tail = cur; 215 | } 216 | else 217 | cur = cur->next; 218 | } 219 | pop_front(); // delete the dummy value; 220 | } 221 | 222 | template 223 | void Doubly_LinkedList::delete_even_positions() 224 | { 225 | if (length < 2) 226 | return; 227 | for (D_Node *cur(head); cur && cur->next; cur = cur->next) 228 | { 229 | delete_and_link_v2(cur->next); 230 | if (!cur->next) 231 | tail = cur; 232 | } 233 | } 234 | 235 | template 236 | void Doubly_LinkedList::delete_odd_positions() 237 | { 238 | insert_front(-1); 239 | delete_even_positions(); 240 | pop_front(); // delete the dummy value; 241 | } 242 | 243 | template 244 | bool Doubly_LinkedList::is_palindrome() 245 | { 246 | if (length < 2) 247 | return true; 248 | D_Node *start(head), *end(tail); 249 | int len(length >> 1); 250 | while (len--) 251 | { 252 | if (start->data != end->data) 253 | return false; 254 | start = start->next, end = end->prev; 255 | } 256 | return true; 257 | } 258 | 259 | template 260 | type Doubly_LinkedList::middle_value_0() 261 | { 262 | assert(head); 263 | D_Node *start(head), *end(tail); 264 | while (start != end && start->next != end) 265 | start = start->next, end = end->prev; 266 | return end->data; 267 | } 268 | 269 | template 270 | type Doubly_LinkedList::middle_value_1() 271 | { 272 | // based on The Tortoise and the Hare Algorithm 273 | assert(head); 274 | D_Node *fast(head), *slow(head); 275 | while (fast && fast->next) 276 | { 277 | fast = fast->next->next; 278 | slow = slow->next; 279 | } 280 | return slow->data; 281 | } 282 | 283 | template 284 | void Doubly_LinkedList::reverse() 285 | { 286 | if (length < 2) 287 | return; 288 | D_Node *first(head), *second(head->next); 289 | while (second) 290 | { 291 | D_Node *first_temp(second), *second_temp(second->next); 292 | link(second, first); 293 | first = first_temp, second = second_temp; 294 | } 295 | std::swap(head, tail); 296 | head->prev = tail->next = nullptr; 297 | } 298 | #endif -------------------------------------------------------------------------------- /source/AVL_Tree.cpp: -------------------------------------------------------------------------------- 1 | #ifndef AVL_TREE_CPP 2 | #define AVL_TREE_CPP 3 | 4 | #include "../header/AVL_Tree.h" 5 | 6 | template 7 | AVL_Tree::AVL_Tree() {} 8 | 9 | template 10 | AVL_Tree::~AVL_Tree() 11 | { 12 | clear(root); 13 | } 14 | 15 | template 16 | void AVL_Tree::clear(AVL_Node *node) 17 | { 18 | if (node) 19 | { 20 | clear(node->left); 21 | clear(node->right); 22 | delete node; 23 | } 24 | } 25 | 26 | template 27 | bool AVL_Tree::search_node(type val, AVL_Node *node) 28 | { 29 | if (!node) 30 | return false; 31 | if (val == node->data) 32 | return true; 33 | if (val < node->data) 34 | return search_node(val, node->left); 35 | return search_node(val, node->right); 36 | } 37 | 38 | template 39 | AVL_Node *AVL_Tree::right_rotation(AVL_Node *Q) 40 | { 41 | // std::cout << "right_rotation " << Q->data << edl; 42 | AVL_Node *P(Q->left); 43 | Q->left = P->right; 44 | P->right = Q; 45 | Q->update_height(); 46 | P->update_height(); 47 | return P; 48 | } 49 | 50 | template 51 | AVL_Node *AVL_Tree::left_rotation(AVL_Node *P) 52 | { 53 | // std::cout << "left_rotation " << P->data << edl; 54 | AVL_Node *Q(P->right); 55 | P->right = Q->left; 56 | Q->left = P; 57 | P->update_height(); 58 | Q->update_height(); 59 | return Q; 60 | } 61 | 62 | template 63 | AVL_Node *AVL_Tree::balance(AVL_Node *node) 64 | { 65 | if (node->balance_factor() == 2) // Left 66 | { 67 | if (node->left->balance_factor() == -1) // Left Right? 68 | node->left = left_rotation(node->left); // To Left Left 69 | node = right_rotation(node); // Balance Left Left 70 | } 71 | else if (node->balance_factor() == -2) 72 | { 73 | if (node->right->balance_factor() == 1) 74 | node->right = right_rotation(node->right); 75 | 76 | node = left_rotation(node); 77 | } 78 | return node; 79 | } 80 | 81 | template 82 | AVL_Node *AVL_Tree::insert_node(type val, AVL_Node *node) 83 | { 84 | if (val < node->data) 85 | { 86 | if (!node->left) 87 | node->left = new AVL_Node(val); 88 | else 89 | node->left = insert_node(val, node->left); 90 | } 91 | else if (val > node->data) 92 | { 93 | if (!node->right) 94 | node->right = new AVL_Node(val); 95 | else 96 | node->right = insert_node(val, node->right); 97 | } 98 | node->update_height(); 99 | return balance(node); 100 | } 101 | 102 | template 103 | bool AVL_Tree::is_bst(AVL_Node *node) 104 | { 105 | bool left_bst(!node->left || node->data > node->left->data && is_bst(node->left)); 106 | 107 | if (!left_bst) 108 | return false; 109 | 110 | bool right_bst(!node->right || node->data < node->right->data && is_bst(node->right)); 111 | return right_bst; 112 | } 113 | 114 | template 115 | void AVL_Tree::verify() 116 | { 117 | assert(abs(root->balance_factor()) < 2); 118 | assert(is_bst(root)); 119 | } 120 | 121 | template 122 | void AVL_Tree::print_in_order_node(AVL_Node *node) 123 | { 124 | if (!node) 125 | return; 126 | print_in_order_node(node->left); 127 | std::cout << node->data << ' '; 128 | print_in_order_node(node->right); 129 | } 130 | 131 | template 132 | AVL_Node *AVL_Tree::min_node(AVL_Node *cur) 133 | { 134 | while (cur && cur->left) 135 | cur = cur->left; 136 | return cur; 137 | } 138 | 139 | template 140 | AVL_Node *AVL_Tree::max_node(AVL_Node *cur) 141 | { 142 | while (cur && cur->right) 143 | cur = cur->right; 144 | return cur; 145 | } 146 | 147 | template 148 | AVL_Node *AVL_Tree::delete_node(type val, AVL_Node *node) 149 | { 150 | if (!node) 151 | return nullptr; 152 | if (val < node->data) 153 | node->left = delete_node(val, node->left); 154 | else if (val > node->data) 155 | node->right = delete_node(val, node->right); 156 | else 157 | { 158 | AVL_Node *tmp(node); 159 | if (!node->left && !node->right) // case 1: no child 160 | node = nullptr; 161 | else if (!node->right) // case 2: has left only 162 | node = node->left; // connect with child 163 | else if (!node->left) // case 2: has right only 164 | node = node->right; 165 | else // 2 children: Use successor 166 | { 167 | AVL_Node *mn(min_node(node->right)); 168 | node->data = mn->data; // copy & go delete 169 | node->right = delete_node(node->data, node->right); 170 | tmp = nullptr; // Don't delete me. Successor will be deleted 171 | } 172 | if (tmp) 173 | delete tmp; 174 | } 175 | if (node) 176 | { 177 | node->update_height(); 178 | node = balance(node); 179 | } 180 | return node; 181 | } 182 | 183 | template 184 | AVL_Node *AVL_Tree::lower_bound_node(type val, AVL_Node *node) 185 | { 186 | if (!node) 187 | return nullptr; 188 | if (node->data >= val) 189 | { 190 | AVL_Node *ans(lower_bound_node(val, node->left)); 191 | if (ans) 192 | return ans; 193 | return node; 194 | } 195 | return lower_bound_node(val, node->right); 196 | } 197 | 198 | template 199 | AVL_Node *AVL_Tree::upper_bound_node(type val, AVL_Node *node) 200 | { 201 | if (!node) 202 | return nullptr; 203 | if (node->data > val) 204 | { 205 | AVL_Node *ans(upper_bound_node(val, node->left)); 206 | if (ans) 207 | return ans; 208 | return node; 209 | } 210 | return upper_bound_node(val, node->right); 211 | } 212 | 213 | template 214 | bool AVL_Tree::prefix_exist_node(std::string prefix, AVL_Node *node) 215 | { 216 | std::string str(node->data.substr(0, std::min(node->data.size(), prefix.size()))); 217 | if (prefix == str) 218 | return true; 219 | if (prefix < str) 220 | return node->left && prefix_exist_node(prefix, node->left); 221 | return node->right && prefix_exist_node(prefix, node->right); 222 | } 223 | 224 | template 225 | void AVL_Tree::insert_value(type val) 226 | { 227 | if (!root) 228 | root = new AVL_Node(val); 229 | else 230 | root = insert_node(val, root); 231 | verify(); 232 | } 233 | 234 | template 235 | bool AVL_Tree::search(type val) 236 | { 237 | return search_node(val, root); 238 | } 239 | 240 | template 241 | void AVL_Tree::print_in_order() 242 | { 243 | print_in_order_node(root); 244 | } 245 | 246 | template 247 | type AVL_Tree::min_value() 248 | { 249 | return min_node(root)->data; 250 | } 251 | 252 | template 253 | type AVL_Tree::max_value() 254 | { 255 | return max_node(root)->data; 256 | } 257 | 258 | template 259 | void AVL_Tree::delete_value(type val) 260 | { 261 | if (root) 262 | { 263 | root = delete_node(val, root); 264 | verify(); 265 | } 266 | } 267 | 268 | template 269 | void AVL_Tree::level_order_traversal() 270 | { 271 | if (!root) 272 | return; 273 | std::queue *> nodes_queue; 274 | nodes_queue.push(root); 275 | int level(0); 276 | while (!nodes_queue.empty()) 277 | { 278 | int sze(nodes_queue.size()); 279 | std::cout << "Level " << level << ": "; 280 | while (sze--) 281 | { 282 | AVL_Node *cur(nodes_queue.front()); 283 | nodes_queue.pop(); 284 | std::cout << cur->data << ' '; 285 | if (cur->left) 286 | nodes_queue.push(cur->left); 287 | if (cur->right) 288 | nodes_queue.push(cur->right); 289 | } 290 | ++level; 291 | std::cout << edl; 292 | } 293 | } 294 | 295 | template 296 | std::pair AVL_Tree::lower_bound(type val) 297 | { 298 | if (root) 299 | { 300 | AVL_Node *ans(lower_bound_node(val, root)); 301 | if (!ans) 302 | return std::make_pair(false, -123); 303 | return std::make_pair(true, ans->data); 304 | } 305 | return std::make_pair(false, -123); 306 | } 307 | 308 | template 309 | std::pair AVL_Tree::upper_bound(type val) 310 | { 311 | if (root) 312 | { 313 | AVL_Node *ans(upper_bound_node(val, root)); 314 | if (!ans) 315 | return std::make_pair(false, -123); 316 | return std::make_pair(true, ans->data); 317 | } 318 | return std::make_pair(false, -123); 319 | } 320 | 321 | template 322 | int AVL_Tree::avl_nodes_recursive(int height) 323 | { 324 | // no(h) = 1 + no(h - 1) + no(h - 2); 325 | if (!height) 326 | return 1; 327 | else if (height == 1) 328 | return 2; 329 | return 1 + avl_nodes_recursive(height - 1) + avl_nodes_recursive(height - 2); 330 | } 331 | 332 | template 333 | int AVL_Tree::avl_nodes_iterative(int height) 334 | { 335 | if (!height) 336 | return 1; 337 | if (height == 1) 338 | return 2; 339 | --height; 340 | int a(1), b(2), c; 341 | while (height--) 342 | c = a + b + 1, a = b, b = c; 343 | return c; 344 | } 345 | 346 | template 347 | bool AVL_Tree::prefix_exist(std::string prefix) 348 | { 349 | if (root) 350 | return prefix_exist_node(prefix, root); 351 | return false; 352 | } 353 | #endif -------------------------------------------------------------------------------- /source/Binary_Search_Tree.cpp: -------------------------------------------------------------------------------- 1 | #ifndef BINARY_SEARCH_TREE_CPP 2 | #define BINARY_SEARCH_TREE_CPP 3 | 4 | #include "../header/Binary_Search_Tree.h" 5 | 6 | template 7 | Binary_Search_Tree::Binary_Search_Tree(type d, Binary_Search_Tree *l, Binary_Search_Tree *r) : data(d), left(l), right(r) {} 8 | 9 | template 10 | Binary_Search_Tree::Binary_Search_Tree(std::deque &preorder, type min, type max) 11 | { 12 | data = preorder[0]; 13 | preorder.pop_front(); 14 | if (next_between(preorder, min, data)) 15 | left = new Binary_Search_Tree(preorder, min, data); 16 | if (next_between(preorder, data, max)) 17 | right = new Binary_Search_Tree(preorder, data, max); 18 | } 19 | 20 | template 21 | Binary_Search_Tree::Binary_Search_Tree(std::deque level_order) 22 | { 23 | std::queue *, std::pair>> nodes_queue; 24 | data = level_order[0]; 25 | level_order.pop_front(); 26 | nodes_queue.push(range(this, INT_MIN, INT_MAX)); 27 | while (!nodes_queue.empty()) 28 | { 29 | int sze(nodes_queue.size()); 30 | while (sze--) 31 | { 32 | Binary_Search_Tree *cur(nodes_queue.front().first); 33 | type mn(nodes_queue.front().second.first); 34 | type mx(nodes_queue.front().second.second); 35 | type data(cur->data); 36 | nodes_queue.pop(); 37 | if (next_between(level_order, mn, data)) 38 | { 39 | type new_data(level_order[0]); 40 | level_order.pop_front(); 41 | cur->left = new Binary_Search_Tree(new_data); 42 | nodes_queue.push(range(cur->left, mn, data)); 43 | } 44 | if (next_between(level_order, data, mx)) 45 | { 46 | type new_data(level_order[0]); 47 | level_order.pop_front(); 48 | cur->right = new Binary_Search_Tree(new_data); 49 | nodes_queue.push(range(cur->right, data, mx)); 50 | } 51 | } 52 | } 53 | assert(is_bst_1()); 54 | } 55 | 56 | template 57 | Binary_Search_Tree::~Binary_Search_Tree() 58 | { 59 | clear(); 60 | } 61 | 62 | template 63 | void Binary_Search_Tree::clear() 64 | { 65 | // Don't try to call clear for children and also delete. This deletes twice! 66 | if (left) 67 | delete left, left = nullptr; 68 | if (right) 69 | delete right, left = right; 70 | } 71 | 72 | // Check if the next element in the preorder is in the range 73 | template 74 | bool Binary_Search_Tree::next_between(std::deque &preorder, type min, type max) 75 | { 76 | if (preorder.empty()) 77 | return false; 78 | return ((min < preorder[0]) && (preorder[0] < max)); 79 | } 80 | 81 | template 82 | std::pair *, std::pair> Binary_Search_Tree::range(Binary_Search_Tree *node, type mn, type mx) 83 | { 84 | std::pair range(make_pair(mn, mx)); 85 | return make_pair(node, range); 86 | } 87 | 88 | template 89 | Binary_Search_Tree *Binary_Search_Tree::min_node() 90 | { 91 | Binary_Search_Tree *cur(this); 92 | while (cur && cur->left) 93 | cur = cur->left; 94 | return cur; 95 | } 96 | 97 | template 98 | Binary_Search_Tree *Binary_Search_Tree::max_node() 99 | { 100 | Binary_Search_Tree *cur(this); 101 | while (cur && cur->right) 102 | cur = cur->right; 103 | return cur; 104 | } 105 | 106 | template 107 | void Binary_Search_Tree::special_delete(Binary_Search_Tree *child) 108 | { 109 | data = child->data; 110 | left = child->left; 111 | right = child->right; 112 | delete child; 113 | } 114 | template 115 | Binary_Search_Tree *Binary_Search_Tree::delete_node_s(type target, Binary_Search_Tree *node) 116 | { 117 | if (!node) 118 | return nullptr; 119 | if (target < node->data) 120 | node->left = delete_node_s(target, node->left); 121 | else if (target > node->data) 122 | node->right = delete_node_s(target, node->right); 123 | else 124 | { 125 | if (!node->left && !node->right) 126 | { 127 | delete node; 128 | node = nullptr; 129 | } 130 | else if (!node->right) // case 2: has left only 131 | node->special_delete(node->left); // connect with child 132 | else if (!node->left) // case 2: has right only 133 | node->special_delete(node->right); 134 | else // 2 children: Use successor 135 | { 136 | Binary_Search_Tree *mn(node->right->min_node()); 137 | node->data = mn->data; // copy & go delete 138 | node->right = delete_node_s(node->data, node->right); 139 | } 140 | } 141 | return node; 142 | } 143 | 144 | template 145 | Binary_Search_Tree *Binary_Search_Tree::delete_node_p(type target, Binary_Search_Tree *node) 146 | { 147 | if (!node) 148 | return nullptr; 149 | if (target < node->data) 150 | node->left = delete_node_p(target, node->left); 151 | else if (target > node->data) 152 | node->right = delete_node_p(target, node->right); 153 | else 154 | { 155 | if (!node->left && !node->right) 156 | { 157 | delete node; 158 | node = nullptr; 159 | } 160 | else if (!node->right) // case 2: has left only 161 | node->special_delete(node->left); // connect with child 162 | else if (!node->left) // case 2: has right only 163 | node->special_delete(node->right); 164 | else // 2 children: Use predecessor 165 | { 166 | Binary_Search_Tree *mx(node->left->max_node()); 167 | node->data = mx->data; // copy & go delete 168 | node->left = delete_node_p(node->data, node->left); 169 | } 170 | } 171 | return node; 172 | } 173 | 174 | template 175 | void Binary_Search_Tree::get_in_order(std::vector &inorder_values) 176 | { 177 | if (left) 178 | left->get_in_order(inorder_values); 179 | inorder_values.emplace_back(data); 180 | if (right) 181 | right->get_in_order(inorder_values); 182 | } 183 | 184 | template 185 | void Binary_Search_Tree::get_pre_order(std::deque &preorder_values) 186 | { 187 | preorder_values.push_back(data); 188 | if (left) 189 | left->get_pre_order(preorder_values); 190 | if (right) 191 | right->get_pre_order(preorder_values); 192 | } 193 | 194 | template 195 | void Binary_Search_Tree::print_in_order() 196 | { 197 | if (left) 198 | left->print_in_order(); 199 | std::cout << data << ' '; 200 | if (right) 201 | right->print_in_order(); 202 | } 203 | 204 | template 205 | void Binary_Search_Tree::insert(type val) 206 | { 207 | if (val < data) 208 | { 209 | if (!left) 210 | left = new Binary_Search_Tree(val); 211 | else 212 | left->insert(val); 213 | } 214 | else if (val > data) 215 | { 216 | if (!right) 217 | right = new Binary_Search_Tree(val); 218 | else 219 | right->insert(val); 220 | } 221 | } 222 | 223 | template 224 | bool Binary_Search_Tree::search(type val) 225 | { 226 | if (val == data) 227 | return true; 228 | if (val < data) 229 | return left && left->search(val); 230 | return right && right->search(val); 231 | } 232 | 233 | template 234 | std::deque Binary_Search_Tree::level_order_traversal() 235 | { 236 | std::queue *> nodes_queue; 237 | nodes_queue.push(this); 238 | std::deque level_order; 239 | int level(0); 240 | while (!nodes_queue.empty()) 241 | { 242 | int sze(nodes_queue.size()); 243 | while (sze--) 244 | { 245 | Binary_Search_Tree *cur(nodes_queue.front()); 246 | nodes_queue.pop(); 247 | level_order.push_back(cur->data); 248 | if (cur->left) 249 | nodes_queue.push(cur->left); 250 | if (cur->right) 251 | nodes_queue.push(cur->right); 252 | } 253 | ++level; 254 | } 255 | return level_order; 256 | } 257 | 258 | template 259 | type Binary_Search_Tree::min_value() 260 | { 261 | return min_node()->data; 262 | } 263 | 264 | template 265 | type Binary_Search_Tree::max_value() 266 | { 267 | return max_node()->data; 268 | } 269 | 270 | template 271 | bool Binary_Search_Tree::search_iterative(type val) 272 | { 273 | Binary_Search_Tree *root(this); 274 | while (root) 275 | { 276 | if (val == root->data) 277 | return true; 278 | if (root->data < val) 279 | root = root->right; 280 | else if (root->data > val) 281 | root = root->left; 282 | } 283 | return false; 284 | } 285 | 286 | template 287 | bool Binary_Search_Tree::is_bst_0(type mn, type mx) 288 | { 289 | bool status((mn < data) && (data < mx)); 290 | if (!status) 291 | return false; 292 | bool left_bst(!left || left->is_bst_0(mn, data)); 293 | if (!left_bst) 294 | return false; 295 | bool right_bst(!right || right->is_bst_0(data, mx)); 296 | return right_bst; 297 | } 298 | 299 | template 300 | bool Binary_Search_Tree::is_bst_1() 301 | { 302 | std::vector inorder_values; 303 | get_in_order(inorder_values); 304 | int len((int)inorder_values.size()); 305 | for (int i(1); i < len; ++i) 306 | { 307 | if (inorder_values[i] < inorder_values[i - 1]) 308 | return false; 309 | } 310 | return true; 311 | } 312 | 313 | template 314 | Binary_Search_Tree *Binary_Search_Tree::build_balanced_bst_tree(std::vector &values, int str, int end) 315 | { 316 | if (end == -1) // first call 317 | end = (int)values.size() - 1; 318 | if (str > end) 319 | return nullptr; 320 | int mid((str + end) >> 1); // mid(str + ((end - str) >> 1)); 321 | Binary_Search_Tree *left(build_balanced_bst_tree(values, str, mid - 1)); 322 | Binary_Search_Tree *right(build_balanced_bst_tree(values, mid + 1, end)); 323 | Binary_Search_Tree *root(new Binary_Search_Tree(values[mid], left, right)); 324 | return root; 325 | } 326 | 327 | template 328 | type Binary_Search_Tree::kth_smallest_0(int &k) 329 | { 330 | std::vector vals; 331 | get_in_order(vals); 332 | int len((int)vals.size()); 333 | if (k >= len) 334 | return -1234; 335 | else 336 | return vals[k - 1]; 337 | } 338 | 339 | template 340 | type Binary_Search_Tree::kth_smallest_1(int &k) 341 | { 342 | if (!k) 343 | return -1234; 344 | if (left) 345 | { 346 | type res(left->kth_smallest_1(k)); 347 | if (!k) 348 | return res; 349 | } 350 | --k; 351 | if (!k) 352 | return data; 353 | if (right) 354 | return right->kth_smallest_1(k); 355 | return -1234; 356 | } 357 | 358 | template 359 | type Binary_Search_Tree::LCA(type x, type y) 360 | { 361 | if (data > x && data > y) 362 | return left->LCA(x, y); 363 | if (data < x && data < y) 364 | return right->LCA(x, y); 365 | return data; 366 | } 367 | 368 | template 369 | bool Binary_Search_Tree::find_chain(std::vector *> &ancestors, type val) 370 | { 371 | ancestors.push_back(this); 372 | if (val == data) 373 | return true; 374 | if (val < data) 375 | return left && left->find_chain(ancestors, val); 376 | return right && right->find_chain(ancestors, val); 377 | } 378 | 379 | template 380 | Binary_Search_Tree *Binary_Search_Tree::get_next(std::vector *> &ancestors) 381 | { 382 | if (!ancestors.size()) 383 | return nullptr; 384 | Binary_Search_Tree *node(ancestors.back()); 385 | ancestors.pop_back(); 386 | return node; 387 | } 388 | 389 | template 390 | std::pair Binary_Search_Tree::successor(type val) 391 | { 392 | std::vector *> ancestors; 393 | 394 | if (!find_chain(ancestors, val)) 395 | return std::make_pair(false, -1); 396 | 397 | Binary_Search_Tree *child(get_next(ancestors)); 398 | 399 | if (child->right) 400 | return std::make_pair(true, child->right->min_value()); 401 | 402 | Binary_Search_Tree *parent(get_next(ancestors)); 403 | 404 | while (parent && parent->right == child) 405 | child = parent, parent = get_next(ancestors); 406 | 407 | if (parent) 408 | return std::make_pair(true, parent->data); 409 | return std::make_pair(false, -1); 410 | } 411 | 412 | template 413 | void Binary_Search_Tree::delete_value_successor(type val) 414 | { 415 | if (val == data && !left && !right) 416 | return; // can't remove root in this structure 417 | delete_node_s(val, this); 418 | } 419 | 420 | template 421 | void Binary_Search_Tree::delete_value_predecessor(type val) 422 | { 423 | if (val == data && !left && !right) 424 | return; // can't remove root in this structure 425 | delete_node_p(val, this); 426 | } 427 | #endif -------------------------------------------------------------------------------- /source/Singly_LinkedList.cpp: -------------------------------------------------------------------------------- 1 | #ifndef SINGLY_LINKEDLIST_CPP 2 | #define SINGLY_LINKEDLIST_CPP 3 | 4 | #include "../header/Singly_LinkedList.h" 5 | 6 | template 7 | Singly_LinkedList::Singly_LinkedList() {} 8 | 9 | template 10 | Singly_LinkedList::~Singly_LinkedList() 11 | { 12 | while (head) 13 | { 14 | S_Node *cur(head->next); 15 | delete head; 16 | head = cur; 17 | } 18 | head = tail = nullptr; 19 | length = 0; 20 | } 21 | 22 | template 23 | const type Singly_LinkedList::get_value(int idx) 24 | { 25 | assert(idx >= 0 || idx < length); 26 | S_Node *cur(head); 27 | int cur_idx(0); 28 | while (cur_idx < idx) 29 | cur = cur->next, ++cur_idx; 30 | return cur->data; 31 | } 32 | 33 | template 34 | const int Singly_LinkedList::get_length() 35 | { 36 | return length; 37 | } 38 | 39 | template 40 | void Singly_LinkedList::insert_end(type val) 41 | { 42 | S_Node *item(new S_Node(val)); 43 | if (!head) 44 | head = tail = item; 45 | else 46 | { 47 | tail->next = item; 48 | tail = item; 49 | } 50 | // tail->next = nullptr; // it depends on the compiler 51 | ++length; 52 | } 53 | 54 | template 55 | void Singly_LinkedList::insert_front(type val) 56 | { 57 | S_Node *item(new S_Node(val)); 58 | ++length; 59 | item->next = head; 60 | head = item; 61 | if (length == 1) 62 | tail = head; 63 | } 64 | 65 | template 66 | void Singly_LinkedList::insert_after(S_Node *src, S_Node *target) 67 | { 68 | assert(src && target); 69 | target->next = src->next; 70 | src->next = target; 71 | ++length; 72 | } 73 | 74 | template 75 | void Singly_LinkedList::insert_sorted(type val) 76 | { 77 | if (!length || head->data >= val) 78 | insert_front(val); 79 | else if (tail->data <= val) 80 | insert_end(val); 81 | else 82 | { 83 | for (S_Node *cur(head), *prv(nullptr); cur; prv = cur, cur = cur->next) 84 | { 85 | if (cur->data >= val) 86 | { 87 | S_Node *item(new S_Node(val)); 88 | ++length; 89 | item->next = prv->next; 90 | prv->next = item; 91 | break; 92 | } 93 | } 94 | } 95 | } 96 | 97 | template 98 | S_Node *Singly_LinkedList::find(type val) 99 | { 100 | for (S_Node *cur(head); cur; cur = cur->next) 101 | { 102 | if (cur->data == val) 103 | return cur; 104 | } 105 | return nullptr; 106 | } 107 | 108 | template 109 | void Singly_LinkedList::print() 110 | { 111 | for (S_Node *cur(head); cur; cur = cur->next) 112 | std::cout << cur->data << ' '; 113 | std::cout << edl; 114 | } 115 | 116 | template 117 | void Singly_LinkedList::print_recr(S_Node *h) 118 | { 119 | if (!h) 120 | { 121 | std::cout << edl; 122 | return; 123 | } 124 | std::cout << h->data << ' '; 125 | print_recr(h->next); 126 | } 127 | 128 | template 129 | void Singly_LinkedList::print_recr_rever(S_Node *h) 130 | { 131 | if (!h) 132 | { 133 | std::cout << edl; 134 | return; 135 | } 136 | print_recr(h->next); 137 | std::cout << h->data << ' '; 138 | } 139 | 140 | template 141 | S_Node *Singly_LinkedList::get_nth(int n) 142 | { 143 | for (S_Node *cur(head); cur; cur = cur->next) 144 | if (!(--n)) 145 | return cur; 146 | return nullptr; 147 | } 148 | 149 | template 150 | S_Node *Singly_LinkedList::get_nth_from_back(int idx) 151 | { 152 | if (idx > length) 153 | return nullptr; 154 | return get_nth(length - idx + 1); 155 | } 156 | 157 | template 158 | int Singly_LinkedList::search(type val) 159 | { 160 | int idx(0); 161 | for (S_Node *cur(head); cur; cur = cur->next, ++idx) 162 | if (cur->data == val) 163 | return idx; 164 | return -1; 165 | } 166 | 167 | template 168 | int Singly_LinkedList::search_improved(type val) 169 | { 170 | int idx(0); 171 | S_Node *prv(nullptr); 172 | for (S_Node *cur(head); cur; cur = cur->next, ++idx) 173 | { 174 | if (cur->data == val) 175 | { 176 | if (!prv) 177 | return idx; 178 | swap(prv->data, cur->data); 179 | return idx - 1; 180 | } 181 | prv = cur; 182 | } 183 | return -1; 184 | } 185 | 186 | template 187 | int Singly_LinkedList::search_improved_v2(type val) // commonly used 188 | { 189 | int idx(0); 190 | for (S_Node *cur(head), *prv(nullptr); cur; prv = cur, cur = cur->next) 191 | { 192 | if (cur->data == val) 193 | { 194 | if (!prv) 195 | return idx; 196 | swap(prv->data, cur->data); 197 | return idx - 1; 198 | } 199 | ++idx; 200 | } 201 | return -1; 202 | } 203 | 204 | template 205 | bool Singly_LinkedList::is_same(const Singly_LinkedList &list) 206 | { 207 | if (length != list.length) 208 | return false; 209 | S_Node *temp(list.head); 210 | for (S_Node *cur(head); cur; cur = cur->next) 211 | { 212 | if (cur->data != temp->data) 213 | return false; 214 | temp = temp->next; 215 | } 216 | return true; 217 | } 218 | 219 | template 220 | S_Node *Singly_LinkedList::move_and_delete(S_Node *node) 221 | { 222 | S_Node *tmp(node->next); 223 | delete_node(node); 224 | return tmp; 225 | } 226 | 227 | template 228 | void Singly_LinkedList::delete_node(S_Node *node) 229 | { 230 | --length; 231 | delete node; 232 | } 233 | 234 | template 235 | type Singly_LinkedList::pop_front() 236 | { 237 | assert(head); 238 | S_Node *cur(head); 239 | type val(cur->data); 240 | head = head->next; 241 | delete_node(cur); 242 | if (!head) 243 | tail = nullptr; 244 | return val; 245 | } 246 | 247 | template 248 | type Singly_LinkedList::pop_back() 249 | { 250 | if (length < 2) 251 | return pop_front(); 252 | S_Node *previous(get_nth(length - 1)); 253 | type val(tail->data); 254 | delete_node(tail); 255 | tail = previous; 256 | tail->next = nullptr; 257 | return val; 258 | } 259 | 260 | template 261 | void Singly_LinkedList::delete_nth_node(int n) 262 | { 263 | if (n < 1 || n > length) 264 | std::cout << "Error. No such nth node" << edl; 265 | else if (n == 1) 266 | pop_front(); 267 | else 268 | { 269 | S_Node *before_nth(get_nth(n - 1)); 270 | S_Node *nth(before_nth->next); 271 | bool is_tail(nth == tail); 272 | before_nth->next = nth->next; 273 | if (is_tail) 274 | tail = before_nth; 275 | delete_node(nth); 276 | } 277 | } 278 | 279 | template 280 | void Singly_LinkedList::delete_next_node(S_Node *node) 281 | { 282 | S_Node *to_delete(node->next); 283 | bool is_tail(to_delete == tail); 284 | node->next = node->next->next; 285 | delete_node(to_delete); 286 | if (is_tail) 287 | tail = node; 288 | } 289 | 290 | template 291 | void Singly_LinkedList::delete_node_with_key(type val) 292 | { 293 | if (!length) 294 | std::cout << "List is Empty" << edl; 295 | else if (head->data == val) 296 | pop_front(); 297 | else 298 | { 299 | for (S_Node *cur(head), *prev(nullptr); cur; prev = cur, cur = cur->next) 300 | { 301 | if (cur->data == val) 302 | { 303 | delete_next_node(prev); 304 | break; 305 | } 306 | } 307 | } 308 | } 309 | 310 | template 311 | void Singly_LinkedList::delete_even_positions() 312 | { 313 | if (length < 2) 314 | return; 315 | for (S_Node *cur(head->next), *prv(head); cur;) 316 | { 317 | delete_next_node(prv); 318 | if (!prv->next) 319 | break; 320 | cur = prv->next->next; 321 | prv = prv->next; 322 | } 323 | } 324 | 325 | template 326 | void Singly_LinkedList::delete_last_occurrence_not_sorted(type key) 327 | { 328 | if (!length) 329 | return; 330 | S_Node *delete_node(nullptr); 331 | bool flag(false); 332 | for (S_Node *cur(head), *prv(nullptr); cur; prv = cur, cur = cur->next) 333 | { 334 | if (cur->data == key) 335 | flag = true, delete_node = prv; 336 | } 337 | if (flag) 338 | { 339 | if (delete_node) 340 | delete_next_node(delete_node); 341 | else 342 | pop_front(); 343 | } 344 | } 345 | 346 | template 347 | void Singly_LinkedList::remove_duplicates_not_sorted() 348 | { 349 | if (length < 2) 350 | return; 351 | 352 | for (S_Node *cur1(head); cur1; cur1 = cur1->next) 353 | { 354 | for (S_Node *cur2(cur1->next), *prv(cur1); cur2;) 355 | { 356 | if (cur1->data == cur2->data) 357 | { 358 | delete_next_node(prv); 359 | cur2 = prv->next; 360 | } 361 | else 362 | prv = cur2, cur2 = cur2->next; 363 | } 364 | } 365 | } 366 | 367 | template 368 | void Singly_LinkedList::swap_repairs() 369 | { 370 | for (S_Node *cur(head); cur; cur = cur->next) 371 | { 372 | if (cur->next) 373 | { 374 | swap(cur->data, cur->next->data); 375 | cur = cur->next; 376 | } 377 | } 378 | } 379 | 380 | template 381 | void Singly_LinkedList::reverse() 382 | { 383 | if (length < 2) 384 | return; 385 | S_Node *cur(head), *prev(nullptr), *nxt(nullptr); 386 | while (cur) 387 | { 388 | nxt = cur->next; 389 | cur->next = prev; 390 | prev = cur; 391 | cur = nxt; 392 | } 393 | tail = head; 394 | head = prev; 395 | // tail->next = nullptr; // it depends on the compiler 396 | } 397 | 398 | template 399 | S_Node *Singly_LinkedList::get_previous(S_Node *node) 400 | { 401 | for (S_Node *cur(head), *prv(nullptr); cur; prv = cur, cur = cur->next) 402 | { 403 | if (cur == node) 404 | return prv; 405 | } 406 | return nullptr; 407 | } 408 | 409 | template 410 | void Singly_LinkedList::swap_head_tail() 411 | { 412 | if (length < 2) 413 | return; 414 | S_Node *prv(get_previous(tail)); 415 | tail->next = head->next; 416 | prv->next = head; 417 | head->next = nullptr; 418 | swap(tail, head); 419 | } 420 | 421 | template 422 | void Singly_LinkedList::left_rotate(int key) 423 | { 424 | key %= length; 425 | if (!key || length < 2) 426 | return; 427 | S_Node *cur(get_nth(key)); 428 | tail->next = head; 429 | tail = cur; 430 | head = cur->next; 431 | tail->next = nullptr; 432 | } 433 | 434 | template 435 | S_Node *Singly_LinkedList::move_to_end(S_Node *cur, S_Node *prv) 436 | { 437 | S_Node *nxt(cur->next); 438 | tail->next = cur; 439 | if (prv) 440 | prv->next = nxt; 441 | else 442 | head = nxt; 443 | tail = cur; 444 | tail->next = nullptr; 445 | return nxt; 446 | } 447 | 448 | template 449 | void Singly_LinkedList::move_key_occurance_to_end_not_sorted(type key) 450 | { 451 | if (length < 2) 452 | return; 453 | int len(length); 454 | for (S_Node *cur(head), *prv(nullptr); len--;) 455 | { 456 | if (cur->data == key) 457 | cur = move_to_end(cur, prv); 458 | else 459 | prv = cur, cur = cur->next; 460 | } 461 | } 462 | 463 | template 464 | S_Node *Singly_LinkedList::max_node(S_Node *h) 465 | { 466 | if (!h) 467 | return nullptr; 468 | else 469 | { 470 | S_Node *mx_node(max_node(h->next)); 471 | if (!mx_node || h->data > mx_node->data) 472 | mx_node = h; 473 | return mx_node; 474 | } 475 | } 476 | 477 | template 478 | S_Node *Singly_LinkedList::min_node(S_Node *h) 479 | { 480 | if (!h) 481 | return nullptr; 482 | else 483 | { 484 | S_Node *mn_node(min_node(h->next)); 485 | if (!mn_node || h->data < mn_node->data) 486 | mn_node = h; 487 | return mn_node; 488 | } 489 | } 490 | 491 | template 492 | type Singly_LinkedList::max_value() 493 | { 494 | return max_node(head)->data; 495 | } 496 | 497 | template 498 | type Singly_LinkedList::min_value() 499 | { 500 | return min_node(head)->data; 501 | } 502 | 503 | template 504 | type Singly_LinkedList::middle_value() 505 | { 506 | // based on The Tortoise and the Hare Algorithm 507 | assert(head); 508 | S_Node *fast(head), *slow(head); 509 | while (fast && fast->next) 510 | { 511 | fast = fast->next->next; 512 | slow = slow->next; 513 | } 514 | return slow->data; 515 | } 516 | 517 | template 518 | void Singly_LinkedList::arrange_odd_pos_even_pos() 519 | { 520 | if (length < 3) 521 | return; 522 | S_Node *first_even(head->next), *cur_odd(head); 523 | while (cur_odd->next && cur_odd->next->next) 524 | { 525 | S_Node *next_even(cur_odd->next); 526 | // connect odd with odd and even with even 527 | cur_odd->next = cur_odd->next->next; 528 | next_even->next = next_even->next->next; 529 | cur_odd = cur_odd->next; 530 | // for odd length, tail is changed to last even node 531 | if (length & 1) 532 | tail = next_even; 533 | } 534 | // connect last odd with the first even 535 | cur_odd->next = first_even; 536 | } 537 | 538 | template 539 | void Singly_LinkedList::insert_alternate(Singly_LinkedList &other) 540 | { 541 | if (!other.length) 542 | return; 543 | if (!length) 544 | { 545 | head = other.head; 546 | tail = other.tail; 547 | length = other.length; 548 | } 549 | else 550 | { 551 | S_Node *his_cur(other.head); 552 | for (S_Node *my_cur(head); my_cur && his_cur;) 553 | { 554 | S_Node *his_cur_next_tmp(his_cur->next); 555 | insert_after(my_cur, his_cur); 556 | --other.length; 557 | his_cur = his_cur_next_tmp; 558 | if (my_cur == tail) 559 | { 560 | tail = other.tail; 561 | my_cur->next->next = his_cur; 562 | length += other.length; 563 | break; 564 | } 565 | my_cur = my_cur->next->next; 566 | } 567 | } 568 | other.head = other.tail = nullptr; 569 | other.length = 0; 570 | } 571 | 572 | template 573 | S_Node *Singly_LinkedList::merge_two_lists_iterative(S_Node &head1, S_Node &head2) 574 | { 575 | S_Node *dummy(new S_Node(-1)); 576 | S_Node *ptr(dummy); 577 | while (head1 && head2) 578 | { 579 | if (head1->data < head2->data) 580 | ptr->next = head1, head1 = head1->next; 581 | else 582 | ptr->next = head2, head2 = head2->next; 583 | ptr = ptr->next; 584 | } 585 | ptr->next = (head1 ? head1 : head2); 586 | // while (head1) 587 | // ptr->next = head1, ptr = ptr->next, head1 = head1->next; 588 | // while (head2) 589 | // ptr->next = head2, ptr = ptr->next, head2 = head2->next; 590 | return dummy->next; 591 | } 592 | 593 | template 594 | S_Node *Singly_LinkedList::merge_two_lists_recursive(S_Node &head1, S_Node &head2) 595 | { 596 | if (!head1) 597 | return head2; 598 | if (!head2) 599 | return head1; 600 | S_Node *ans; 601 | if (head1->data < head2->data) 602 | ans = head1, ans->next = merge_two_lists_recursive(head1->next, head2); 603 | else 604 | ans = head2, ans->next = merge_two_lists_recursive(head1, head2->next); 605 | return ans; 606 | } 607 | 608 | template 609 | bool Singly_LinkedList::recursive_check(S_Node *cur_head) 610 | { 611 | if (cur_head) 612 | { 613 | if (!recursive_check(cur_head->next)) 614 | return false; 615 | if (frontptr->data != cur_head->data) 616 | return false; 617 | frontptr = frontptr->next; 618 | } 619 | return true; 620 | } 621 | 622 | template 623 | bool Singly_LinkedList::is_palindrome() 624 | { 625 | // see the slides here 626 | // https://leetcode.com/problems/palindrome-linked-list/editorial/ 627 | frontptr = head; 628 | return recursive_check(head); 629 | } 630 | #endif -------------------------------------------------------------------------------- /source/Binary_Tree.cpp: -------------------------------------------------------------------------------- 1 | #ifndef BINARY_TREE_CPP 2 | #define BINARY_TREE_CPP 3 | 4 | #include "../header/Binary_Tree.h" 5 | 6 | template 7 | Binary_Tree::Binary_Tree(type data) : data(data) {} 8 | 9 | template 10 | Binary_Tree::~Binary_Tree() 11 | { 12 | clear(); 13 | } 14 | 15 | template 16 | void Binary_Tree::clear() 17 | { 18 | // Don't try to call clear for children and also delete. This deletes twice! 19 | if (left) 20 | delete left, left = nullptr; 21 | if (right) 22 | delete right, left = right; 23 | } 24 | 25 | template 26 | void Binary_Tree::add(std::vector values, std::vector direction) 27 | { 28 | assert(values.size() == direction.size()); 29 | Binary_Tree *current(this); 30 | int len((int)values.size()); 31 | for (int i(0); i < len; ++i) 32 | { 33 | if (direction[i] == 'L') 34 | { 35 | if (!current->left) 36 | current->left = new Binary_Tree(values[i]); 37 | else 38 | assert(current->left->data == values[i]); 39 | current = current->left; 40 | } 41 | else 42 | { 43 | if (!current->right) 44 | current->right = new Binary_Tree(values[i]); 45 | else 46 | assert(current->right->data == values[i]); 47 | current = current->right; 48 | } 49 | } 50 | } 51 | 52 | template 53 | const void Binary_Tree::get_in_order(std::vector &inorder_values) 54 | 55 | { 56 | if (left) 57 | left->get_in_order(inorder_values); 58 | inorder_values.emplace_back(data); 59 | if (right) 60 | right->get_in_order(inorder_values); 61 | } 62 | 63 | template 64 | void Binary_Tree::print_in_order() 65 | { 66 | if (left) 67 | left->print_in_order(); 68 | std::cout << data << ' '; 69 | if (right) 70 | right->print_in_order(); 71 | } 72 | 73 | template 74 | void Binary_Tree::print_pre_order() 75 | { 76 | std::cout << data << ' '; 77 | if (left) 78 | left->print_pre_order(); 79 | if (right) 80 | right->print_pre_order(); 81 | } 82 | 83 | template 84 | void Binary_Tree::print_post_order() 85 | { 86 | if (left) 87 | left->print_post_order(); 88 | if (right) 89 | right->print_post_order(); 90 | std::cout << data << ' '; 91 | } 92 | 93 | template 94 | type Binary_Tree::max_value() 95 | { 96 | type mx(data); 97 | if (left) 98 | mx = std::max(mx, left->max_value()); 99 | if (right) 100 | mx = std::max(mx, right->max_value()); 101 | return mx; 102 | } 103 | 104 | template 105 | int Binary_Tree::tree_height_0() 106 | { 107 | int height(0); 108 | if (left) 109 | height = 1 + left->tree_height_0(); 110 | if (right) 111 | height = std::max(height, 1 + right->tree_height_0()); 112 | return height; 113 | } 114 | 115 | template 116 | int Binary_Tree::tree_height_1() 117 | { 118 | if (!left || !right) 119 | return 0; 120 | return 1 + std::max(left->tree_height_1(), right->tree_height_1()); 121 | } 122 | 123 | template 124 | int Binary_Tree::total_nodes() 125 | { 126 | int cnt(1); 127 | if (left) 128 | cnt += left->total_nodes(); 129 | if (right) 130 | cnt += right->total_nodes(); 131 | return cnt; 132 | } 133 | 134 | template 135 | int Binary_Tree::no_leaf_nodes() 136 | { 137 | int cnt(!left && !right); 138 | if (left) 139 | cnt += left->no_leaf_nodes(); 140 | if (right) 141 | cnt += right->no_leaf_nodes(); 142 | return cnt; 143 | } 144 | 145 | template 146 | bool Binary_Tree::is_exists(type value) 147 | { 148 | bool res(value == data); 149 | if (!res && left) 150 | res = left->is_exists(value); 151 | if (!res && right) 152 | res = right->is_exists(value); 153 | return res; 154 | } 155 | 156 | template 157 | bool Binary_Tree::is_perfect_fomula() 158 | { 159 | int height(tree_height_0()), nodes(total_nodes()); 160 | int res(pow(2, (height + 1)) - 1); 161 | return (res == nodes); 162 | } 163 | 164 | template 165 | bool Binary_Tree::is_perfect(int h) 166 | { 167 | if (h == -1) // first call 168 | h = tree_height_0(); 169 | 170 | if (!left && !right) 171 | return h == 0; 172 | 173 | if (!left && right || left && !right) 174 | return false; 175 | return left->is_perfect(h - 1) && right->is_perfect(h - 1); 176 | } 177 | 178 | template 179 | void Binary_Tree::print_inorder_iterative_0() 180 | { 181 | std::stack *, bool>> nodes; 182 | nodes.push(std::make_pair(this, false)); 183 | while (!nodes.empty()) 184 | { 185 | Binary_Tree *current(nodes.top().first); 186 | bool is_done(nodes.top().second); 187 | nodes.pop(); 188 | if (is_done) 189 | std::cout << current->data << ' '; 190 | else 191 | { 192 | if (current->right) 193 | nodes.push(std::make_pair(current->right, false)); 194 | nodes.push(std::make_pair(current, true)); 195 | if (current->left) 196 | nodes.push(std::make_pair(current->left, false)); 197 | } 198 | } 199 | std::cout << edl; 200 | } 201 | 202 | template 203 | void Binary_Tree::print_inorder_iterative_1() 204 | { 205 | std::stack *> st; 206 | Binary_Tree *cur(this); 207 | while (cur || !st.empty()) 208 | { 209 | while (cur) 210 | { 211 | st.push(cur); 212 | cur = cur->left; 213 | } 214 | cur = st.top(); 215 | st.pop(); 216 | std::cout << cur->data << ' '; 217 | cur = cur->right; 218 | } 219 | } 220 | 221 | template 222 | void Binary_Tree::traverse_left_boundry() 223 | { 224 | std::cout << data << ' '; 225 | if (left) 226 | left->traverse_left_boundry(); 227 | else if (right) 228 | right->traverse_left_boundry(); 229 | } 230 | 231 | template 232 | std::pair Binary_Tree::tree_diameter() 233 | { 234 | std::pair res(std::make_pair(0, 0)); 235 | if (!left && !right) 236 | return res; 237 | std::pair left_diam(std::make_pair(0, 0)); 238 | std::pair right_diam(std::make_pair(0, 0)); 239 | if (left) 240 | left_diam = left->tree_diameter(), res.first += 1 + left_diam.second; 241 | if (right) 242 | right_diam = right->tree_diameter(), res.first += 1 + right_diam.second; 243 | // diameter if in one of my children subtrees 244 | res.first = std::max(res.first, std::max(left_diam.first, right_diam.first)); 245 | // normal height computation 246 | res.second = 1 + std::max(left_diam.second, right_diam.second); 247 | return res; 248 | } 249 | 250 | template 251 | void Binary_Tree::level_order_traversal_0() 252 | { 253 | std::queue *> nodes_queue; 254 | nodes_queue.push(this); 255 | while (!nodes_queue.empty()) 256 | { 257 | Binary_Tree *cur(nodes_queue.front()); 258 | nodes_queue.pop(); 259 | std::cout << cur->data << ' '; 260 | if (cur->left) 261 | nodes_queue.push(cur->left); 262 | if (cur->right) 263 | nodes_queue.push(cur->right); 264 | } 265 | std::cout << edl; 266 | } 267 | 268 | template 269 | void Binary_Tree::level_order_traversal_1() 270 | { 271 | std::queue *> nodes_queue; 272 | nodes_queue.push(this); 273 | int level(0), sze; 274 | while (!nodes_queue.empty()) 275 | { 276 | sze = (int)nodes_queue.size(); 277 | std::cout << "Level " << level << ": "; 278 | while (sze--) 279 | { 280 | Binary_Tree *cur(nodes_queue.front()); 281 | nodes_queue.pop(); 282 | std::cout << cur->data << ' '; 283 | if (cur->left) 284 | nodes_queue.push(cur->left); 285 | if (cur->right) 286 | nodes_queue.push(cur->right); 287 | } 288 | ++level; 289 | std::cout << edl; 290 | } 291 | } 292 | 293 | template 294 | void Binary_Tree::print_level_nodes(int level) 295 | { 296 | if (!level) 297 | std::cout << data << ' '; 298 | else if (level) 299 | { 300 | if (left) 301 | left->print_level_nodes(level - 1); 302 | if (right) 303 | right->print_level_nodes(level - 1); 304 | } 305 | } 306 | 307 | template 308 | void Binary_Tree::level_order_traversal_sorted() 309 | { 310 | std::priority_queue *>> heaps[2]; 311 | int flag(0); 312 | heaps[flag].push(std::make_pair(data, this)); 313 | while (!heaps[flag].empty()) 314 | { 315 | int sze(heaps[flag].size()); 316 | while (sze--) 317 | { 318 | std::pair *> cur_pair(heaps[flag].top()); 319 | heaps[flag].pop(); 320 | Binary_Tree *cur(cur_pair.second); 321 | std::cout << cur_pair.first << ' '; 322 | if (cur->left) 323 | heaps[!flag].push(std::make_pair(cur->left->data, cur->left)); 324 | if (cur->right) 325 | heaps[!flag].push(std::make_pair(cur->right->data, cur->right)); 326 | } 327 | std::cout << edl; 328 | flag = !flag; 329 | } 330 | } 331 | 332 | template 333 | void Binary_Tree::level_order_traversal_recursive() // O(N^2) 334 | { 335 | int height(tree_height_0()); 336 | for (int level(0); level <= height; ++level) 337 | print_level_nodes(level); 338 | } 339 | 340 | template 341 | void Binary_Tree::level_order_traversal_spiral() 342 | { 343 | std::deque *> nodes_deque; 344 | nodes_deque.push_back(this); 345 | int level(0), flag(1); 346 | while (!nodes_deque.empty()) 347 | { 348 | int sze(nodes_deque.size()); 349 | std::cout << "Level " << level << ": "; 350 | while (sze--) 351 | { 352 | Binary_Tree *cur; 353 | if (flag) 354 | { 355 | cur = nodes_deque.front(); 356 | nodes_deque.pop_front(); 357 | if (cur->left) 358 | nodes_deque.push_back(cur->left); 359 | if (cur->right) 360 | nodes_deque.push_back(cur->right); 361 | } 362 | else 363 | { 364 | cur = nodes_deque.back(); 365 | nodes_deque.pop_back(); 366 | if (cur->right) 367 | nodes_deque.push_front(cur->right); 368 | if (cur->left) 369 | nodes_deque.push_front(cur->left); 370 | } 371 | std::cout << cur->data << ' '; 372 | } 373 | flag = !flag, ++level; 374 | std::cout << edl; 375 | } 376 | } 377 | 378 | template 379 | bool Binary_Tree::is_complete() 380 | { 381 | std::queue *> nodes_queue; 382 | nodes_queue.push(this); 383 | bool no_more_allowed(false); 384 | while (!nodes_queue.empty()) 385 | { 386 | int sze(nodes_queue.size()); 387 | while (sze--) 388 | { 389 | Binary_Tree *cur(nodes_queue.front()); 390 | nodes_queue.pop(); 391 | if (cur->left) 392 | { 393 | if (no_more_allowed) 394 | return false; 395 | nodes_queue.push(cur->left); 396 | } 397 | else 398 | no_more_allowed = true; 399 | 400 | if (cur->right) 401 | { 402 | if (no_more_allowed) 403 | return false; 404 | nodes_queue.push(cur->right); 405 | } 406 | else 407 | no_more_allowed = true; 408 | } 409 | } 410 | return true; 411 | } 412 | 413 | template 414 | Binary_Tree::Binary_Tree(std::deque &preorder, std::deque &inorder, int inorder_start, int inorder_end) 415 | { 416 | if (inorder_end == -1) 417 | inorder_end = (int)inorder.size() - 1; 418 | data = preorder[0]; 419 | preorder.pop_front(); 420 | for (int split(inorder_start); split <= inorder_end; ++split) 421 | { 422 | if (inorder[split] == data) 423 | { 424 | if (inorder_start < split) 425 | left = new Binary_Tree(preorder, inorder, inorder_start, split - 1); 426 | if (split < inorder_end) 427 | right = new Binary_Tree(preorder, inorder, split + 1, inorder_end); 428 | break; 429 | } 430 | } 431 | } 432 | 433 | template 434 | Binary_Tree::Binary_Tree(std::queue> &preorder_queue) 435 | { 436 | std::pair p(preorder_queue.front()); 437 | preorder_queue.pop(); 438 | data = p.first; 439 | if (!p.second) 440 | { 441 | if (preorder_queue.size()) 442 | left = new Binary_Tree(preorder_queue); 443 | if (preorder_queue.size()) 444 | right = new Binary_Tree(preorder_queue); 445 | } 446 | } 447 | 448 | template 449 | void Binary_Tree::build_preorder(std::queue> &preorder_queue) 450 | { 451 | preorder_queue.push(std::make_pair(data, !left && !right)); 452 | if (left) 453 | left->build_preorder(preorder_queue); 454 | if (right) 455 | right->build_preorder(preorder_queue); 456 | } 457 | 458 | template 459 | void Binary_Tree::print_preorder_complete() 460 | { 461 | std::cout << data << ' '; 462 | if (left) 463 | left->print_preorder_complete(); 464 | else 465 | std::cout << "-1 "; 466 | 467 | if (right) 468 | right->print_preorder_complete(); 469 | else 470 | std::cout << "-1 "; 471 | } 472 | 473 | template 474 | std::string Binary_Tree::to_str(type n) 475 | { 476 | std::ostringstream oss; 477 | oss << n; 478 | return oss.str(); 479 | } 480 | 481 | template 482 | std::string Binary_Tree::parenthesize_0(bool left_first) 483 | { 484 | std::string repr("(" + to_str(data)); 485 | 486 | if (left_first) 487 | { 488 | if (left) 489 | repr += left->parenthesize_0(left_first); 490 | else 491 | repr += "()"; // null: no child 492 | 493 | if (right) 494 | repr += right->parenthesize_0(left_first); 495 | else 496 | repr += "()"; // null: no child 497 | } 498 | else 499 | { 500 | if (right) 501 | repr += right->parenthesize_0(left_first); 502 | else 503 | repr += "()"; // null: no child 504 | 505 | if (left) 506 | repr += left->parenthesize_0(left_first); 507 | else 508 | repr += "()"; // null: no child 509 | } 510 | repr += ")"; 511 | return repr; 512 | } 513 | 514 | template 515 | std::string Binary_Tree::parenthesize_canonical() 516 | { 517 | std::string repr("(" + to_str(data)); 518 | std::vector v; 519 | if (left) 520 | v.push_back(left->parenthesize_canonical()); 521 | else 522 | v.push_back("()"); 523 | 524 | if (right) 525 | v.push_back(right->parenthesize_canonical()); 526 | else 527 | v.push_back("()"); 528 | 529 | sort(v.begin(), v.end()); 530 | 531 | int len((int)v.size()); 532 | 533 | for (int i(0); i < len; ++i) 534 | repr += v[i]; 535 | 536 | repr += ")"; 537 | return repr; 538 | } 539 | 540 | template 541 | bool Binary_Tree::is_mirror(Binary_Tree *first, Binary_Tree *second) 542 | { 543 | if (!first && !second) 544 | return true; 545 | 546 | if (first && second && first->data == second->data) 547 | return is_mirror(first->left, second->right) && 548 | is_mirror(first->right, second->left); 549 | 550 | return false; 551 | } 552 | 553 | template 554 | bool Binary_Tree::is_symmetric() 555 | { 556 | if (!left && !right) 557 | return true; 558 | 559 | if (!left && right || left && !right) 560 | return false; 561 | 562 | return (left->parenthesize_0() == right->parenthesize_0(false)); 563 | // return is_mirror(left, right); 564 | } 565 | 566 | template 567 | bool Binary_Tree::is_flip_equiv_0(Binary_Tree *other) 568 | { 569 | return parenthesize_canonical() == other->parenthesize_canonical(); 570 | } 571 | 572 | template 573 | bool Binary_Tree::is_flip_equiv_1(Binary_Tree *first, Binary_Tree *second) 574 | { 575 | if (!first && !second) 576 | return true; 577 | if (!first || !second) 578 | return false; 579 | if (first->data != second->data) 580 | return false; 581 | bool y, x(is_flip_equiv_1(first->left, second->left) && is_flip_equiv_1(first->right, second->right)); 582 | if (!x) 583 | y(is_flip_equiv_1(first->left, second->right) && is_flip_equiv_1(first->right, second->left)); 584 | return (x || y); 585 | } 586 | 587 | template 588 | std::string Binary_Tree::parenthesize_1(std::vector &all_repres) 589 | { 590 | std::string repr("(" + to_str(data)); 591 | if (left) 592 | repr += left->parenthesize_1(all_repres); 593 | else 594 | repr += "()"; 595 | 596 | if (right) 597 | repr += right->parenthesize_1(all_repres); 598 | else 599 | repr += "()"; 600 | 601 | repr += ")"; 602 | 603 | if (left || right) // nodes > 1 604 | all_repres.push_back(repr); 605 | return repr; 606 | } 607 | 608 | template 609 | void Binary_Tree::print_duplicate_subtrees() 610 | { 611 | std::vector all_repres; 612 | parenthesize_1(all_repres); 613 | 614 | sort(all_repres.begin(), all_repres.end()); 615 | all_repres.push_back("#"); 616 | 617 | int len((int)all_repres.size()); 618 | for (int i(0); i < len;) 619 | { 620 | int j(i + 1); 621 | while (j < len && all_repres[i] == all_repres[j]) 622 | ++j; 623 | if (j > i + 1) 624 | std::cout << all_repres[i] << edl; 625 | i = j; 626 | } 627 | } 628 | #endif --------------------------------------------------------------------------------