├── .gitignore ├── Algorithm ├── binary_search.h ├── bucket_sort.h ├── digraph_algorithm.h ├── graph_algorithm.h ├── heap_sort.h ├── insertion_sort.h ├── merge_sort.h ├── postfix_expression_manager.h ├── quick_sort.h ├── radix_sort.h ├── selection_sort.h ├── shell_sort.h ├── symbol_pair_checker.cpp ├── symbol_pair_checker.h ├── union_find.h ├── weighted_digraph_algorithm.h └── weighted_graph_algorithm.h ├── CMakeLists.txt ├── DataStructures ├── 2_3_tree.h ├── 2_3_tree_node.h ├── avl_tree.h ├── binary_heap.h ├── binary_search_tree.h ├── binary_tree_node.h ├── digraph.h ├── graph.h ├── graph_adj_set.h ├── hash_table.h ├── linked_list.h ├── list_node.h ├── orderly_symbol_table.h ├── polynomial.h ├── polynomial_unit.h ├── priority_queue.h ├── queue.h ├── queue_based_on_array.h ├── red_black_tree.h ├── red_black_tree_node.h ├── stack.h ├── stack_based_on_array.h ├── symbol_table.h ├── symbol_table_elements.h ├── tree_element.h ├── weighted_digraph.h ├── weighted_graph.h └── weighted_graph_adj_set.h ├── README.md ├── Ruby ├── .gitignore ├── LeetCode │ ├── add_two_numbers.rb │ ├── find_smallest_letter_greater_than_target.rb │ ├── longest_palindrome.rb │ ├── minimum_time_difference.rb │ ├── n_queue.rb │ ├── shortest_palindrome.rb │ └── sum.rb └── String │ ├── alphabet.rb │ ├── alphabet_test.rb │ ├── sorting.rb │ └── sorting_test.rb ├── Tests ├── avl_tree.test.h ├── binary_heap.test.h ├── binary_search.test.h ├── binary_search_tree.test.h ├── bucket_sort.test.h ├── digraph.test.h ├── digraph_algorithm.test.h ├── graph.test.h ├── grapha_algorithm.test.h ├── hash_table.test.h ├── heap_sort.test.h ├── insertion_sort.test.h ├── linked_list.test.h ├── list_node.test.h ├── merge_sort.test.h ├── orderly_symbol_table.test.h ├── polynomial.test.h ├── postfix_expression_manager.test.h ├── priority_queue.test.h ├── queue.test.h ├── queue_based_on_array.test.h ├── quick_sort.test.h ├── radix_sort.test.h ├── red_black_tree.test.h ├── selection_sort.test.h ├── shell_sort.test.h ├── stack.test.h ├── stack_based_on_array.test.h ├── symbol_pair_checker.test.h ├── symbol_table.test.h ├── weighted_digraph.test.h ├── weighted_digraph_algorithm.test.h ├── weighted_graph.test.h └── weighted_graph_algorithm.test.h ├── main.cpp ├── main.h ├── optional.hpp ├── requirements.txt └── utils.h /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.o -------------------------------------------------------------------------------- /Algorithm/binary_search.h: -------------------------------------------------------------------------------- 1 | // 2 | // binary_search 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/9. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_BINARY_SEARCH_H 10 | #define ALGORITHM_BINARY_SEARCH_H 11 | 12 | #include 13 | #include 14 | 15 | 16 | namespace my_algorithm { 17 | 18 | // time: O(log(n)) 19 | // space: O(1) 20 | template 21 | int binarySearch(const std::vector& t_vector, const T& element) { 22 | size_t left = 0; 23 | size_t right = t_vector.size() - 1; 24 | size_t middle; 25 | while (true) { 26 | middle = (left + right) / 2; 27 | if (left > right) { 28 | return -1; 29 | } 30 | if (t_vector[middle] == element) { 31 | return (int)middle; 32 | } 33 | if (t_vector[middle] > element) { 34 | right = middle - 1; 35 | } else { 36 | left = middle + 1; 37 | } 38 | } 39 | } 40 | } 41 | 42 | #endif //ALGORITHM_BINARY_SEARCH_H 43 | -------------------------------------------------------------------------------- /Algorithm/bucket_sort.h: -------------------------------------------------------------------------------- 1 | // 2 | // bucket_sort.hpp 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/31. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef bucket_sort_hpp 10 | #define bucket_sort_hpp 11 | 12 | #include 13 | #include 14 | 15 | 16 | namespace my_algorithm { 17 | using std::vector; 18 | 19 | // time: O(t_size + t_max) 20 | // space: O(t_max) 21 | void bucketSort(vector& t_vector, const uint32_t t_max, const bool reverse = false) { 22 | auto bucket = vector(size_t(t_max + 1)); 23 | for (auto &t: t_vector) { 24 | bucket[t] = 1; 25 | } 26 | 27 | uint32_t index = 0; 28 | 29 | if (reverse) { 30 | for (auto i = bucket.size(); i > 0; i--) { 31 | if (bucket[i - 1] == 1) { 32 | t_vector[index] = uint32_t(i - 1); 33 | index++; 34 | } 35 | } 36 | return; 37 | } 38 | 39 | 40 | for (auto i = 0; i < bucket.size(); i++) { 41 | if (bucket[i] == 1) { 42 | t_vector[index] = uint32_t(i); 43 | index++; 44 | } 45 | } 46 | } 47 | } 48 | 49 | 50 | #endif /* bucket_sort_hpp */ 51 | -------------------------------------------------------------------------------- /Algorithm/heap_sort.h: -------------------------------------------------------------------------------- 1 | // 2 | // heap_sort 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/10/28. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_HEAP_SORT_H 10 | #define ALGORITHM_HEAP_SORT_H 11 | 12 | #include 13 | #include 14 | #include "binary_heap.h" 15 | 16 | 17 | namespace my_algorithm { 18 | // time: O(nlog(n)) 19 | // space: O(n) 20 | template 21 | void heapSort(std::vector& t_vector, bool reverse = false) { 22 | auto size = size_t(t_vector.size()); 23 | if (size > Size) { 24 | throw std::out_of_range("Vector's size must be less than heap's."); 25 | } 26 | if (reverse) { 27 | data_structures::MaxBinaryHeap heap; 28 | for (int i = 0; i < size; i++) { 29 | heap.insert(t_vector[i]); 30 | } 31 | for (int i = 0; i < size; i++) { 32 | t_vector[i] = heap.deleteTop(); 33 | } 34 | } else { 35 | data_structures::MinBinaryHeap heap; 36 | for (int i = 0; i < size; i++) { 37 | heap.insert(t_vector[i]); 38 | } 39 | for (int i = 0; i < size; i++) { 40 | t_vector[i] = heap.deleteTop(); 41 | } 42 | } 43 | } 44 | } 45 | 46 | 47 | #endif //ALGORITHM_HEAP_SORT_H 48 | -------------------------------------------------------------------------------- /Algorithm/insertion_sort.h: -------------------------------------------------------------------------------- 1 | // 2 | // insertion_sort 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/11. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_INSERTION_SORT_H 10 | #define ALGORITHM_INSERTION_SORT_H 11 | 12 | #include 13 | #include 14 | 15 | 16 | namespace my_algorithm { 17 | using std::vector; 18 | 19 | // time: O(n) ~ O(n^2) 20 | // space: O(1) 21 | template 22 | void insertionSort(vector& t_vector, const bool reverse = false, const size_t low = 0, const size_t high = 0) { 23 | 24 | auto t_size = high == 0 ? t_vector.size() : high + 1; 25 | size_t end, current; 26 | T tmp; 27 | 28 | for (size_t i = low + 1; i < t_size; i++) { 29 | end = i; 30 | current = end; 31 | tmp = t_vector[end]; 32 | 33 | if (reverse) { 34 | while (current > 0 && t_vector[current - 1] < tmp) { 35 | t_vector[current] = t_vector[current - 1]; 36 | current--; 37 | } 38 | } 39 | else { 40 | while (current > 0 && t_vector[current - 1] > tmp) { 41 | t_vector[current] = t_vector[current - 1]; 42 | current--; 43 | } 44 | } 45 | 46 | t_vector[current] = tmp; 47 | } 48 | } 49 | } 50 | 51 | #endif //ALGORITHM_INSERTION_SORT_H 52 | -------------------------------------------------------------------------------- /Algorithm/merge_sort.h: -------------------------------------------------------------------------------- 1 | // 2 | // merge_sort 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/13. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_MERGE_SORT_H 10 | #define ALGORITHM_MERGE_SORT_H 11 | 12 | #include 13 | #include 14 | 15 | 16 | namespace my_algorithm { 17 | using std::vector; 18 | 19 | // time: O(n * log(n)) 20 | // space: O(Pn) 21 | template 22 | void mergeSort(vector& t_vector, const bool reverse = false) { 23 | auto size = t_vector.size(); 24 | size_t step = 1; 25 | 26 | while (step < size) { 27 | auto tmp = vector(); 28 | 29 | for (size_t begin = 0; begin < size; begin += 2 * step) { 30 | auto middle = (begin + step) > size ? size : (begin + step); 31 | auto end = (middle + step) > size ? size : (middle + step); 32 | 33 | if (middle == end) { 34 | for (auto i = begin; i < end; i++) { 35 | tmp.push_back(t_vector[i]); 36 | } 37 | continue; 38 | } 39 | 40 | if (reverse && t_vector[middle - 1] > t_vector[middle]) { 41 | for (auto i = begin; i < end; i++) { 42 | tmp.push_back(t_vector[i]); 43 | } 44 | continue; 45 | } 46 | 47 | if (!reverse && t_vector[middle - 1] < t_vector[middle]) { 48 | for (auto i = begin; i < end; i++) { 49 | tmp.push_back(t_vector[i]); 50 | } 51 | continue; 52 | } 53 | 54 | auto i1 = begin; 55 | auto i2 = middle; 56 | 57 | while (i1 < middle || i2 < end) { 58 | if (i1 == middle) { 59 | tmp.push_back(t_vector[i2]); 60 | i2++; 61 | } 62 | else if (i2 == end) { 63 | tmp.push_back(t_vector[i1]); 64 | i1++; 65 | } 66 | else if (reverse && t_vector[i1] > t_vector[i2]) { 67 | tmp.push_back(t_vector[i1]); 68 | i1++; 69 | } 70 | else if (!reverse && t_vector[i1] < t_vector[i2]) { 71 | tmp.push_back(t_vector[i1]); 72 | i1++; 73 | } 74 | else { 75 | tmp.push_back(t_vector[i2]); 76 | i2++; 77 | } 78 | } 79 | 80 | } 81 | 82 | t_vector = tmp; 83 | step *= 2; 84 | } 85 | } 86 | } 87 | 88 | #endif //ALGORITHM_MERGE_SORT_H 89 | -------------------------------------------------------------------------------- /Algorithm/postfix_expression_manager.h: -------------------------------------------------------------------------------- 1 | // 2 | // postfix_expression_manager 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/6. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_POSTFIX_EXPRESSION_MANAGER_H 10 | #define ALGORITHM_POSTFIX_EXPRESSION_MANAGER_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "utils.h" 17 | #include "stack.h" 18 | 19 | 20 | namespace my_algorithm { 21 | 22 | template 23 | class PostfixExpressionManager { 24 | 25 | protected: 26 | std::vector> _operators; 27 | data_structures::Stack _stack; 28 | data_structures::Stack _stack_converter; 29 | data_structures::Stack _stack_priority; 30 | std::vector _all_operators; 31 | 32 | public: 33 | PostfixExpressionManager(); 34 | PostfixExpressionManager(const PostfixExpressionManager& manager); 35 | virtual ~PostfixExpressionManager(); 36 | T eval(const std::vector& expression); 37 | std::vector fromInfixExpression(const std::vector& expression); 38 | }; 39 | 40 | 41 | template inline 42 | PostfixExpressionManager::PostfixExpressionManager() { 43 | _stack = data_structures::Stack(); 44 | _stack_converter = data_structures::Stack(); 45 | _stack_priority = data_structures::Stack(); 46 | _all_operators = {}; 47 | _operators = T::operators; 48 | _operators.insert(_operators.begin(), {")"}); 49 | _operators.push_back({"("}); 50 | for (auto &ops: _operators) { 51 | for (auto &op: ops) { 52 | _all_operators.push_back(op); 53 | } 54 | } 55 | } 56 | 57 | template inline 58 | PostfixExpressionManager::PostfixExpressionManager(const PostfixExpressionManager &manager) { 59 | _stack = manager._stack; 60 | _stack_converter = manager._stack_converter; 61 | _stack_priority = manager._stack_priority; 62 | _operators = manager._operators; 63 | _all_operators = manager._all_operators; 64 | } 65 | 66 | template inline 67 | PostfixExpressionManager::~PostfixExpressionManager() {} 68 | 69 | // time: O(N) 70 | // space: O(1) 71 | template inline 72 | T PostfixExpressionManager::eval(const std::vector &expression) { 73 | _stack.clear(); 74 | for (auto &e: expression) { 75 | if (!isInVector(_all_operators, e)) { 76 | _stack.push(T(e)); 77 | continue; 78 | } 79 | _stack.push(_stack.pop().exec(e, _stack.pop())); 80 | } 81 | return _stack.pop(); 82 | } 83 | 84 | // time: O(N) 85 | // space: O(2N) 86 | template inline 87 | std::vector PostfixExpressionManager::fromInfixExpression(const std::vector &expression) { 88 | auto result = std::vector(); 89 | auto result_stack = data_structures::Stack(); 90 | _stack_converter.clear(); 91 | _stack_priority.clear(); 92 | auto max_priority = _operators.size(); 93 | for (auto &e: expression) { 94 | if (!isInVector(_all_operators, e)) { 95 | result_stack.push(e); 96 | continue; 97 | } 98 | for (auto priority = max_priority; priority > 0; priority--) { 99 | if (!isInVector(_operators[priority - 1], e)) { 100 | continue; 101 | } 102 | while (!_stack_converter.isEmpty()) { 103 | if (priority > _stack_priority.top()) { 104 | break; 105 | } 106 | if (_stack_converter.top() == "(" && e == ")") { 107 | _stack_priority.pop(); 108 | _stack_converter.pop(); 109 | break; 110 | } 111 | if (_stack_converter.top() == "(") { 112 | break; 113 | } 114 | result_stack.push(_stack_converter.pop()); 115 | _stack_priority.pop(); 116 | } 117 | if (e != ")") { 118 | _stack_converter.push(e); 119 | _stack_priority.push(priority); 120 | } 121 | } 122 | } 123 | while (!_stack_converter.isEmpty()) { 124 | result_stack.push(_stack_converter.pop()); 125 | } 126 | while (!result_stack.isEmpty()) { 127 | result.insert(result.begin(), result_stack.pop()); 128 | } 129 | return result; 130 | } 131 | 132 | } 133 | 134 | #endif //ALGORITHM_POSTFIX_EXPRESSION_MANAGER_H 135 | -------------------------------------------------------------------------------- /Algorithm/quick_sort.h: -------------------------------------------------------------------------------- 1 | // 2 | // quick_sort 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/14. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_QUICK_SORT_H 10 | #define ALGORITHM_QUICK_SORT_H 11 | 12 | #include 13 | #include 14 | #include "insertion_sort.h" 15 | 16 | 17 | namespace my_algorithm { 18 | using std::vector; 19 | 20 | 21 | template inline 22 | void _swapForQuickSort(vector& t_vector, const size_t i1, const size_t i2) { 23 | T tmp = t_vector[i1]; 24 | t_vector[i1] = t_vector[i2]; 25 | t_vector[i2] = tmp; 26 | } 27 | 28 | // median3, prevent the worst condition 29 | // set the median item to low, and make their three items be sorted 30 | template inline 31 | size_t _median3ForQuickSort(vector& t_vector, const size_t low, const size_t high, const bool reverse) { 32 | auto middle = (high + low) / 2; 33 | if (t_vector[low] < t_vector[middle]) { 34 | _swapForQuickSort(t_vector, low, middle); 35 | } 36 | if (t_vector[middle] > t_vector[high]) { 37 | _swapForQuickSort(t_vector, middle, high); 38 | } 39 | if ((!reverse && t_vector[low] > t_vector[high]) || (reverse && t_vector[low] < t_vector[high])) { 40 | _swapForQuickSort(t_vector, low, high); 41 | } 42 | return middle; 43 | } 44 | 45 | template inline 46 | size_t _partitionForQuickSort(vector& t_vector, const size_t low, const size_t high, const bool reverse = false) { 47 | 48 | auto middle = _median3ForQuickSort(t_vector, low, high, reverse); 49 | 50 | // if the size of elements is less than 3, they are already sorted 51 | // if (high - low < 3) { 52 | // _swapForQuickSort(t_vector, low, middle); 53 | // return middle; 54 | // } 55 | 56 | auto comparable = t_vector[low]; 57 | auto l = low + 1; 58 | auto h = high; 59 | 60 | while (l < h) { 61 | if (reverse) { 62 | while(t_vector[h] < comparable && h > l) { h--; } 63 | while(t_vector[l] >= comparable && l < h) { l++; } 64 | } 65 | else { 66 | while(t_vector[h] > comparable && h > l) { h--; } 67 | while(t_vector[l] <= comparable && l < h) { l++; } 68 | } 69 | _swapForQuickSort(t_vector, l, h); 70 | } 71 | _swapForQuickSort(t_vector, l, low); 72 | return l; 73 | } 74 | 75 | template inline 76 | vector _partitionForQuickSort3Way(vector& t_vector, const size_t low, const size_t high, const bool reverse = false) { 77 | 78 | auto middle = _median3ForQuickSort(t_vector, low, high, reverse); 79 | 80 | // if the size of elements is less than 3, they are already sorted 81 | // if (high - low < 3) { 82 | // _swapForQuickSort(t_vector, low, middle); 83 | // return {low, high}; 84 | // } 85 | 86 | auto comparable = t_vector[low]; 87 | auto l = low; 88 | auto h = high; 89 | auto e = l + 1; 90 | 91 | while (e <= h) { 92 | if ((!reverse && (t_vector[e] < comparable)) || (reverse && (t_vector[e] > comparable))) { 93 | _swapForQuickSort(t_vector, l++, e++); 94 | } 95 | else if ((!reverse && t_vector[e] > comparable) || (reverse && t_vector[e] < comparable)) { 96 | _swapForQuickSort(t_vector, e, h--); 97 | } 98 | else { 99 | e++; 100 | } 101 | } 102 | return {l, h}; 103 | } 104 | 105 | template 106 | void _sortForQuickSort(vector& t_vector, const size_t low, const size_t high, const bool reverse = false) { 107 | if (high <= low) { 108 | return; 109 | } 110 | 111 | // if the size of elements will be sorted is less than 20, we may use insertion sort to make it quicker like this: 112 | if (high - low < 20) { 113 | insertionSort(t_vector, reverse, low, high); 114 | return; 115 | } 116 | 117 | auto middle = _partitionForQuickSort(t_vector, low, high, reverse); 118 | _sortForQuickSort(t_vector, low, middle - 1, reverse); 119 | _sortForQuickSort(t_vector, middle + 1, high, reverse); 120 | } 121 | 122 | template 123 | void _sortForQuickSort3Way(vector& t_vector, const size_t low, const size_t high, const bool reverse = false) { 124 | if (high <= low) { 125 | return; 126 | } 127 | 128 | // if the size of elements will be sorted is less than 20, we may use insertion sort to make it quicker like this: 129 | if (high - low < 20) { 130 | insertionSort(t_vector, reverse, low, high); 131 | return; 132 | } 133 | 134 | // 3way, this method is optimize for vector has many repeated elements 135 | auto lh = _partitionForQuickSort3Way(t_vector, low, high, reverse); 136 | if (lh[0] - low > 1) { 137 | _sortForQuickSort3Way(t_vector, low, lh[0] - 1, reverse); 138 | } 139 | if (high - lh[1] > 1) { 140 | _sortForQuickSort3Way(t_vector, lh[1] + 1, high, reverse); 141 | } 142 | } 143 | 144 | // time: O(n * log(n)) 145 | // space: O(n) 146 | template 147 | void quickSort(vector& t_vector, const bool reverse = false, const bool use3Way = true) { 148 | // randomly all elements in vector, prevent the worst condition 149 | std::random_shuffle(t_vector.begin(), t_vector.end()); 150 | if (use3Way) { 151 | _sortForQuickSort3Way(t_vector, 0, t_vector.size() - 1, reverse); 152 | } 153 | else { 154 | _sortForQuickSort(t_vector, 0, t_vector.size() - 1, reverse); 155 | } 156 | } 157 | } 158 | 159 | #endif //ALGORITHM_QUICK_SORT_H 160 | -------------------------------------------------------------------------------- /Algorithm/radix_sort.h: -------------------------------------------------------------------------------- 1 | // 2 | // bucket_sort.hpp 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/31. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef radix_sort_hpp 10 | #define radix_sort_hpp 11 | 12 | #include 13 | #include 14 | #include 15 | #include "linked_list.h" 16 | 17 | 18 | namespace my_algorithm { 19 | using std::vector; 20 | using data_structures::LinkedList; 21 | 22 | // time: O(t_msd(t_size + t_size)) 23 | // space: O(t_size * t_radix) 24 | void radixSort(vector& t_vector, const uint32_t t_msd, const uint32_t t_radix, const bool reverse = false) { 25 | 26 | for (auto dig = 0; dig < t_msd; dig++) { 27 | auto counts = vector>(size_t(t_radix)); 28 | for (auto &t: t_vector) { 29 | counts[uint32_t(t / pow(t_radix, dig)) % t_radix].insertToTail(t); 30 | } 31 | auto position = 0; 32 | for (auto &count: counts) { 33 | for (auto node = count.begin(); node != count.end(); node = node->next()) { 34 | t_vector[position] = node->element; 35 | position++; 36 | } 37 | } 38 | } 39 | 40 | if (reverse) { 41 | auto tmp = t_vector; 42 | auto size = t_vector.size(); 43 | for (auto i = 0; i < size; i++) { 44 | t_vector[i] = tmp[size - 1 - i]; 45 | } 46 | } 47 | 48 | } 49 | } 50 | 51 | 52 | #endif /* radix_sort_hpp */ 53 | -------------------------------------------------------------------------------- /Algorithm/selection_sort.h: -------------------------------------------------------------------------------- 1 | // 2 | // selection_sort 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/9. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_SELECTION_SORT_H 10 | #define ALGORITHM_SELECTION_SORT_H 11 | 12 | #include 13 | #include 14 | 15 | 16 | namespace my_algorithm { 17 | using std::vector; 18 | 19 | // time: O(n^2) 20 | // space: O(1) 21 | template 22 | void selectionSort(vector& t_vector, const bool reverse = false) { 23 | size_t cursor_current = 0; 24 | auto size = t_vector.size(); 25 | 26 | for (size_t begin = 0; begin < size; begin++) { 27 | cursor_current = begin; 28 | for (size_t i = begin; i < size; i++) { 29 | 30 | if (reverse) { 31 | if (t_vector[i] > t_vector[cursor_current]) { 32 | cursor_current = i; 33 | } 34 | continue; 35 | } 36 | 37 | if (t_vector[i] < t_vector[cursor_current]) { 38 | cursor_current = i; 39 | } 40 | 41 | } 42 | 43 | auto tmp = t_vector[begin]; 44 | t_vector[begin] = t_vector[cursor_current]; 45 | t_vector[cursor_current] = tmp; 46 | } 47 | } 48 | } 49 | 50 | #endif //ALGORITHM_SELECTION_SORT_H 51 | -------------------------------------------------------------------------------- /Algorithm/shell_sort.h: -------------------------------------------------------------------------------- 1 | // 2 | // shell_sort 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/13. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_SHELL_SORT_H 10 | #define ALGORITHM_SHELL_SORT_H 11 | 12 | #include 13 | #include 14 | 15 | 16 | namespace my_algorithm { 17 | using std::vector; 18 | 19 | // time: ...... 20 | // space: O(1) 21 | template 22 | void shellSort(vector& t_vector, const vector& step_queue, const bool reverse = false) { 23 | auto size = t_vector.size(); 24 | size_t current = 0; 25 | T tmp; 26 | 27 | for (auto step: step_queue) { 28 | 29 | for (size_t start = 0; start < step; start++) { 30 | 31 | for (auto end = 1 * step + start; end < size; end += step) { 32 | tmp = t_vector[end]; 33 | current = end; 34 | 35 | if (reverse) { 36 | while (current > start && t_vector[current - step] < tmp) { 37 | t_vector[current] = t_vector[current - step]; 38 | current -= step; 39 | } 40 | } 41 | else { 42 | while (current > start && t_vector[current - step] > tmp) { 43 | t_vector[current] = t_vector[current - step]; 44 | current -= step; 45 | } 46 | } 47 | 48 | t_vector[current] = tmp; 49 | } 50 | } 51 | } 52 | } 53 | } 54 | 55 | #endif //ALGORITHM_SHELL_SORT_H 56 | -------------------------------------------------------------------------------- /Algorithm/symbol_pair_checker.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // symbol_pair_checker 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/6. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include "symbol_pair_checker.h" 10 | 11 | 12 | namespace my_algorithm { 13 | SymbolPairChecker::SymbolPairChecker() { 14 | _cursor = 0; 15 | _open_symbols = std::string(); 16 | _close_symbols = std::string(); 17 | _stack = data_structures::Stack(); 18 | } 19 | 20 | SymbolPairChecker::SymbolPairChecker(const SymbolPairChecker& checker) { 21 | _cursor = checker._cursor; 22 | _open_symbols = checker._open_symbols; 23 | _close_symbols = checker._close_symbols; 24 | _stack = checker._stack; 25 | } 26 | 27 | SymbolPairChecker::SymbolPairChecker(const std::vector& symbol_pairs) { 28 | _cursor = 0; 29 | _open_symbols = std::string(); 30 | _close_symbols = std::string(); 31 | setSymbolPairs(symbol_pairs); 32 | _stack = data_structures::Stack(); 33 | } 34 | 35 | SymbolPairChecker::~SymbolPairChecker() {} 36 | 37 | SymbolPairChecker& SymbolPairChecker::operator=(const SymbolPairChecker &checker) { 38 | _cursor = checker._cursor; 39 | _open_symbols = checker._open_symbols; 40 | _close_symbols = checker._close_symbols; 41 | _stack = data_structures::Stack(); 42 | return *this; 43 | } 44 | 45 | void SymbolPairChecker::setSymbolPairs(const std::vector &symbol_pairs) { 46 | for (auto &pair: symbol_pairs) { 47 | _open_symbols += pair[0]; 48 | _close_symbols += pair[1]; 49 | } 50 | } 51 | 52 | // online, O(n) 53 | bool SymbolPairChecker::check(const std::string &str) { 54 | _cursor = 0; 55 | _stack.clear(); 56 | auto size = str.size(); 57 | for (uint32_t i = 0; i < size; i++) { 58 | _cursor = i; 59 | auto s = str[i]; 60 | auto _close_position = _close_symbols.find(s); 61 | auto _open_position = _open_symbols.find(s); 62 | // normal characters 63 | if (_close_position == std::string::npos && _open_position == std::string::npos) { 64 | continue; 65 | } 66 | // open symbol is equal close symbol, like '', "" ...... 67 | if (_open_position != std::string::npos && _close_position != std::string::npos) { 68 | if(_stack.isEmpty()) { 69 | _stack.push(s); 70 | continue; 71 | } 72 | if (s != _close_symbols[_open_symbols.find(_stack.top())]) { 73 | _stack.push(s); 74 | continue; 75 | } 76 | } 77 | if (_close_position != std::string::npos) { 78 | if(_stack.isEmpty()) { 79 | return false; 80 | } 81 | if (s != _close_symbols[_open_symbols.find(_stack.pop())]) { 82 | return false; 83 | } 84 | continue; 85 | } 86 | _stack.push(s); 87 | } 88 | return _stack.isEmpty(); 89 | } 90 | 91 | uint32_t SymbolPairChecker::position() { 92 | return _cursor; 93 | } 94 | } -------------------------------------------------------------------------------- /Algorithm/symbol_pair_checker.h: -------------------------------------------------------------------------------- 1 | // 2 | // symbol_pair_checker 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/6. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_SYMBOL_PAIR_CHECKER_H 10 | #define ALGORITHM_SYMBOL_PAIR_CHECKER_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include "stack.h" 16 | 17 | 18 | namespace my_algorithm { 19 | class SymbolPairChecker { 20 | 21 | protected: 22 | uint32_t _cursor; 23 | std::string _open_symbols; 24 | std::string _close_symbols; 25 | data_structures::Stack _stack; 26 | 27 | public: 28 | SymbolPairChecker(); 29 | SymbolPairChecker(const SymbolPairChecker& checker); 30 | SymbolPairChecker(const std::vector& symbol_pairs); 31 | virtual ~SymbolPairChecker(); 32 | SymbolPairChecker& operator=(const SymbolPairChecker& checker); 33 | void setSymbolPairs(const std::vector& symbol_pairs); 34 | bool check(const std::string& str); 35 | uint32_t position(); 36 | }; 37 | 38 | } 39 | 40 | 41 | #endif //ALGORITHM_SYMBOL_PAIR_CHECKER_H 42 | -------------------------------------------------------------------------------- /Algorithm/union_find.h: -------------------------------------------------------------------------------- 1 | // 2 | // union_find 3 | // Algorithm 4 | // 5 | // Created by dtysky on 2017/2/27. 6 | // Copyright © 2017 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_UNION_FIND_H 10 | #define ALGORITHM_UNION_FIND_H 11 | 12 | #include 13 | #include "red_black_tree.h" 14 | #include "optional.hpp" 15 | 16 | 17 | namespace my_algorithm { 18 | using std::experimental::optional; 19 | 20 | template 21 | class UnionFind { 22 | protected: 23 | size_t _count; 24 | size_t _max_id; 25 | data_structures::RBTree _table; 26 | public: 27 | UnionFind(); 28 | UnionFind(const UnionFind& uf); 29 | virtual ~UnionFind(); 30 | size_t count(); 31 | bool connected(T v, T w); 32 | optional id(T v); 33 | void un(T v, T w); 34 | friend std::ostream &operator<<(std::ostream &out, UnionFind &uf) { 35 | auto nodes = uf._table.getAllNodes(); 36 | for (auto &node: nodes) { 37 | out << node->element.key << " " << node->element.value << std::endl; 38 | } 39 | return out; 40 | } 41 | }; 42 | 43 | template inline 44 | UnionFind::UnionFind() { 45 | _max_id = 0; 46 | _count = 0; 47 | _table.clear(); 48 | } 49 | 50 | template inline 51 | UnionFind::UnionFind(const UnionFind& uf) { 52 | _max_id = uf._max_id; 53 | _count = uf._count; 54 | _table = uf._table; 55 | } 56 | 57 | template inline 58 | UnionFind::~UnionFind() {} 59 | 60 | template inline 61 | size_t UnionFind::count() { 62 | return _count; 63 | } 64 | 65 | template inline 66 | bool UnionFind::connected(T v, T w) { 67 | auto id_v = id(v); 68 | auto id_w = id(w); 69 | if (id_v && id_w) { 70 | return id_v == id_w; 71 | } 72 | return false; 73 | } 74 | 75 | template inline 76 | optional UnionFind::id(T v) { 77 | try { 78 | return _table.get(v); 79 | } catch (std::out_of_range) { 80 | return optional(); 81 | } 82 | } 83 | 84 | template inline 85 | void UnionFind::un(T v, T w) { 86 | auto id_v = id(v); 87 | auto id_w = id(w); 88 | if (id_v && id_w) { 89 | // wait for completing 90 | auto nodes = _table.getAllNodes(); 91 | if (id_v > id_w) { 92 | for (auto &node: nodes) { 93 | if (node->element.value == id_w) { 94 | node->element.value = id_v.value(); 95 | } 96 | } 97 | } else { 98 | for (auto &node: nodes) { 99 | if (node->element.value == id_v) { 100 | node->element.value = id_w.value(); 101 | } 102 | } 103 | } 104 | } else if (id_v) { 105 | _table.set(w, id_v.value()); 106 | } else if (id_w) { 107 | _table.set(v, id_w.value()); 108 | } else { 109 | _max_id++; 110 | _table.set(v, _max_id); 111 | _table.set(w, _max_id); 112 | _count++; 113 | } 114 | } 115 | } 116 | 117 | #endif //ALGORITHM_UNION_FIND_H 118 | -------------------------------------------------------------------------------- /Algorithm/weighted_graph_algorithm.h: -------------------------------------------------------------------------------- 1 | // 2 | // weighted_graph_algorithm 3 | // Algorithm 4 | // 5 | // Created by dtysky on 2017/2/26. 6 | // Copyright © 2017 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_WEIGHTED_GRAPH_ALGORITHM_H 10 | #define ALGORITHM_WEIGHTED_GRAPH_ALGORITHM_H 11 | 12 | #include 13 | #include "weighted_graph.h" 14 | #include "priority_queue.h" 15 | #include "union_find.h" 16 | 17 | 18 | namespace my_algorithm { 19 | using data_structures::WeightedGraph; 20 | using data_structures::WeightedGraphEdge; 21 | using data_structures::WeightedGraphAdjSet; 22 | using data_structures::TreeElement; 23 | using data_structures::RBTreeNode; 24 | using data_structures::SymbolTable; 25 | using data_structures::PriorityQueue; 26 | 27 | // only works on connected graph 28 | template 29 | class WeightedGraphMSTPrim { 30 | typedef RBTreeNode>> Node; 31 | typedef WeightedGraphEdge Edge; 32 | protected: 33 | std::vector _marked_nodes; 34 | PriorityQueue _edges_queue; 35 | std::vector _tree; 36 | Weight _weight; 37 | void _visit(Node* vertex) { 38 | _marked_nodes.push_back(vertex); 39 | auto adj_edges = vertex->element.value.adjEdges(); 40 | for (auto &e: adj_edges) { 41 | if (isInVector(_marked_nodes, e.to)) { 42 | continue; 43 | } 44 | _edges_queue.enqueue(e); 45 | } 46 | } 47 | 48 | public: 49 | WeightedGraphMSTPrim(WeightedGraph& graph) { 50 | _marked_nodes.clear(); 51 | _edges_queue.clear(); 52 | auto count = 0; 53 | auto size = graph.vertexCount() - 1; 54 | _visit(graph.rootNode()); 55 | while (!_edges_queue.isEmpty()) { 56 | auto edge = _edges_queue.dequeueMinN(); 57 | auto markedFrom = isInVector(_marked_nodes, edge.from); 58 | auto markedTo = isInVector(_marked_nodes, edge.to); 59 | if (markedFrom && markedTo) { 60 | continue; 61 | } 62 | _tree.push_back(edge); 63 | count++; 64 | _weight += edge.weight; 65 | if (count == size) { 66 | return; 67 | } 68 | if (!markedFrom) { 69 | _visit(edge.from); 70 | } 71 | if (!markedTo) { 72 | _visit(edge.to); 73 | } 74 | } 75 | } 76 | std::vector edges() { 77 | return _tree; 78 | } 79 | Weight weight() { 80 | return _weight; 81 | } 82 | }; 83 | 84 | // only works on connected graph 85 | template 86 | class WeightedGraphMSTKruskal { 87 | typedef RBTreeNode>> Node; 88 | typedef WeightedGraphEdge Edge; 89 | protected: 90 | UnionFind _uf; 91 | PriorityQueue _edges_queue; 92 | std::vector _tree; 93 | Weight _weight; 94 | 95 | public: 96 | WeightedGraphMSTKruskal(WeightedGraph& graph) { 97 | _uf = UnionFind(); 98 | _edges_queue = graph.getSortedEdges(); 99 | auto count = 0; 100 | auto size = graph.vertexCount() - 1; 101 | while (!_edges_queue.isEmpty()) { 102 | auto edge = _edges_queue.dequeueMinN(); 103 | if (_uf.connected(edge.from, edge.to)) { 104 | continue; 105 | } 106 | _tree.push_back(edge); 107 | count++; 108 | _weight += edge.weight; 109 | if (count == size) { 110 | return; 111 | } 112 | _uf.un(edge.from, edge.to); 113 | } 114 | } 115 | std::vector edges() { 116 | return _tree; 117 | } 118 | Weight weight() { 119 | return _weight; 120 | } 121 | }; 122 | } 123 | 124 | #endif //ALGORITHM_WEIGHTED_GRAPH_ALGORITHM_H 125 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.6) 2 | project(Algorithm) 3 | 4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") 5 | 6 | #add_library(. DataStructures inked_list.hpp) 7 | 8 | include_directories( 9 | ${PROJECT_SOURCE_DIR} 10 | ${PROJECT_SOURCE_DIR}/DataStructures 11 | ${PROJECT_SOURCE_DIR}/Algorithm 12 | ${PROJECT_SOURCE_DIR}/Tests) 13 | 14 | set(SOURCE_FILES 15 | Algorithm/bucket_sort.h 16 | Algorithm/radix_sort.h 17 | DataStructures/linked_list.h 18 | DataStructures/list_node.h 19 | DataStructures/polynomial.h 20 | DataStructures/polynomial_unit.h 21 | Tests/bucket_sort.test.h 22 | Tests/linked_list.test.h 23 | Tests/list_node.test.h 24 | Tests/polynomial.test.h 25 | Tests/radix_sort.test.h 26 | main.cpp 27 | main.h 28 | utils.h 29 | optional.hpp 30 | DataStructures/stack.h Tests/stack.test.h Algorithm/symbol_pair_checker.cpp Algorithm/symbol_pair_checker.h Tests/symbol_pair_checker.test.h Algorithm/postfix_expression_manager.h Tests/postfix_expression_manager.test.h DataStructures/queue.h Tests/queue.test.h DataStructures/queue_based_on_array.h Tests/queue_based_on_array.test.h Algorithm/binary_search.h Algorithm/selection_sort.h Tests/selection_sort.test.h Algorithm/insertion_sort.h Tests/insertion_sort.test.h Algorithm/shell_sort.h Tests/shell_sort.test.h Algorithm/merge_sort.h Tests/merge_sort.test.h Algorithm/quick_sort.h Tests/quick_sort.test.h DataStructures/priority_queue.h Tests/priority_queue.test.h DataStructures/binary_heap.h Algorithm/heap_sort.h DataStructures/symbol_table.h DataStructures/symbol_table_elements.h DataStructures/tree_element.h DataStructures/2_3_tree.h DataStructures/binary_tree_node.h DataStructures/2_3_tree_node.h DataStructures/red_black_tree.h DataStructures/red_black_tree_node.h Tests/red_black_tree.test.h DataStructures/avl_tree.h Tests/avl_tree.test.h DataStructures/hash_table.h Tests/hash_table.test.h DataStructures/graph.h DataStructures/graph_adj_set.h Tests/graph.test.h Algorithm/graph_algorithm.h Tests/grapha_algorithm.test.h DataStructures/digraph.h Tests/digraph.test.h Algorithm/digraph_algorithm.h Tests/digraph_algorithm.test.h DataStructures/weighted_graph_adj_set.h DataStructures/weighted_graph.h Tests/weighted_graph.test.h Algorithm/weighted_graph_algorithm.h Tests/weighted_graph_algorithm.test.h Algorithm/union_find.h DataStructures/weighted_digraph.h Tests/weighted_digraph.test.h Algorithm/weighted_digraph_algorithm.h Tests/weighted_digraph_algorithm.test.h) 31 | 32 | add_executable(Algorithm ${SOURCE_FILES}) 33 | -------------------------------------------------------------------------------- /DataStructures/binary_tree_node.h: -------------------------------------------------------------------------------- 1 | // 2 | // binary_tree_node 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/11/30. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_BINARY_TREE_NODE_H 10 | #define ALGORITHM_BINARY_TREE_NODE_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | namespace data_structures { 19 | template 20 | class BinaryTreeNode { 21 | protected: 22 | BinaryTreeNode *_left, *_right, *_parent; 23 | bool _is_left; 24 | void _init(); 25 | void _copy(const BinaryTreeNode &node); 26 | 27 | public: 28 | T element; 29 | size_t node_count; 30 | int b_factor; 31 | BinaryTreeNode(); 32 | BinaryTreeNode(const T &element); 33 | BinaryTreeNode(const BinaryTreeNode &node); 34 | virtual ~BinaryTreeNode(); 35 | bool isLeft(); 36 | BinaryTreeNode *initRoot(); 37 | BinaryTreeNode * insertLeft(BinaryTreeNode *node); 38 | BinaryTreeNode * insertRight(BinaryTreeNode *node); 39 | BinaryTreeNode *deleteLeft(); 40 | BinaryTreeNode *deleteRight(); 41 | BinaryTreeNode *left(); 42 | BinaryTreeNode *right(); 43 | BinaryTreeNode *parent(); 44 | std::string toString(); 45 | BinaryTreeNode& operator=(const BinaryTreeNode &node); 46 | bool operator==(const BinaryTreeNode &node); 47 | bool operator!=(const BinaryTreeNode &node); 48 | friend std::ostream &operator<<(std::ostream &out, const BinaryTreeNode &node) { 49 | out << "Current: " << &node << ", Element: " << node.element << ", Parent: " << node._parent 50 | << ", Left: " << node._left << ", Right: " << node._right << ", IsLeft: " << node._is_left; 51 | return out; 52 | } 53 | }; 54 | 55 | template inline 56 | void BinaryTreeNode::_init() { 57 | _left = nullptr; 58 | _right = nullptr; 59 | _parent = nullptr; 60 | element = T(); 61 | node_count = 1; 62 | _is_left = false; 63 | b_factor = 0; 64 | } 65 | 66 | template inline 67 | void BinaryTreeNode::_copy(const BinaryTreeNode &node){ 68 | element = node.element; 69 | _left = node._left; 70 | _right = node._right; 71 | _parent = node._parent; 72 | node_count = 1; 73 | _is_left = false; 74 | b_factor = 0; 75 | } 76 | 77 | template inline 78 | BinaryTreeNode::BinaryTreeNode(){ 79 | _init(); 80 | } 81 | 82 | template inline 83 | BinaryTreeNode::BinaryTreeNode(const T& element){ 84 | _init(); 85 | this->element = element; 86 | } 87 | 88 | template inline 89 | BinaryTreeNode::BinaryTreeNode(const BinaryTreeNode& node){ 90 | _copy(node); 91 | } 92 | 93 | template inline 94 | BinaryTreeNode::~BinaryTreeNode(){ 95 | _init(); 96 | } 97 | 98 | template inline 99 | BinaryTreeNode& BinaryTreeNode::operator=(const BinaryTreeNode& node){ 100 | _copy(node); 101 | return *this; 102 | } 103 | 104 | template inline 105 | bool BinaryTreeNode::operator==(const BinaryTreeNode& node){ 106 | return (element == node.element) && (_parent == node._parent) && (_left == node._left); 107 | } 108 | 109 | template inline 110 | bool BinaryTreeNode::operator!=(const BinaryTreeNode& node){ 111 | return !(*this == node); 112 | } 113 | 114 | template inline 115 | bool BinaryTreeNode::isLeft(){ 116 | return _is_left; 117 | } 118 | 119 | template inline 120 | BinaryTreeNode* BinaryTreeNode::initRoot(){ 121 | _parent = nullptr; 122 | _is_left = false; 123 | return this; 124 | } 125 | 126 | template inline 127 | BinaryTreeNode * BinaryTreeNode::insertLeft(BinaryTreeNode *node){ 128 | BinaryTreeNode* temp_node = _left; 129 | if (node != nullptr) { 130 | node->_parent = this; 131 | node->_is_left = true; 132 | } 133 | _left = node; 134 | return temp_node; 135 | } 136 | 137 | template inline 138 | BinaryTreeNode * BinaryTreeNode::insertRight(BinaryTreeNode *node){ 139 | BinaryTreeNode* temp_node = _right; 140 | if (node != nullptr) { 141 | node->_parent = this; 142 | node->_is_left = false; 143 | } 144 | _right = node; 145 | return temp_node; 146 | } 147 | 148 | template inline 149 | BinaryTreeNode* BinaryTreeNode::deleteLeft(){ 150 | BinaryTreeNode* temp_node = _left; 151 | _left = nullptr; 152 | return temp_node; 153 | } 154 | 155 | template inline 156 | BinaryTreeNode* BinaryTreeNode::deleteRight(){ 157 | BinaryTreeNode* temp_node = _right; 158 | _right = nullptr; 159 | return temp_node; 160 | } 161 | 162 | template inline 163 | BinaryTreeNode* BinaryTreeNode::left(){ 164 | return _left; 165 | } 166 | 167 | template inline 168 | BinaryTreeNode* BinaryTreeNode::right(){ 169 | return _right; 170 | } 171 | 172 | template inline 173 | BinaryTreeNode* BinaryTreeNode::parent(){ 174 | return _parent; 175 | } 176 | 177 | template inline 178 | std::string BinaryTreeNode::toString(){ 179 | std::ostringstream ss; 180 | if (b_factor == 0) { 181 | ss << element << "(" << node_count << ")"; 182 | } else { 183 | ss << element << "(" << node_count << "," << b_factor << ")"; 184 | } 185 | return ss.str(); 186 | } 187 | } 188 | 189 | #endif //ALGORITHM_BINARY_TREE_NODE_H 190 | -------------------------------------------------------------------------------- /DataStructures/digraph.h: -------------------------------------------------------------------------------- 1 | // 2 | // digraph 3 | // Algorithm 4 | // 5 | // Created by dtysky on 2017/2/18. 6 | // Copyright © 2017 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_DIGRAPH_H 10 | #define ALGORITHM_DIGRAPH_H 11 | 12 | #include 13 | #include 14 | #include "graph.h" 15 | 16 | 17 | namespace data_structures { 18 | template 19 | class Digraph: public Graph { 20 | public: 21 | Digraph(): Graph() {}; 22 | Digraph(Digraph &graph): Graph(graph) {}; 23 | virtual ~Digraph(); 24 | Digraph& addEdge(const T& v, const T& w); 25 | Digraph& deleteEdge(const T& v, const T& w); 26 | void reverse(Digraph& res_graph); 27 | friend std::ostream &operator<<(std::ostream &out, Digraph &graph) { 28 | auto nodes = graph._tree.getAllNodes(); 29 | for (auto node: nodes) { 30 | out << node->element.key << ": "; 31 | for (auto &v: node->element.value.adjVertex()) { 32 | out << v << " "; 33 | } 34 | out << std::endl; 35 | } 36 | return out; 37 | } 38 | }; 39 | 40 | template inline 41 | Digraph::~Digraph() {} 42 | 43 | template inline 44 | Digraph& Digraph::addEdge(const T& v, const T& w){ 45 | auto vp = this->_tree.getNode(v); 46 | auto wp = this->_tree.getNode(w); 47 | if (vp->element.value.addEdge(wp)) { 48 | this->_edge_count++; 49 | } 50 | return *this; 51 | } 52 | 53 | template inline 54 | Digraph& Digraph::deleteEdge(const T& v, const T& w){ 55 | auto vp = this->_tree.getNode(v); 56 | auto wp = this->_tree.getNode(w); 57 | if (vp->element.value.deleteEdge(wp)) { 58 | this->_edge_count--; 59 | } 60 | return *this; 61 | } 62 | 63 | template inline 64 | void Digraph::reverse(Digraph& res_graph){ 65 | res_graph.clear(); 66 | auto nodes = this->_tree.getAllNodes(); 67 | for (auto &node: nodes) { 68 | res_graph.addVertex(node->element.key); 69 | } 70 | for (auto &node: nodes) { 71 | auto adj_set = node->element.value.adjVertexNodes(); 72 | for (auto &v: adj_set) { 73 | res_graph.addEdge(v->element.key, node->element.key); 74 | } 75 | } 76 | } 77 | } 78 | 79 | 80 | #endif //ALGORITHM_DIGRAPH_H 81 | -------------------------------------------------------------------------------- /DataStructures/graph_adj_set.h: -------------------------------------------------------------------------------- 1 | // 2 | // graph_adj_set 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/12/14. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_GRAPH_ADJ_SET_H 10 | #define ALGORITHM_GRAPH_ADJ_SET_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include "symbol_table.h" 16 | #include "red_black_tree_node.h" 17 | #include "tree_element.h" 18 | 19 | 20 | namespace data_structures { 21 | template 22 | class GraphAdjSet { 23 | typedef RBTreeNode>> Node; 24 | protected: 25 | SymbolTable _table; 26 | public: 27 | GraphAdjSet(); 28 | GraphAdjSet(const GraphAdjSet &set); 29 | virtual ~GraphAdjSet(); 30 | std::vector adjVertex(); 31 | std::vector>>*> adjVertexNodes(); 32 | size_t degree(); 33 | bool addEdge(Node *node); 34 | bool deleteEdge(Node *node); 35 | bool hasEdge(Node *node); 36 | GraphAdjSet& operator=(const GraphAdjSet &set); 37 | bool operator==(GraphAdjSet &set); 38 | bool operator!=(GraphAdjSet &set); 39 | friend std::ostream &operator<<(std::ostream &out, const GraphAdjSet &set) { 40 | out << set._table; 41 | return out; 42 | } 43 | }; 44 | 45 | template inline 46 | GraphAdjSet::GraphAdjSet(){ 47 | _table = SymbolTable(); 48 | } 49 | 50 | template inline 51 | GraphAdjSet::GraphAdjSet(const GraphAdjSet& set){ 52 | _table = set._table; 53 | } 54 | 55 | template inline 56 | GraphAdjSet::~GraphAdjSet(){} 57 | 58 | template inline 59 | GraphAdjSet& GraphAdjSet::operator=(const GraphAdjSet& set){ 60 | _table = set._table; 61 | return *this; 62 | } 63 | 64 | template inline 65 | bool GraphAdjSet::operator==(GraphAdjSet& set){ 66 | auto size = _table.size(); 67 | if (size != set._table.size()) { 68 | return false; 69 | } 70 | auto values1 = _table.values(); 71 | auto values2 = set._table.values(); 72 | for (size_t i = 0; i < size; i++) { 73 | if (values1[i] != values2[i]) { 74 | return false; 75 | } 76 | } 77 | return true; 78 | } 79 | 80 | template inline 81 | bool GraphAdjSet::operator!=(GraphAdjSet& set){ 82 | return !(*this == set); 83 | } 84 | 85 | template inline 86 | std::vector GraphAdjSet::adjVertex(){ 87 | return _table.values(); 88 | } 89 | 90 | template inline 91 | std::vector>>*> GraphAdjSet::adjVertexNodes(){ 92 | return _table.keys(); 93 | } 94 | 95 | template inline 96 | size_t GraphAdjSet::degree(){ 97 | return _table.size(); 98 | } 99 | 100 | template inline 101 | bool GraphAdjSet::addEdge(Node *node){ 102 | auto size = _table.size(); 103 | _table.set(node, node->element.key); 104 | return size != _table.size(); 105 | } 106 | 107 | template inline 108 | bool GraphAdjSet::deleteEdge(Node *node){ 109 | auto size = _table.size(); 110 | _table.del(node); 111 | return size != _table.size(); 112 | } 113 | 114 | template inline 115 | bool GraphAdjSet::hasEdge(Node *node){ 116 | return _table.has(node); 117 | } 118 | } 119 | 120 | 121 | #endif //ALGORITHM_GRAPH_ADJ_SET_H 122 | -------------------------------------------------------------------------------- /DataStructures/hash_table.h: -------------------------------------------------------------------------------- 1 | // 2 | // hash_table 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/12/12. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_HASH_TABLE_H 10 | #define ALGORITHM_HASH_TABLE_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "symbol_table.h" 18 | #include "symbol_table_elements.h" 19 | #include "linked_list.h" 20 | 21 | 22 | namespace data_structures { 23 | template 24 | class HashTable { 25 | protected: 26 | std::array, Radix> _array; 27 | size_t _size; 28 | std::hash _calculator; 29 | public: 30 | HashTable(); 31 | virtual ~HashTable(); 32 | HashTable(const HashTable &table); 33 | HashTable& operator=(const HashTable &table); 34 | bool operator==(const HashTable& table); 35 | bool operator!=(const HashTable& table); 36 | bool isEmpty(); 37 | size_t size(); 38 | HashTable& clear(); 39 | HashTable& set(const Key& key, const Value& value); 40 | Value get(const Key& key); 41 | Value del(const Key& key); 42 | std::vector keys(); 43 | std::vector> elements(); 44 | friend std::ostream &operator<<(std::ostream& out, HashTable& table) { 45 | out << "{" << std::endl; 46 | auto elements = table.elements(); 47 | for (auto &e: elements) { 48 | out << " " << e.key << ": " << e.value << std::endl; 49 | } 50 | out << "}" << std::endl; 51 | return out; 52 | }; 53 | }; 54 | 55 | template inline 56 | HashTable::HashTable() { 57 | _array = std::array, Radix>(); 58 | _size = 0; 59 | } 60 | 61 | template inline 62 | HashTable::~HashTable() {} 63 | 64 | template inline 65 | HashTable::HashTable(const HashTable &table){ 66 | _array = table._array; 67 | _size = table._size; 68 | } 69 | 70 | template inline 71 | HashTable& HashTable::operator=(const HashTable &table){ 72 | _array = table._array; 73 | _size = table._size; 74 | } 75 | 76 | template inline 77 | bool HashTable::operator==(const HashTable &table){ 78 | for (size_t i = 0; i < Radix; i++) { 79 | if (_array[i] != table._array[i]) { 80 | return false; 81 | } 82 | } 83 | return true; 84 | } 85 | 86 | template inline 87 | bool HashTable::operator!=(const HashTable &table){ 88 | for (size_t i = 0; i < Radix; i++) { 89 | if (_array[i] != table._array[i]) { 90 | return true; 91 | } 92 | } 93 | return false; 94 | } 95 | 96 | template inline 97 | bool HashTable::isEmpty(){ 98 | return _size == 0; 99 | } 100 | 101 | template inline 102 | size_t HashTable::size(){ 103 | return _size; 104 | } 105 | 106 | template inline 107 | HashTable& HashTable::clear(){ 108 | if (isEmpty()) { 109 | return *this; 110 | } 111 | for (auto &table : _array) { 112 | table.clear(); 113 | _size = 0; 114 | } 115 | } 116 | 117 | template inline 118 | HashTable& HashTable::set(const Key &key, const Value &value){ 119 | auto hash = _calculator(key) % Radix; 120 | auto size = _array[hash].size(); 121 | if (_array[hash].set(key, value).size() != size) { 122 | _size++; 123 | } 124 | return *this; 125 | } 126 | 127 | template inline 128 | Value HashTable::get(const Key &key){ 129 | auto hash = _calculator(key) % Radix; 130 | return _array[hash].get(key); 131 | } 132 | 133 | template inline 134 | Value HashTable::del(const Key &key){ 135 | auto hash = _calculator(key) % Radix; 136 | auto size = _array[hash].size(); 137 | auto result = _array[hash].del(key); 138 | if (_array[hash].size() != size) { 139 | _size--; 140 | } 141 | return result; 142 | } 143 | 144 | template inline 145 | std::vector HashTable::keys(){ 146 | auto keys = std::vector(); 147 | for (auto &table: _array) { 148 | auto keys2 = table.keys(); 149 | keys.insert(keys.end(), keys2.begin(), keys2.end()); 150 | } 151 | return keys; 152 | } 153 | 154 | template inline 155 | std::vector> HashTable::elements(){ 156 | auto elements = std::vector>(); 157 | for (auto &table: _array) { 158 | auto elements2 = table.elements(); 159 | elements.insert(elements.end(), elements2.begin(), elements2.end()); 160 | } 161 | return elements; 162 | } 163 | } 164 | 165 | 166 | #endif //ALGORITHM_HASH_TABLE_H 167 | -------------------------------------------------------------------------------- /DataStructures/list_node.h: -------------------------------------------------------------------------------- 1 | // 2 | // list_node.hpp 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/22. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef list_node_hpp 10 | #define list_node_hpp 11 | 12 | #include 13 | #include 14 | 15 | 16 | namespace data_structures { 17 | using std::cout; 18 | using std::ostream; 19 | 20 | template 21 | class ListNode{ 22 | 23 | private: 24 | ListNode* _next; 25 | 26 | public: 27 | T element; 28 | ListNode(); 29 | ListNode(const T& element, ListNode* next_node = nullptr); 30 | ListNode(const ListNode& node); 31 | virtual ~ListNode(); 32 | void insertAfter(ListNode* node); 33 | ListNode* deleteAfter(); 34 | ListNode* next(); 35 | ListNode& operator=(const ListNode& node); 36 | bool operator==(const ListNode& node) const; 37 | bool operator!=(const ListNode& node) const; 38 | friend ostream& operator<<(ostream& out, const ListNode& node){ 39 | out << "Current: " << &node << ", Element: " << node.element << ", Next: " << node._next; 40 | return out; 41 | } 42 | }; 43 | 44 | 45 | template inline 46 | ListNode::ListNode(){ 47 | _next = nullptr; 48 | element = T(); 49 | } 50 | 51 | template inline 52 | ListNode::ListNode(const T& element, ListNode* next_node){ 53 | this->element = element; 54 | _next = next_node; 55 | } 56 | 57 | template inline 58 | ListNode::ListNode(const ListNode& node){ 59 | this->element = node.element; 60 | _next = node._next; 61 | } 62 | 63 | template inline 64 | ListNode::~ListNode(){ 65 | _next = nullptr; 66 | } 67 | 68 | template inline 69 | ListNode& ListNode::operator=(const ListNode& node){ 70 | this->element = node.element; 71 | _next = node._next; 72 | return *this; 73 | } 74 | 75 | template inline 76 | bool ListNode::operator==(const ListNode& node) const { 77 | return (this->element == node.element) && (_next == node._next); 78 | } 79 | 80 | template inline 81 | bool ListNode::operator!=(const ListNode& node) const { 82 | return (this->element != node.element) || (_next != node._next); 83 | } 84 | 85 | template inline 86 | void ListNode::insertAfter(ListNode* node){ 87 | node->_next = _next; 88 | _next = node; 89 | } 90 | 91 | template inline 92 | ListNode* ListNode::deleteAfter(){ 93 | ListNode* temp_node = _next; 94 | if (_next != nullptr) { 95 | _next = _next->_next; 96 | } 97 | return temp_node; 98 | } 99 | 100 | template inline 101 | ListNode* ListNode::next() { 102 | return _next; 103 | } 104 | 105 | } 106 | 107 | #endif /* list_node_hpp */ 108 | -------------------------------------------------------------------------------- /DataStructures/polynomial.h: -------------------------------------------------------------------------------- 1 | // 2 | // polynomial.hpp 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/28. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef polynomial_hpp 10 | #define polynomial_hpp 11 | 12 | #include 13 | #include 14 | #include "linked_list.h" 15 | #include "polynomial_unit.h" 16 | 17 | 18 | namespace data_structures { 19 | using std::cout; 20 | using std::ostream; 21 | using std::vector; 22 | 23 | template 24 | class Polynomail : public LinkedList { 25 | 26 | public: 27 | Polynomail(): LinkedList(){}; 28 | Polynomail(const Polynomail& py): LinkedList(py){}; 29 | Polynomail(const vector& units); 30 | Value eval(const Value& x); 31 | Polynomail operator-() const; 32 | Polynomail operator-(); 33 | Polynomail operator+(const Polynomail& py); 34 | Polynomail operator-(const Polynomail& py); 35 | Polynomail operator*(const Polynomail& py); 36 | friend ostream& operator<<(ostream& out, const Polynomail& py){ 37 | auto tail = py.tail(); 38 | for(auto node = py.begin(); node != py.end(); node = node->next()) { 39 | out << node->element << (node == tail ? "" : " + "); 40 | } 41 | return out; 42 | }; 43 | }; 44 | 45 | template inline 46 | Polynomail::Polynomail(const vector& units) { 47 | this->_header = new ListNode(); 48 | auto _current = this->_header; 49 | for (const Unit& unit: units) { 50 | _current->insertAfter(new ListNode(unit)); 51 | _current = _current->next(); 52 | } 53 | } 54 | 55 | template inline 56 | Value Polynomail::eval(const Value& x) { 57 | Value _result = Value(); 58 | for(auto node = this->begin(); node != this->end(); node = node->next()) { 59 | _result += node->element.eval(x); 60 | } 61 | return _result; 62 | } 63 | 64 | template inline 65 | Polynomail Polynomail::operator-() const { 66 | auto _result = Polynomail(*this); 67 | for(auto node = _result.begin(); node != _result.end(); node = node->next()) { 68 | node->element.coefficient = -node->element.coefficient; 69 | } 70 | return _result; 71 | } 72 | 73 | template inline 74 | Polynomail Polynomail::operator-() { 75 | auto _result = Polynomail(*this); 76 | for(auto node = _result.begin(); node != _result.end(); node = node->next()) { 77 | node->element.coefficient = -node->element.coefficient; 78 | } 79 | return _result; 80 | } 81 | 82 | template inline 83 | Polynomail Polynomail::operator+(const Polynomail& py) { 84 | if (this->isEmpty()) { 85 | return py; 86 | } 87 | if (py.isEmpty()) { 88 | return *this; 89 | } 90 | auto _result = Polynomail(); 91 | auto _result_node = _result._header; 92 | auto element = Unit(); 93 | auto n1 = this->begin(); 94 | auto n2 = py.begin(); 95 | // nodes in lists are plused are from big to small 96 | while (n1 != this->end() || n2 != py.end()) { 97 | if (n1 == this->end()){ 98 | element.exponent = n2->element.exponent; 99 | element.coefficient = n2->element.coefficient; 100 | n2 = n2->next(); 101 | } 102 | else if (n2 == py.end()) { 103 | element.exponent = n1->element.exponent; 104 | element.coefficient = n1->element.coefficient; 105 | n1 = n1->next(); 106 | } 107 | else if (n1->element.exponent > n2->element.exponent) { 108 | element.exponent = n1->element.exponent; 109 | element.coefficient = n1->element.coefficient; 110 | n1 = n1->next(); 111 | } 112 | else if (n1->element.exponent < n2->element.exponent) { 113 | element.exponent = n2->element.exponent; 114 | element.coefficient = n2->element.coefficient; 115 | n2 = n2->next(); 116 | } 117 | else { 118 | element.exponent = n1->element.exponent; 119 | element.coefficient = n1->element.coefficient + n2->element.coefficient; 120 | n1 = n1->next(); 121 | n2 = n2->next(); 122 | } 123 | if (element.isZero()) { 124 | continue; 125 | } 126 | _result_node->insertAfter(new ListNode(element)); 127 | _result_node = _result_node->next(); 128 | } 129 | return _result; 130 | } 131 | 132 | template inline 133 | Polynomail Polynomail::operator-(const Polynomail& py) { 134 | if (py.isEmpty()) { 135 | return *this; 136 | } 137 | auto _tmp = -py; 138 | if (this->isEmpty()) { 139 | return _tmp; 140 | } 141 | return *this + _tmp; 142 | } 143 | 144 | 145 | template inline 146 | Polynomail Polynomail::operator*(const Polynomail& py) { 147 | auto _result = Polynomail(); 148 | if (this->isEmpty() || py.isEmpty()) { 149 | return _result; 150 | } 151 | for (auto n1 = this->begin(); n1 != this->end(); n1 = n1 -> next()) { 152 | auto _tmp = Polynomail(); 153 | auto _tmp_node = _tmp._header; 154 | for (auto n2 = py.begin(); n2 != py.end(); n2 = n2 -> next()) { 155 | _tmp_node->insertAfter(new ListNode({ 156 | n1->element.exponent + n2->element.exponent, 157 | n1->element.coefficient * n2->element.coefficient, 158 | })); 159 | _tmp_node = _tmp_node->next(); 160 | } 161 | _result = _result + _tmp; 162 | } 163 | return _result; 164 | } 165 | } 166 | 167 | 168 | #endif /* polynomial_hpp */ 169 | -------------------------------------------------------------------------------- /DataStructures/polynomial_unit.h: -------------------------------------------------------------------------------- 1 | // 2 | // polynomial_unit.hpp 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/28. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef polynomial_unit_hpp 10 | #define polynomial_unit_hpp 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace data_structures{ 17 | using std::cout; 18 | using std::ostream; 19 | 20 | struct PolynomailUnit { 21 | float exponent; 22 | float coefficient; 23 | PolynomailUnit() { 24 | exponent = 0; 25 | coefficient = 0; 26 | } 27 | bool isZero() { 28 | return coefficient == 0; 29 | } 30 | float eval(const float& x) { 31 | return coefficient * pow(x, exponent); 32 | } 33 | bool operator==(const PolynomailUnit& unit) const { 34 | return exponent == unit.exponent && coefficient == unit.coefficient; 35 | }; 36 | bool operator!=(const PolynomailUnit& unit) const { 37 | return exponent != unit.exponent || coefficient != unit.coefficient; 38 | }; 39 | }; 40 | 41 | 42 | ostream& operator<<(ostream& out, const PolynomailUnit& unit){ 43 | out << unit.coefficient << "x^" << unit.exponent; 44 | return out; 45 | }; 46 | } 47 | 48 | #endif /* polynomial_unit_hpp */ 49 | -------------------------------------------------------------------------------- /DataStructures/priority_queue.h: -------------------------------------------------------------------------------- 1 | // 2 | // priority_queue 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/19. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_PRIORITY_QUEUE_H 10 | #define ALGORITHM_PRIORITY_QUEUE_H 11 | 12 | #include 13 | #include 14 | #include "linked_list.h" 15 | 16 | 17 | namespace data_structures { 18 | template 19 | class PriorityQueue { 20 | protected: 21 | LinkedList _list; 22 | bool _less(const T& element1, const T& element2); 23 | void _checkN(const size_t n); 24 | 25 | public: 26 | PriorityQueue(); 27 | PriorityQueue(const PriorityQueue& queue); 28 | virtual ~PriorityQueue(); 29 | bool isEmpty(); 30 | size_t size(); 31 | PriorityQueue& clear(); 32 | PriorityQueue& enqueue(const T &element); 33 | T dequeueMaxN(const size_t n = 1); 34 | T dequeueMinN(const size_t n = 1); 35 | T maxN(const size_t n = 1); 36 | T minN(const size_t n = 1); 37 | PriorityQueue& operator=(const PriorityQueue& queue); 38 | bool operator==(const PriorityQueue& queue) const; 39 | bool operator!=(const PriorityQueue& queue) const; 40 | ListNode* begin() const; 41 | ListNode* end() const; 42 | ListNode* header() const; 43 | ListNode* tail() const; 44 | friend std::ostream& operator<<(std::ostream& out, const PriorityQueue& queue){ 45 | out << "Min ---- "; 46 | out << queue._list; 47 | out << " ---- Max"; 48 | return out; 49 | }; 50 | }; 51 | 52 | template inline 53 | PriorityQueue::PriorityQueue() { 54 | _list = LinkedList(); 55 | } 56 | 57 | template inline 58 | PriorityQueue::PriorityQueue(const PriorityQueue& queue) { 59 | _list = LinkedList(queue._list); 60 | } 61 | 62 | template inline 63 | PriorityQueue::~PriorityQueue() {} 64 | 65 | template inline 66 | PriorityQueue& PriorityQueue::operator=(const PriorityQueue& queue){ 67 | _list = queue._list; 68 | return *this; 69 | } 70 | 71 | template inline 72 | bool PriorityQueue::operator==(const PriorityQueue& queue) const { 73 | return _list == queue._list; 74 | } 75 | 76 | template inline 77 | bool PriorityQueue::operator!=(const PriorityQueue& queue) const { 78 | return _list != queue._list; 79 | } 80 | 81 | template inline 82 | bool PriorityQueue::isEmpty() { 83 | return _list.isEmpty(); 84 | } 85 | 86 | template inline 87 | size_t PriorityQueue::size(){ 88 | return _list.size(); 89 | } 90 | 91 | template inline 92 | PriorityQueue& PriorityQueue::clear(){ 93 | _list.clear(); 94 | return *this; 95 | } 96 | 97 | template inline 98 | bool PriorityQueue::_less(const T &element1, const T &element2) { 99 | return element1 < element2; 100 | } 101 | 102 | template inline 103 | PriorityQueue& PriorityQueue::enqueue(const T &element) { 104 | if (isEmpty()) { 105 | _list.insertToHeader(element); 106 | return *this; 107 | } 108 | 109 | if (_less(element, _list.begin()->element)) { 110 | _list.insertToHeader(element); 111 | return *this; 112 | } 113 | 114 | for (auto node = _list.begin(); node->next() != _list.end(); node = node->next()) { 115 | if (_less(element, node->next()->element)) { 116 | _list.insertAfterNode(node, element); 117 | return *this; 118 | } 119 | } 120 | _list.insertToTail(element); 121 | return *this; 122 | } 123 | 124 | template inline 125 | void PriorityQueue::_checkN(const size_t n) { 126 | auto size = _list.size(); 127 | if (n == 0 || n > size) { 128 | throw std::out_of_range("N must be larger than 0 and less than this queue's size !"); 129 | } 130 | } 131 | 132 | template inline 133 | T PriorityQueue::maxN(const size_t n) { 134 | _checkN(n); 135 | return _list.getKthNode(_list.size() - n)->element; 136 | } 137 | 138 | template inline 139 | T PriorityQueue::minN(const size_t n) { 140 | _checkN(n); 141 | return _list.getKthNode(n - 1)->element; 142 | } 143 | 144 | template inline 145 | T PriorityQueue::dequeueMaxN(const size_t n) { 146 | _checkN(n); 147 | auto size = _list.size(); 148 | T result; 149 | if (n == size) { 150 | result = _list.begin()->element; 151 | _list.deleteFromHeader(); 152 | } 153 | else { 154 | auto node = _list.getKthNode(_list.size() - n - 1); 155 | result = node->next()->element; 156 | _list.deleteAfterNode(node); 157 | } 158 | return result; 159 | } 160 | 161 | template inline 162 | T PriorityQueue::dequeueMinN(const size_t n) { 163 | _checkN(n); 164 | T result; 165 | if (n == 1) { 166 | result = _list.begin()->element; 167 | _list.deleteFromHeader(); 168 | } 169 | else { 170 | auto node = _list.getKthNode(n - 1); 171 | result = node->next()->element; 172 | _list.deleteAfterNode(node); 173 | } 174 | return result; 175 | } 176 | 177 | template inline 178 | ListNode* PriorityQueue::begin() const { 179 | return _list.begin(); 180 | } 181 | 182 | template inline 183 | ListNode* PriorityQueue::end() const { 184 | return _list.end(); 185 | } 186 | 187 | template inline 188 | ListNode* PriorityQueue::header() const { 189 | return _list.header(); 190 | } 191 | 192 | template inline 193 | ListNode* PriorityQueue::tail() const { 194 | return _list.tail(); 195 | } 196 | 197 | } 198 | 199 | #endif //ALGORITHM_PRIORITY_QUEUE_H 200 | -------------------------------------------------------------------------------- /DataStructures/queue.h: -------------------------------------------------------------------------------- 1 | // 2 | // queue 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/8. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_QUEUE_H 10 | #define ALGORITHM_QUEUE_H 11 | 12 | #include 13 | #include "linked_list.h" 14 | 15 | 16 | namespace data_structures { 17 | template 18 | class Queue { 19 | 20 | protected: 21 | LinkedList _list; 22 | 23 | public: 24 | Queue(); 25 | Queue(const Queue& queue); 26 | virtual ~Queue(); 27 | bool isEmpty() const; 28 | Queue& clear(); 29 | Queue& enqueue(const T& element); 30 | T dequeue(); 31 | T front(); 32 | T rear(); 33 | Queue& operator=(const Queue& queue); 34 | bool operator==(const Queue& queue) const; 35 | bool operator!=(const Queue& queue) const; 36 | friend ostream& operator<<(ostream& out, const Queue& queue){ 37 | out << "Front ---- "; 38 | out << queue._list; 39 | out << " ---- Rear"; 40 | return out; 41 | }; 42 | }; 43 | 44 | 45 | template inline 46 | Queue::Queue() { 47 | _list = LinkedList(); 48 | } 49 | 50 | template inline 51 | Queue::Queue(const Queue& queue) { 52 | _list = LinkedList(queue._list); 53 | } 54 | 55 | template inline 56 | Queue::~Queue() {} 57 | 58 | template inline 59 | Queue& Queue::operator=(const Queue& queue){ 60 | _list = queue._list; 61 | return *this; 62 | } 63 | 64 | template inline 65 | bool Queue::operator==(const Queue& queue) const { 66 | return _list == queue._list; 67 | } 68 | 69 | template inline 70 | bool Queue::operator!=(const Queue& queue) const { 71 | return _list != queue._list; 72 | } 73 | 74 | template inline 75 | bool Queue::isEmpty() const { 76 | return _list.isEmpty(); 77 | } 78 | 79 | template inline 80 | Queue& Queue::clear() { 81 | _list.clear(); 82 | return *this; 83 | } 84 | 85 | template inline 86 | Queue& Queue::enqueue(const T &element){ 87 | _list.insertToTail(element); 88 | return *this; 89 | } 90 | 91 | template inline 92 | T Queue::dequeue(){ 93 | if (isEmpty()) { 94 | throw std::out_of_range("Noting in this queue !"); 95 | } 96 | T result = _list.begin()->element; 97 | _list.deleteFromHeader(); 98 | return result; 99 | } 100 | 101 | template inline 102 | T Queue::front(){ 103 | if (isEmpty()) { 104 | throw std::out_of_range("Noting in this queue !"); 105 | } 106 | return _list.begin()->element; 107 | } 108 | 109 | template inline 110 | T Queue::rear(){ 111 | if (isEmpty()) { 112 | throw std::out_of_range("Noting in this queue !"); 113 | } 114 | return _list.tail()->element; 115 | } 116 | 117 | } 118 | 119 | 120 | #endif //ALGORITHM_QUEUE_H 121 | -------------------------------------------------------------------------------- /DataStructures/queue_based_on_array.h: -------------------------------------------------------------------------------- 1 | // 2 | // queue_based_on_array 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/8. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_QUEUE_BASED_ON_ARRAY_H 10 | #define ALGORITHM_QUEUE_BASED_ON_ARRAY_H 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | namespace data_structures { 18 | using std::ostream; 19 | using std::cout; 20 | using std::endl; 21 | 22 | template 23 | class QueueBasedOnArray { 24 | 25 | protected: 26 | std::array _array; 27 | int _cursor_front, _cursor_rear; 28 | bool _empty, _full; 29 | 30 | public: 31 | QueueBasedOnArray(); 32 | QueueBasedOnArray(const QueueBasedOnArray& queue); 33 | virtual ~QueueBasedOnArray(); 34 | bool isEmpty() const; 35 | bool isFull() const; 36 | QueueBasedOnArray& clear(); 37 | QueueBasedOnArray& enqueue(const T& element); 38 | T dequeue(); 39 | T front(); 40 | T rear(); 41 | QueueBasedOnArray& operator=(const QueueBasedOnArray& queue); 42 | bool operator==(const QueueBasedOnArray& queue) const; 43 | bool operator!=(const QueueBasedOnArray& queue) const; 44 | friend ostream& operator<<(ostream& out, const QueueBasedOnArray& queue){ 45 | out << "Front ---- "; 46 | if (queue.isEmpty()) {} 47 | else if (queue._cursor_front < queue._cursor_rear) { 48 | for(auto i = queue._cursor_front + 1; i <= queue._cursor_rear; i++) { 49 | out << queue._array[i] << " "; 50 | } 51 | } 52 | else { 53 | for(auto i = queue._cursor_front + 1; i < Size; i++) { 54 | out << queue._array[i] << " "; 55 | } 56 | for(auto i = 0; i <= queue._cursor_rear; i++) { 57 | out << queue._array[i] << " "; 58 | } 59 | } 60 | out << " ---- Rear"; 61 | return out; 62 | }; 63 | }; 64 | 65 | 66 | template inline 67 | QueueBasedOnArray::QueueBasedOnArray() { 68 | _cursor_front = _cursor_rear = (int) (Size - 1); 69 | _full = false; 70 | _empty = true; 71 | _array = std::array(); 72 | } 73 | 74 | template inline 75 | QueueBasedOnArray::QueueBasedOnArray(const QueueBasedOnArray& queue) { 76 | _cursor_front = queue._cursor_front; 77 | _cursor_rear = queue._cursor_rear; 78 | _full = queue._full; 79 | _empty = queue._empty; 80 | _array = queue._array; 81 | } 82 | 83 | template inline 84 | QueueBasedOnArray::~QueueBasedOnArray() {} 85 | 86 | template inline 87 | QueueBasedOnArray& QueueBasedOnArray::operator=(const QueueBasedOnArray& queue){ 88 | _cursor_front = queue._cursor_front; 89 | _cursor_rear = queue._cursor_rear; 90 | _full = queue._full; 91 | _empty = queue._empty; 92 | _array = queue._array; 93 | return *this; 94 | } 95 | 96 | template inline 97 | bool QueueBasedOnArray::operator==(const QueueBasedOnArray& queue) const { 98 | return _array == queue._array && _cursor_front == queue._cursor_front && _cursor_rear == queue._cursor_rear; 99 | } 100 | 101 | template inline 102 | bool QueueBasedOnArray::operator!=(const QueueBasedOnArray& queue) const { 103 | return _cursor_front != queue._cursor_front || _cursor_rear != queue._cursor_rear || _array != queue._array; 104 | } 105 | 106 | template inline 107 | bool QueueBasedOnArray::isEmpty() const { 108 | return _empty; 109 | } 110 | 111 | template inline 112 | bool QueueBasedOnArray::isFull() const { 113 | return _full; 114 | } 115 | 116 | template inline 117 | QueueBasedOnArray& QueueBasedOnArray::clear() { 118 | _array = std::array(); 119 | _cursor_front = _cursor_rear = (int) (Size - 1); 120 | _full = false; 121 | _empty = true; 122 | return *this; 123 | } 124 | 125 | template inline 126 | QueueBasedOnArray& QueueBasedOnArray::enqueue(const T& element) { 127 | if (isFull()) { 128 | throw std::out_of_range("Queue overflow !"); 129 | } 130 | if (_cursor_rear == Size - 1) { 131 | _cursor_rear = -1; 132 | } 133 | _array[++_cursor_rear] = element; 134 | if (_cursor_rear == _cursor_front) { 135 | _full = true; 136 | } 137 | _empty = false; 138 | return *this; 139 | } 140 | 141 | template inline 142 | T QueueBasedOnArray::dequeue() { 143 | if (isEmpty()) { 144 | throw std::out_of_range("Noting in this queue !"); 145 | } 146 | if (_cursor_front == Size - 1) { 147 | _cursor_front = -1; 148 | } 149 | if (++_cursor_front == _cursor_rear) { 150 | _empty = true; 151 | } 152 | _full = false; 153 | return _array[_cursor_front]; 154 | } 155 | 156 | template inline 157 | T QueueBasedOnArray::front() { 158 | if (isEmpty()) { 159 | throw std::out_of_range("Noting in this queue !"); 160 | } 161 | return _array[_cursor_front]; 162 | } 163 | 164 | template inline 165 | T QueueBasedOnArray::rear(){ 166 | if (isEmpty()) { 167 | throw std::out_of_range("Noting in this queue !"); 168 | } 169 | return _array[_cursor_rear]; 170 | } 171 | 172 | } 173 | 174 | #endif //ALGORITHM_QUEUE_BASED_ON_ARRAY_H 175 | -------------------------------------------------------------------------------- /DataStructures/red_black_tree_node.h: -------------------------------------------------------------------------------- 1 | // 2 | // red_black_tree_node 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/11/30. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_RED_BLACK_TREE_NODE_H 10 | #define ALGORITHM_RED_BLACK_TREE_NODE_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | namespace data_structures { 19 | template 20 | class RBTreeNode { 21 | protected: 22 | RBTreeNode *_left, *_right, *_parent; 23 | bool _is_left, _is_red; 24 | void _init(); 25 | void _copy(const RBTreeNode &node); 26 | 27 | public: 28 | T element; 29 | size_t node_count; 30 | RBTreeNode(); 31 | RBTreeNode(const T &element); 32 | RBTreeNode(const RBTreeNode &node); 33 | virtual ~RBTreeNode(); 34 | bool isLeft(); 35 | bool isRed(); 36 | RBTreeNode *initRoot(); 37 | RBTreeNode *flipColors(); 38 | RBTreeNode *insertLeft(RBTreeNode *node, const bool is_red = false); 39 | RBTreeNode *insertRight(RBTreeNode *node, const bool is_red = false); 40 | RBTreeNode *deleteLeft(); 41 | RBTreeNode *deleteRight(); 42 | RBTreeNode *left(); 43 | RBTreeNode *right(); 44 | RBTreeNode *parent(); 45 | std::string toString(); 46 | RBTreeNode& operator=(const RBTreeNode &node); 47 | bool operator==(const RBTreeNode &node); 48 | bool operator!=(const RBTreeNode &node); 49 | friend std::ostream &operator<<(std::ostream &out, const RBTreeNode &node) { 50 | out << "Current: " << &node << ", Element: " << node.element << ", Parent: " << node._parent 51 | << ", Left: " << node._left << ", Right: " << node._right 52 | << ", IsLeft: " << node._is_left << ", IsRed: " << node._is_red; 53 | return out; 54 | } 55 | }; 56 | 57 | template inline 58 | void RBTreeNode::_init() { 59 | _left = nullptr; 60 | _right = nullptr; 61 | _parent = nullptr; 62 | element = T(); 63 | node_count = 1; 64 | _is_left = false; 65 | _is_red = false; 66 | } 67 | 68 | template inline 69 | void RBTreeNode::_copy(const RBTreeNode &node){ 70 | element = node.element; 71 | _left = node._left; 72 | _right = node._right; 73 | _parent = node._parent; 74 | node_count = 1; 75 | _is_left = false; 76 | _is_red = false; 77 | } 78 | 79 | template inline 80 | RBTreeNode::RBTreeNode(){ 81 | _init(); 82 | } 83 | 84 | template inline 85 | RBTreeNode::RBTreeNode(const T& element){ 86 | _init(); 87 | this->element = element; 88 | } 89 | 90 | template inline 91 | RBTreeNode::RBTreeNode(const RBTreeNode& node){ 92 | _copy(node); 93 | } 94 | 95 | template inline 96 | RBTreeNode::~RBTreeNode(){ 97 | _init(); 98 | } 99 | 100 | template inline 101 | RBTreeNode& RBTreeNode::operator=(const RBTreeNode& node){ 102 | _copy(node); 103 | return *this; 104 | } 105 | 106 | template inline 107 | bool RBTreeNode::operator==(const RBTreeNode& node){ 108 | return (element == node.element) && (_parent == node._parent) && (_left == node._left); 109 | } 110 | 111 | template inline 112 | bool RBTreeNode::operator!=(const RBTreeNode& node){ 113 | return !(*this == node); 114 | } 115 | 116 | template inline 117 | bool RBTreeNode::isLeft(){ 118 | return _is_left; 119 | } 120 | 121 | template inline 122 | bool RBTreeNode::isRed(){ 123 | return _is_red; 124 | } 125 | 126 | template inline 127 | RBTreeNode* RBTreeNode::initRoot(){ 128 | _parent = nullptr; 129 | _is_left = false; 130 | _is_red = false; 131 | return this; 132 | } 133 | 134 | template inline 135 | RBTreeNode * RBTreeNode::flipColors(){ 136 | _is_red = !_is_red; 137 | return this; 138 | } 139 | 140 | template inline 141 | RBTreeNode * RBTreeNode::insertLeft(RBTreeNode *node, const bool is_red){ 142 | RBTreeNode* temp_node = _left; 143 | if (node != nullptr) { 144 | node->_parent = this; 145 | node->_is_left = true; 146 | node->_is_red = is_red; 147 | } 148 | _left = node; 149 | return temp_node; 150 | } 151 | 152 | template inline 153 | RBTreeNode * RBTreeNode::insertRight(RBTreeNode *node, const bool is_red){ 154 | RBTreeNode* temp_node = _right; 155 | if (node != nullptr) { 156 | node->_parent = this; 157 | node->_is_left = false; 158 | node->_is_red = is_red; 159 | } 160 | _right = node; 161 | return temp_node; 162 | } 163 | 164 | template inline 165 | RBTreeNode* RBTreeNode::deleteLeft(){ 166 | RBTreeNode* temp_node = _left; 167 | _left = nullptr; 168 | return temp_node; 169 | } 170 | 171 | template inline 172 | RBTreeNode* RBTreeNode::deleteRight(){ 173 | RBTreeNode* temp_node = _right; 174 | _right = nullptr; 175 | return temp_node; 176 | } 177 | 178 | template inline 179 | RBTreeNode* RBTreeNode::left(){ 180 | return _left; 181 | } 182 | 183 | template inline 184 | RBTreeNode* RBTreeNode::right(){ 185 | return _right; 186 | } 187 | 188 | template inline 189 | RBTreeNode* RBTreeNode::parent(){ 190 | return _parent; 191 | } 192 | 193 | template inline 194 | std::string RBTreeNode::toString(){ 195 | std::ostringstream ss; 196 | ss << element << "(" << (_is_red ? "r" : "b") << "," << node_count << ")"; 197 | return ss.str(); 198 | } 199 | } 200 | 201 | 202 | #endif //ALGORITHM_RED_BLACK_TREE_NODE_H 203 | -------------------------------------------------------------------------------- /DataStructures/stack.h: -------------------------------------------------------------------------------- 1 | // 2 | // stack 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/4. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_STACK_H 10 | #define ALGORITHM_STACK_H 11 | 12 | #include 13 | #include "linked_list.h" 14 | 15 | 16 | namespace data_structures { 17 | template 18 | class Stack { 19 | 20 | protected: 21 | LinkedList _list; 22 | 23 | public: 24 | Stack(); 25 | Stack(const Stack& stack); 26 | virtual ~Stack(); 27 | bool isEmpty() const; 28 | Stack& clear(); 29 | Stack& push(const T& element); 30 | T pop(); 31 | T top(); 32 | Stack& operator=(const Stack& stack); 33 | bool operator==(const Stack& stack) const; 34 | bool operator!=(const Stack& stack) const; 35 | friend ostream& operator<<(ostream& out, const Stack& stack){ 36 | out << "Top ---- "; 37 | out << stack._list; 38 | out << " ---- Bottom"; 39 | return out; 40 | }; 41 | }; 42 | 43 | 44 | template inline 45 | Stack::Stack() { 46 | _list = LinkedList(); 47 | } 48 | 49 | template inline 50 | Stack::Stack(const Stack& stack) { 51 | _list = LinkedList(stack._list); 52 | } 53 | 54 | template inline 55 | Stack::~Stack() {} 56 | 57 | template inline 58 | Stack& Stack::operator=(const Stack& stack){ 59 | _list = stack._list; 60 | return *this; 61 | } 62 | 63 | template inline 64 | bool Stack::operator==(const Stack& stack) const { 65 | return _list == stack._list; 66 | } 67 | 68 | template inline 69 | bool Stack::operator!=(const Stack& stack) const { 70 | return _list != stack._list; 71 | } 72 | 73 | template inline 74 | bool Stack::isEmpty() const { 75 | return _list.isEmpty(); 76 | } 77 | 78 | template inline 79 | Stack& Stack::clear() { 80 | _list.clear(); 81 | return *this; 82 | } 83 | 84 | template inline 85 | Stack& Stack::push(const T& element) { 86 | _list.insertToHeader(element); 87 | return *this; 88 | } 89 | 90 | template inline 91 | T Stack::pop() { 92 | if (isEmpty()) { 93 | throw std::out_of_range("Noting in this stack !"); 94 | } 95 | T result = _list.begin()->element; 96 | _list.deleteFromHeader(); 97 | return result; 98 | } 99 | 100 | template inline 101 | T Stack::top() { 102 | if (isEmpty()) { 103 | throw std::out_of_range("Noting in this stack !"); 104 | } 105 | return _list.begin()->element; 106 | } 107 | 108 | } 109 | 110 | 111 | #endif //ALGORITHM_STACK_H 112 | -------------------------------------------------------------------------------- /DataStructures/stack_based_on_array.h: -------------------------------------------------------------------------------- 1 | // 2 | // stack_based_on_array 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/4. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_STACK_BASED_ON_ARRAY_H 10 | #define ALGORITHM_STACK_BASED_ON_ARRAY_H 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | namespace data_structures { 18 | using std::ostream; 19 | using std::cout; 20 | using std::endl; 21 | 22 | template 23 | class StackBasedOnArray { 24 | 25 | protected: 26 | std::array _array; 27 | int _cursor; 28 | 29 | public: 30 | StackBasedOnArray(); 31 | StackBasedOnArray(const StackBasedOnArray& stack); 32 | virtual ~StackBasedOnArray(); 33 | bool isEmpty() const; 34 | bool isFull() const; 35 | StackBasedOnArray& clear(); 36 | StackBasedOnArray& push(const T& element); 37 | T pop(); 38 | T top(); 39 | StackBasedOnArray& operator=(const StackBasedOnArray& stack); 40 | bool operator==(const StackBasedOnArray& stack) const; 41 | bool operator!=(const StackBasedOnArray& stack) const; 42 | friend ostream& operator<<(ostream& out, const StackBasedOnArray& stack){ 43 | out << "Top ---- "; 44 | for(auto i = stack._cursor; i > -1; i--) { 45 | out << stack._array[i] << " "; 46 | } 47 | out << " ---- Bottom"; 48 | return out; 49 | }; 50 | }; 51 | 52 | 53 | template inline 54 | StackBasedOnArray::StackBasedOnArray() { 55 | _cursor = -1; 56 | _array = std::array(); 57 | } 58 | 59 | template inline 60 | StackBasedOnArray::StackBasedOnArray(const StackBasedOnArray& stack) { 61 | _cursor = stack._cursor; 62 | _array = stack._array; 63 | } 64 | 65 | template inline 66 | StackBasedOnArray::~StackBasedOnArray() {} 67 | 68 | template inline 69 | StackBasedOnArray& StackBasedOnArray::operator=(const StackBasedOnArray& stack){ 70 | _cursor = stack._cursor; 71 | _array = stack._array; 72 | return *this; 73 | } 74 | 75 | template inline 76 | bool StackBasedOnArray::operator==(const StackBasedOnArray& stack) const { 77 | return _array == stack._array && _cursor == stack._cursor; 78 | } 79 | 80 | template inline 81 | bool StackBasedOnArray::operator!=(const StackBasedOnArray& stack) const { 82 | return _cursor != stack._cursor || _array != stack._array; 83 | } 84 | 85 | template inline 86 | bool StackBasedOnArray::isEmpty() const { 87 | return _cursor == -1; 88 | } 89 | 90 | template inline 91 | bool StackBasedOnArray::isFull() const { 92 | return _cursor == Size - 1; 93 | } 94 | 95 | template inline 96 | StackBasedOnArray& StackBasedOnArray::clear() { 97 | _array = std::array(); 98 | _cursor = -1; 99 | return *this; 100 | } 101 | 102 | template inline 103 | StackBasedOnArray& StackBasedOnArray::push(const T& element) { 104 | if (isFull()) { 105 | throw std::out_of_range("Stack overflow !"); 106 | } 107 | _array[++_cursor] = element; 108 | return *this; 109 | } 110 | 111 | template inline 112 | T StackBasedOnArray::pop() { 113 | if (isEmpty()) { 114 | throw std::out_of_range("Noting in this stack !"); 115 | } 116 | return _array[--_cursor]; 117 | } 118 | 119 | template inline 120 | T StackBasedOnArray::top() { 121 | if (isEmpty()) { 122 | throw std::out_of_range("Noting in this stack !"); 123 | } 124 | return _array[_cursor]; 125 | } 126 | 127 | } 128 | 129 | 130 | #endif //ALGORITHM_STACK_BASED_ON_ARRAY_H 131 | -------------------------------------------------------------------------------- /DataStructures/symbol_table.h: -------------------------------------------------------------------------------- 1 | // 2 | // symbol_table 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/11/9. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_SYMBOL_TABLE_H 10 | #define ALGORITHM_SYMBOL_TABLE_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include "linked_list.h" 16 | #include "symbol_table_elements.h" 17 | 18 | 19 | namespace data_structures { 20 | template 21 | class SymbolTable { 22 | protected: 23 | LinkedList> _list; 24 | public: 25 | SymbolTable(); 26 | virtual ~SymbolTable(); 27 | SymbolTable(const SymbolTable& table); 28 | SymbolTable& operator=(const SymbolTable& table); 29 | bool operator==(const SymbolTable& table); 30 | bool operator!=(const SymbolTable& table); 31 | bool isEmpty(); 32 | size_t size(); 33 | bool has(const Key& key); 34 | SymbolTable& set(const Key& key, const Value& value); 35 | Value get(const Key& key); 36 | Value del(const Key& key); 37 | SymbolTable& clear(); 38 | std::vector keys(); 39 | std::vector values(); 40 | std::vector> elements(); 41 | friend std::ostream &operator<<(std::ostream &out, const SymbolTable &table) { 42 | out << "{" << std::endl; 43 | out << " " << table._list; 44 | out << "}" << std::endl; 45 | return out; 46 | }; 47 | }; 48 | 49 | template inline 50 | SymbolTable::SymbolTable() { 51 | _list = LinkedList>(); 52 | } 53 | 54 | template inline 55 | SymbolTable::~SymbolTable() { 56 | _list.clear(); 57 | } 58 | 59 | template inline 60 | SymbolTable::SymbolTable(const SymbolTable& table) { 61 | _list = table._list; 62 | } 63 | 64 | template inline 65 | SymbolTable& SymbolTable::operator=(const SymbolTable &table){ 66 | _list = table._list; 67 | return *this; 68 | } 69 | 70 | template inline 71 | bool SymbolTable::operator==(const SymbolTable &table){ 72 | return _list == table._list; 73 | } 74 | 75 | template inline 76 | bool SymbolTable::operator!=(const SymbolTable &table){ 77 | return _list != table._list; 78 | } 79 | 80 | template inline 81 | bool SymbolTable::isEmpty(){ 82 | return _list.isEmpty(); 83 | } 84 | 85 | template inline 86 | size_t SymbolTable::size(){ 87 | return _list.size(); 88 | } 89 | 90 | template inline 91 | bool SymbolTable::has(const Key &key){ 92 | for (auto node = _list.begin(); node != _list.end(); node = node->next()) { 93 | if (node->element.key == key) { 94 | return true; 95 | } 96 | } 97 | return false; 98 | } 99 | 100 | template inline 101 | SymbolTable& SymbolTable::set(const Key &key, const Value &value){ 102 | for (auto node = _list.begin(); node != _list.end(); node = node->next()) { 103 | if (node->element.key == key) { 104 | node->element.value = value; 105 | return *this; 106 | } 107 | } 108 | _list.insertToTail(SymbolTableElement(key, value)); 109 | return *this; 110 | } 111 | 112 | template inline 113 | Value SymbolTable::get(const Key &key){ 114 | for (auto node = _list.begin(); node != _list.end(); node = node->next()) { 115 | if (node->element.key == key) { 116 | return node->element.value; 117 | } 118 | } 119 | throw std::out_of_range("Key error, no such key in this table !"); 120 | } 121 | 122 | template inline 123 | Value SymbolTable::del(const Key &key){ 124 | auto pre_node = _list.header(); 125 | for (auto node = _list.begin(); node != _list.end(); node = node->next()) { 126 | if (node->element.key == key) { 127 | auto result = node->element.value; 128 | _list.deleteAfterNode(pre_node); 129 | return result; 130 | } 131 | pre_node = node; 132 | } 133 | throw std::out_of_range("Key error, no such key in this table !"); 134 | } 135 | 136 | template inline 137 | SymbolTable& SymbolTable::clear(){ 138 | _list.clear(); 139 | return *this; 140 | } 141 | 142 | template inline 143 | std::vector SymbolTable::keys(){ 144 | auto keys = std::vector(); 145 | for (auto node = _list.begin(); node != _list.end(); node = node->next()) { 146 | keys.push_back(node->element.key); 147 | } 148 | return keys; 149 | } 150 | 151 | template inline 152 | std::vector SymbolTable::values(){ 153 | auto values = std::vector(); 154 | for (auto node = _list.begin(); node != _list.end(); node = node->next()) { 155 | values.push_back(node->element.value); 156 | } 157 | return values; 158 | } 159 | 160 | template inline 161 | std::vector> SymbolTable::elements(){ 162 | auto elements = std::vector>(); 163 | for (auto node = _list.begin(); node != _list.end(); node = node->next()) { 164 | elements.push_back(node->element); 165 | } 166 | return elements; 167 | } 168 | } 169 | 170 | 171 | #endif //ALGORITHM_SYMBOL_TABLE_H 172 | -------------------------------------------------------------------------------- /DataStructures/symbol_table_elements.h: -------------------------------------------------------------------------------- 1 | // 2 | // symbol_table_elements 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/11/14. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_SYMBOL_TABLE_ELEMENTS_H 10 | #define ALGORITHM_SYMBOL_TABLE_ELEMENTS_H 11 | 12 | #include 13 | #include 14 | 15 | 16 | namespace data_structures { 17 | template 18 | struct SymbolTableElement { 19 | public: 20 | Key key; 21 | Value value; 22 | SymbolTableElement() {} 23 | virtual ~SymbolTableElement() {} 24 | SymbolTableElement(const Key& k, const Value& v) { 25 | key = k; 26 | value = v; 27 | } 28 | SymbolTableElement(const SymbolTableElement& element) { 29 | key = element.key; 30 | value = element.value; 31 | } 32 | SymbolTableElement& operator=(const SymbolTableElement& element) { 33 | key = element.key; 34 | value = element.value; 35 | return *this; 36 | } 37 | bool operator==(const SymbolTableElement& element) { 38 | return key == element.key && value == element.value; 39 | } 40 | bool operator!=(const SymbolTableElement& element) { 41 | return !(*this == element); 42 | } 43 | friend std::ostream &operator<<(std::ostream &out, const SymbolTableElement &element) { 44 | std::cout << element.key << ": " << element.value << std::endl; 45 | return out; 46 | }; 47 | }; 48 | 49 | 50 | template 51 | struct OrderlySymbolTableElement { 52 | public: 53 | Key key; 54 | Value value; 55 | OrderlySymbolTableElement() {} 56 | OrderlySymbolTableElement(const Key& k, const Value& v) { 57 | key = k; 58 | value = v; 59 | } 60 | OrderlySymbolTableElement(const OrderlySymbolTableElement& element) { 61 | key = element.key; 62 | value = element.value; 63 | } 64 | OrderlySymbolTableElement& operator=(const OrderlySymbolTableElement& element) { 65 | key = element.key; 66 | value = element.value; 67 | return *this; 68 | } 69 | bool operator==(const OrderlySymbolTableElement& element) const { 70 | return key == element.key; 71 | } 72 | bool operator!=(const OrderlySymbolTableElement& element) const { 73 | return key != element.key; 74 | } 75 | bool operator>(const OrderlySymbolTableElement& element) const { 76 | return key > element.key; 77 | } 78 | bool operator<(const OrderlySymbolTableElement& element) const { 79 | return key < element.key; 80 | } 81 | bool operator>=(const OrderlySymbolTableElement& element) const { 82 | return key >= element.key; 83 | } 84 | bool operator<=(const OrderlySymbolTableElement& element) const { 85 | return key <= element.key; 86 | } 87 | friend std::ostream &operator<<(std::ostream &out, const OrderlySymbolTableElement &element) { 88 | std::cout << element.key << ": " << element.value << std::endl; 89 | return out; 90 | }; 91 | }; 92 | } 93 | 94 | 95 | #endif //ALGORITHM_SYMBOL_TABLE_ELEMENTS_H 96 | -------------------------------------------------------------------------------- /DataStructures/tree_element.h: -------------------------------------------------------------------------------- 1 | // 2 | // tree_element 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/11/19. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_TREE_ELEMENTS_H 10 | #define ALGORITHM_TREE_ELEMENTS_H 11 | 12 | #include 13 | #include 14 | 15 | 16 | namespace data_structures { 17 | template 18 | struct TreeElement { 19 | public: 20 | Key key; 21 | Value value; 22 | TreeElement() {} 23 | TreeElement(const Key& k, const Value& v) { 24 | key = k; 25 | value = v; 26 | } 27 | TreeElement(const TreeElement& element) { 28 | key = element.key; 29 | value = element.value; 30 | } 31 | TreeElement& operator=(const TreeElement& element) { 32 | key = element.key; 33 | value = element.value; 34 | return *this; 35 | } 36 | bool operator==(const TreeElement& element) const { 37 | return key == element.key; 38 | } 39 | bool operator!=(const TreeElement& element) const { 40 | return key != element.key; 41 | } 42 | bool operator>(const TreeElement& element) const { 43 | return key > element.key; 44 | } 45 | bool operator<(const TreeElement& element) const { 46 | return key < element.key; 47 | } 48 | bool operator>=(const TreeElement& element) const { 49 | return key >= element.key; 50 | } 51 | bool operator<=(const TreeElement& element) const { 52 | return key <= element.key; 53 | } 54 | friend std::ostream &operator<<(std::ostream &out, const TreeElement &element) { 55 | out<< element.key << ":" << element.value; 56 | return out; 57 | }; 58 | }; 59 | } 60 | 61 | #endif //ALGORITHM_TREE_ELEMENTS_H 62 | -------------------------------------------------------------------------------- /DataStructures/weighted_digraph.h: -------------------------------------------------------------------------------- 1 | // 2 | // weighted_digraph 3 | // Algorithm 4 | // 5 | // Created by dtysky on 2017/3/11. 6 | // Copyright © 2017 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_WEIGHTED_DIGRAPH_H 10 | #define ALGORITHM_WEIGHTED_DIGRAPH_H 11 | 12 | #include 13 | #include "weighted_graph.h" 14 | 15 | namespace data_structures { 16 | template 17 | class WeightedDigraph : public WeightedGraph { 18 | public: 19 | WeightedDigraph(): WeightedGraph() {}; 20 | WeightedDigraph(WeightedDigraph &graph): WeightedGraph(graph) {}; 21 | virtual ~WeightedDigraph(); 22 | WeightedDigraph& addEdge(const T& v, const T& w, Weight weight); 23 | WeightedDigraph& deleteEdge(const T& v, const T& w); 24 | void reverse(WeightedDigraph& res_graph); 25 | friend std::ostream &operator<<(std::ostream &out, WeightedDigraph &graph) { 26 | auto nodes = graph._tree.getAllNodes(); 27 | for (auto node: nodes) { 28 | out << node->element.key << ": "; 29 | for (auto &e: node->element.value.adjEdges()) { 30 | out << e.to->element.key << "(" << e.weight << ")" << " "; 31 | } 32 | out << std::endl; 33 | } 34 | return out; 35 | } 36 | }; 37 | 38 | template inline 39 | WeightedDigraph::~WeightedDigraph() {} 40 | 41 | template inline 42 | WeightedDigraph& WeightedDigraph::addEdge(const T& v, const T& w, Weight weight){ 43 | if (v == w) { 44 | return *this; 45 | } 46 | auto vp = this->_tree.getNode(v); 47 | auto wp = this->_tree.getNode(w); 48 | if (vp->element.value.addEdge(wp, weight)) { 49 | this->_edge_count++; 50 | } 51 | return *this; 52 | } 53 | 54 | template inline 55 | WeightedDigraph& WeightedDigraph::deleteEdge(const T& v, const T& w){ 56 | auto vp = this->_tree.getNode(v); 57 | auto wp = this->_tree.getNode(w); 58 | if (vp->element.value.deleteEdge(wp)) { 59 | this->_edge_count--; 60 | } 61 | return *this; 62 | } 63 | 64 | template inline 65 | void WeightedDigraph::reverse(WeightedDigraph& res_graph){ 66 | res_graph.clear(); 67 | auto nodes = this->_tree.getAllNodes(); 68 | for (auto &node: nodes) { 69 | res_graph.addVertex(node->element.key); 70 | } 71 | for (auto &node: nodes) { 72 | auto adj_set = node->element.value.adjEdges(); 73 | for (auto &edge: adj_set) { 74 | res_graph.addEdge(edge.to->element.key, edge.from->element.key, edge.weight); 75 | } 76 | } 77 | } 78 | } 79 | 80 | #endif //ALGORITHM_WEIGHTED_DIGRAPH_H 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algorithm 2 | 3 | 4 | Algorithm and data structures exercises. 5 | 6 | Build with Cpp and Ruby. 7 | 8 | 9 | ## DataStructures 10 | 11 | ### Cpp 12 | 13 | 1. ListNode: node for single linked list. 14 | 2. LinkedList: single linked list based on pointer. 15 | 3. Polynomial: polynomial class based on linked list, which supports operators +, - and *. 16 | 4. Stack: stack based on linked list. 17 | 5. StackBasedOnArray: stack based on array. 18 | 6. Queue: queue based on linked list. 19 | 7. QueueBasedOnArray: queue based on array. 20 | 8. PriorityQueue: priority queue based on linked list. 21 | 9. BinaryHeap: Binary heap based on array. 22 | 10. SymbolTable: Symbol table based on linked list. 23 | 11. OrderlySymbolTable: Orderly symbol table based on priority queue. 24 | 12. BinarySearchTree: Binary search tree based on pointer. 25 | 13. TwoThreeTree: 2-3-tree based on pointer, waiting for testing. 26 | 14. RBTree: Red-black tree based on pointer. 27 | 15. AVLTree: AVL tree based on pointer. 28 | 16. HashTable: Separate chaining hash table based on array and symbol table. 29 | 17. Graph: Undirected graph based on red black tree(vertex) and symbol table(adjacent vertex set). 30 | 18. Digraph: Directed graph based on red black tree(vertex) and symbol table(adjacent vertex set). 31 | 19. WeightedGraph: Weighted graph based on red black tree(vertex) and symbol table(adjacent vertex set). 32 | 20. WeightedDigraph: Weighted directed graph based on red black tree(vertex) and symbol table(adjacent vertex set). 33 | 34 | ### Ruby 35 | 36 | 1. Aplhabet: alphabet based on array. 37 | 38 | ## Algorithm 39 | 40 | ### Cpp 41 | 42 | 1. BucketSort: bucket sort, time-O(num_max + num_size), space-O(num_max). 43 | 2. RadixSort: radix sort, time-O(num_msd(num_size)), space-O(num_size * num_radix). 44 | 3. SymbolPairChecker: check the symbol pairs in string, time-online-O(n), space-O(n). 45 | 4. PostfixExpressionManager: evaluate a postfix expression(time-O(n), space-O(1)) or convert an infix expression to postfix expression(time-O(n), space-O(N)). 46 | 5. SelectionSort: selection sort, time-O(n^2), space-O(1). 47 | 6. insertionSort: insertion sort, time-O(n)~O(n^2), space-O(1). 48 | 7. shellSort: shell sort, time-O(n)~O(n^(3/2))(faster than insertion sort), space-O(1). 49 | 8. mergeSort: merge sort, time-O(n * log(n)), space-O(Pn). 50 | 9. quickSort: quick sort, optimized by insertion sort, median3 and 3way, time-O(n * log(n)), space-O(n). 51 | 10. heapSort: heap sort, time-O(n * log(n)), space-O(n). 52 | 11. binarySearch: binary search, time-O(log(n)), space-O(1). 53 | 12. GraphDFS, GraphPathsDFS, GraphPathsBFS: algorithms for searching in graphs. 54 | 13. DigraphDFS, DigraphPathsDFS, DigraphPathsBFS: algorithms for searching in graphs. 55 | 14. DigraphFindCycle: find the cycle in an digraph. 56 | 15. DigraphDFO: depth-first-order algorithm for digraph. 57 | 16. DigraphTopological: topological sorting for an non-cycle digraph. 58 | 17. DigraphSCCKosaraju: find all strongly connected components in a digraph. 59 | 18. UnionFind: a tool class to solve problems about dynamic connectivity. 60 | 19. WeightedGraphMSTPrim: find the Minimum Spanning Tree for a weighted graph with prim algorithm. 61 | 20. WeightedGraphMSTKruskal: find the Minimum Spanning Tree for a weighted graph with kruskal algorithm. 62 | 21. WeightedDigraphSPDijkstra: find the shortest path for a connected weighted digraph which has no negative weight with dijkstra algorithm. 63 | 21. WeightedDigraphSPAcyclic: find the shortest path for a weighted DAG with a simple and fast algorithm. 64 | 65 | ### Ruby 66 | 67 | 1. Sorting: sortings for string, includes msd, lsd, q3w. 68 | 69 | ### LeetCode 70 | 71 | 1. add_two_numbers 72 | 2. longest_palindrome 73 | 3. minimum_time_difference 74 | 4. sum 75 | -------------------------------------------------------------------------------- /Ruby/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | -------------------------------------------------------------------------------- /Ruby/LeetCode/add_two_numbers.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | Author: Dai Tianyu(dtysky) 3 | Github: https://github.com/dtysky 4 | Created: 2017/6/4 5 | =end 6 | 7 | # You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. 8 | # 9 | # You may assume the two numbers do not contain any leading zero, except the number 0 itself. 10 | # 11 | # Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) 12 | # Output: 7 -> 0 -> 8 13 | 14 | # Definition for singly-linked list. 15 | class ListNode 16 | attr_accessor :val, :next 17 | def initialize(val) 18 | @val = val 19 | @next = nil 20 | end 21 | 22 | def to_s 23 | res = "[" 24 | node = self 25 | while node != nil 26 | res += "#{node.val}" 27 | if node.next 28 | res += ', ' 29 | end 30 | node = node.next 31 | end 32 | res += ']' 33 | end 34 | end 35 | 36 | # @param {ListNode} l1 37 | # @param {ListNode} l2 38 | # @return {ListNode} 39 | def add_two_numbers(l1, l2) 40 | sum = l1.val + l2.val 41 | carry = sum / 10 42 | res = ListNode.new sum % 10 43 | res_copy = res 44 | n1 = l1.next 45 | n2 = l2.next 46 | 47 | while n1 != nil || n2 != nil 48 | if n1.nil? 49 | sum = n2.val + carry 50 | n2 = n2.next 51 | elsif n2.nil? 52 | sum = n1.val + carry 53 | n1 = n1.next 54 | else 55 | sum = n1.val + n2.val + carry 56 | n1 = n1.next 57 | n2 = n2.next 58 | end 59 | 60 | carry = sum / 10 61 | res.next = ListNode.new sum % 10 62 | res = res.next 63 | end 64 | 65 | if carry == 1 66 | res.next = ListNode.new 1 67 | end 68 | 69 | res_copy 70 | end 71 | 72 | def gen_num array 73 | node = ListNode.new array[0] 74 | node_copy = node 75 | (1..array.length - 1).each do |i| 76 | node_copy.next = ListNode.new array[i] 77 | node_copy = node_copy.next 78 | end 79 | node 80 | end 81 | 82 | l1 = gen_num [5] 83 | l2 = gen_num [5] 84 | print add_two_numbers l1, l2 85 | -------------------------------------------------------------------------------- /Ruby/LeetCode/find_smallest_letter_greater_than_target.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | Author: Dai Tianyu(dtysky) 3 | Github: https://github.com/dtysky 4 | Created: 2018/4/4 5 | =end 6 | 7 | =begin 8 | Given a list of sorted characters letters containing only lowercase letters, and given a target letter target, find the smallest element in the list that is larger than the given target. 9 | 10 | Letters also wrap around. For example, if the target is target = 'z' and letters = ['a', 'b'], the answer is 'a'. 11 | 12 | Examples: 13 | Input: 14 | letters = ["c", "f", "j"] 15 | target = "a" 16 | Output: "c" 17 | 18 | Input: 19 | letters = ["c", "f", "j"] 20 | target = "c" 21 | Output: "f" 22 | 23 | Input: 24 | letters = ["c", "f", "j"] 25 | target = "d" 26 | Output: "f" 27 | 28 | Input: 29 | letters = ["c", "f", "j"] 30 | target = "g" 31 | Output: "j" 32 | 33 | Input: 34 | letters = ["c", "f", "j"] 35 | target = "j" 36 | Output: "c" 37 | 38 | Input: 39 | letters = ["c", "f", "j"] 40 | target = "k" 41 | Output: "c" 42 | Note: 43 | letters has a length in range [2, 10000]. 44 | letters consists of lowercase letters, and contains at least 2 unique letters. 45 | target is a lowercase letter. 46 | =end 47 | require 'set' 48 | 49 | # @param {Character[]} letters 50 | # @param {Character} target 51 | # @return {Character} 52 | def next_greatest_letter_unsorted(letters, target) 53 | letter_set = Set[] 54 | letters.each { |letter| letter_set.add letter } 55 | 56 | diff = 100 57 | result = '' 58 | 59 | target_ascii = target.bytes[0] 60 | max = 'z'.bytes[0] - target_ascii - 'a'.bytes[0] + 1 61 | 62 | letter_set.map do |letter| 63 | letter_ascii = letter.bytes[0] 64 | d = letter_ascii - target_ascii 65 | 66 | if d == 1 67 | letter 68 | end 69 | 70 | if d <= 0 71 | d = max + letter_ascii 72 | end 73 | 74 | if d < diff 75 | diff = d 76 | result = letter 77 | end 78 | 79 | end 80 | 81 | result 82 | end 83 | 84 | # sorted, using binary search! 85 | # @param {Character[]} letters 86 | # @param {Character} target 87 | # @return {Character} 88 | def next_greatest_letter(letters, target) 89 | left = 0 90 | right = letters.length - 1 91 | 92 | while left < right - 1 do 93 | middle = (left + right) / 2 94 | if target < letters[middle] 95 | right = middle 96 | else 97 | left = middle 98 | end 99 | end 100 | 101 | if target < letters[left] 102 | return letters[left] 103 | end 104 | 105 | if target < letters[right] 106 | return letters[right] 107 | end 108 | 109 | letters[0] 110 | 111 | end 112 | 113 | 114 | letters = ["b","c","d","e","f","g","h","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"] 115 | target = 'a' 116 | 117 | p next_greatest_letter letters, target 118 | 119 | 120 | -------------------------------------------------------------------------------- /Ruby/LeetCode/longest_palindrome.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | Author: Dai Tianyu(dtysky) 3 | Github: https://github.com/dtysky 4 | Created: 2017/6/6 5 | =end 6 | 7 | # Given a string which consists of lowercase or uppercase letters, find the length of the longest palindromes that can be built with those letters. 8 | # 9 | # This is case sensitive, for example "Aa" is not considered a palindrome here. 10 | # 11 | # Note: 12 | # Assume the length of given string will not exceed 1,010. 13 | # 14 | # Example: 15 | # 16 | # Input: 17 | # "abccccdd" 18 | # 19 | # Output: 20 | # 7 21 | # 22 | # Explanation: 23 | # One longest palindrome that can be built is "dccaccd", whose length is 7. 24 | 25 | 26 | # @param {String} s 27 | # @return {Integer} 28 | def longest_palindrome(s) 29 | map = {} 30 | s.each_byte do |byte| 31 | if map.include? byte 32 | map[byte] += 1 33 | else 34 | map[byte] = 1 35 | end 36 | end 37 | 38 | res = 0 39 | center_inserted = false 40 | map.each_value do |num| 41 | if num % 2 == 1 && !center_inserted 42 | res += num 43 | center_inserted = true 44 | next 45 | end 46 | res += num / 2 * 2 47 | end 48 | res 49 | end 50 | 51 | i = 'civilwartestingwhetherthatnaptionoranynartionsoconceivedandsodedicatedcanlongendureWeareqmetonagreatbattlefiemldoftzhatwarWehavecometodedicpateaportionofthatfieldasafinalrestingplaceforthosewhoheregavetheirlivesthatthatnationmightliveItisaltogetherfangandproperthatweshoulddothisButinalargersensewecannotdedicatewecannotconsecratewecannothallowthisgroundThebravelmenlivinganddeadwhostruggledherehaveconsecrateditfaraboveourpoorponwertoaddordetractTgheworldadswfilllittlenotlenorlongrememberwhatwesayherebutitcanneverforgetwhattheydidhereItisforusthelivingrathertobededicatedheretotheulnfinishedworkwhichtheywhofoughtherehavethusfarsonoblyadvancedItisratherforustobeherededicatedtothegreattdafskremainingbeforeusthatfromthesehonoreddeadwetakeincreaseddevotiontothatcauseforwhichtheygavethelastpfullmeasureofdevotionthatweherehighlyresolvethatthesedeadshallnothavediedinvainthatthisnationunsderGodshallhaveanewbirthoffreedomandthatgovernmentofthepeoplebythepeopleforthepeopleshallnotperishfromtheearth' 52 | print longest_palindrome i 53 | -------------------------------------------------------------------------------- /Ruby/LeetCode/minimum_time_difference.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | Author: Dai Tianyu(dtysky) 3 | Github: https://github.com/dtysky 4 | Created: 2017/6/5 5 | =end 6 | 7 | # Given a list of 24-hour clock time points in "Hour:Minutes" format, find the minimum minutes difference between any two time points in the list. 8 | # 9 | # Example 1: 10 | # Input: ["23:59","00:00"] 11 | # Output: 1 12 | # Note: 13 | # The number of time points in the given list is at least 2 and won't exceed 20000. 14 | # The input time is legal and ranges from 00:00 to 23:59. 15 | 16 | def time_to_int time 17 | h, m = (time.split ':').map { |s| s.to_i} 18 | h * 60 + m 19 | end 20 | 21 | # @param {String[]} time_points 22 | # @return {Integer} 23 | def find_min_difference(time_points) 24 | diff= Array.new time_points.length, 1440 25 | map = {} 26 | points = [] 27 | for point in time_points 28 | if map.include? point 29 | return 0 30 | end 31 | map[point] = 0 32 | points.push time_to_int point 33 | end 34 | points = points.sort 35 | len = points.length 36 | (0..len - 2).each do |i| 37 | diff[i] = points[i + 1] - points[i] 38 | end 39 | diff[len] = points[0] + 1440 - points[len - 1] 40 | diff.min 41 | end 42 | 43 | i = ["23:59", "00:00"] 44 | print find_min_difference i 45 | -------------------------------------------------------------------------------- /Ruby/LeetCode/n_queue.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | Author: Dai Tianyu(dtysky) 3 | Github: https://github.com/dtysky 4 | Created: 2018/1/13 5 | =end 6 | 7 | def print_matrix array, n 8 | p '' 9 | n.times do |y| 10 | a = [] 11 | n.times {|x| a.push x == array[y] ? 1 : 0} 12 | p a 13 | end 14 | p '' 15 | end 16 | 17 | def in_diagonal r1, c1, r2, c2 18 | r1 - r2 == c1 - c2 or r1 - r2 == -(c1 - c2) 19 | end 20 | 21 | def in_col r1, c1, r2, c2 22 | c1 == c2 23 | end 24 | 25 | def conflict r1, c1, r2, c2 26 | in_diagonal r1, c1, r2, c2 or in_col r1, r2, c1, c2 27 | end 28 | 29 | def n_queue n 30 | rows = [] 31 | cols = [] 32 | current_row = 0 33 | current_col = 0 34 | 35 | while current_row < n 36 | rows = rows.slice(0, current_row) 37 | current_row += 1 38 | 39 | (current_col..n).times do |col| 40 | catch :outer do 41 | (0..current_row).times do |row| 42 | if conflict current_row, col, row, rows[row] 43 | throw :outer 44 | end 45 | rows.push col 46 | break 47 | end 48 | end 49 | end 50 | 51 | end 52 | 53 | raise "No solution !" 54 | end 55 | 56 | p n_queue 8 57 | -------------------------------------------------------------------------------- /Ruby/LeetCode/shortest_palindrome.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | Author: Dai Tianyu(dtysky) 3 | Github: https://github.com/dtysky 4 | Created: 2017/6/7 5 | =end 6 | 7 | # Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. Find and return the shortest palindrome you can find by performing this transformation. 8 | # 9 | # For example: 10 | # 11 | # Given "aacecaaa", return "aaacecaaa". 12 | # 13 | # Given "abcd", return "dcbabcd". 14 | # 15 | # Credits: 16 | # Special thanks to @ifanchu for adding this problem and creating all test cases. Thanks to @Freezen for additional test cases. 17 | 18 | # @param {String} s 19 | # @return {String} 20 | def shortest_palindrome(s) 21 | len = s.length 22 | 23 | if len == 1 24 | return s 25 | end 26 | 27 | center = len / 2 28 | tmp = s 29 | 30 | if len % 2 == 1 31 | tmp = s.substr(0, center - 1) + s.substr(center + 1, len) 32 | len -= 1 33 | end 34 | 35 | stack = [] 36 | 37 | i = len 38 | while i >= 0 39 | char = tmp[i] 40 | print stack, " ", char, "\n" 41 | if stack[stack.length - 1] == char 42 | stack.pop 43 | else 44 | stack.push char 45 | end 46 | 47 | i -= 1 48 | end 49 | 50 | (stack.reverse.join '') + s 51 | end 52 | 53 | i = 'aacecaaa' 54 | shortest_palindrome i 55 | -------------------------------------------------------------------------------- /Ruby/LeetCode/sum.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | Author: Dai Tianyu(dtysky) 3 | Github: https://github.com/dtysky 4 | Created: 2017/6/1 5 | =end 6 | 7 | # Given an array of integers, return indices of the two numbers such that they add up to a specific target. 8 | # 9 | # You may assume that each input would have exactly one solution, and you may not use the same element twice. 10 | # 11 | # Example: 12 | # Given nums = [2, 7, 11, 15], target = 9, 13 | # 14 | # Because nums[0] + nums[1] = 2 + 7 = 9, 15 | # return [0, 1]. 16 | 17 | # Use hash map could always reduce a layer of overhead 18 | def two_sum(nums, target) 19 | map = {} 20 | len = nums.length 21 | len.times do |i| 22 | complement = target - nums[i] 23 | if map.include? complement 24 | return [i, map[complement]] 25 | end 26 | map[nums[i]] = i 27 | end 28 | raise "No solution !" 29 | end 30 | 31 | # Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number. 32 | # 33 | # The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based. 34 | # 35 | # You may assume that each input would have exactly one solution and you may not use the same element twice. 36 | # 37 | # Input: numbers={2, 7, 11, 15}, target=9 38 | # Output: index1=1, index2=2 39 | 40 | # An application of binary search 41 | def two_sum_2(numbers, target) 42 | left = 0 43 | right = numbers.length - 1 44 | while left < right 45 | sum = numbers[left] + numbers[right] 46 | if sum == target 47 | return [left + 1, right + 1] 48 | # already sorted 49 | elsif sum < target 50 | left += 1 51 | else 52 | right -= 1 53 | end 54 | end 55 | raise "No solution !" 56 | end 57 | 58 | nums = [2,3,4] 59 | target = 6 60 | print two_sum_2 nums, target 61 | 62 | -------------------------------------------------------------------------------- /Ruby/String/alphabet.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | Author: Dai Tianyu(dtysky) 3 | Github: https://github.com/dtysky 4 | Created: 2017/3/25 5 | =end 6 | module MyString 7 | class Alphabet 8 | def initialize str 9 | @table = [] 10 | str.split('').each do |char| 11 | if not @table.include? char 12 | @table.push char 13 | end 14 | end 15 | @radix = @table.length 16 | end 17 | 18 | def to_char index 19 | @table[index] 20 | end 21 | 22 | def to_index char 23 | index = @table.index char 24 | index == nil ? -1 : index 25 | end 26 | 27 | def contains char 28 | @table.include? char 29 | end 30 | 31 | def radix 32 | @radix 33 | end 34 | 35 | def lg_radix 36 | (Math.sqrt @radix).to_int + 1 37 | end 38 | 39 | def to_indices str 40 | str.split('').map do |char| 41 | if @table.include? char 42 | @table.index char 43 | else 44 | raise "This alphabet does not has char #{char} !" 45 | end 46 | end 47 | end 48 | 49 | def to_chars indices 50 | indices.map do |index| 51 | if @radix > index 52 | @table[index] 53 | else 54 | raise "This alphabet only has #{@radix} characters !" 55 | end 56 | end 57 | end 58 | 59 | def to_s 60 | @table.to_s 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /Ruby/String/alphabet_test.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | Author: Dai Tianyu(dtysky) 3 | Github: https://github.com/dtysky 4 | Created: 2017/3/25 5 | =end 6 | require 'test/unit' 7 | require './alphabet' 8 | 9 | class MyTest < Test::Unit::TestCase 10 | 11 | # Called before every test method runs. Can be used 12 | # to set up fixture information. 13 | def setup 14 | @ab = MyString::Alphabet.new 'dtysky' 15 | end 16 | 17 | # Called after every test method runs. Can be used to tear 18 | # down fixture information. 19 | 20 | def teardown 21 | # Do nothing 22 | end 23 | 24 | def test_constructor 25 | assert @ab.to_s == '["d", "t", "y", "s", "k"]' 26 | puts @ab.to_s 27 | end 28 | 29 | def test_radix 30 | assert @ab.radix == 5 31 | assert @ab.lg_radix == 3 32 | print @ab.radix, " ", @ab.lg_radix 33 | puts 34 | end 35 | 36 | def test_to_char_and_to_index 37 | @ab.radix.times do |index| 38 | char = @ab.to_char index 39 | print char, " ", @ab.to_index(char) 40 | puts 41 | end 42 | end 43 | 44 | def test_to_indices 45 | p @ab.to_indices 'dtysky' 46 | begin 47 | @ab.to_indices '1' 48 | rescue => err 49 | puts err.message 50 | end 51 | end 52 | 53 | def test_to_chars 54 | p @ab.to_chars [0, 1, 2, 3, 4] 55 | begin 56 | @ab.to_chars [5] 57 | rescue => err 58 | puts err.message 59 | end 60 | end 61 | end -------------------------------------------------------------------------------- /Ruby/String/sorting.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | Author: Dai Tianyu(dtysky) 3 | Github: https://github.com/dtysky 4 | Created: 2017/3/26 5 | =end 6 | module MyString 7 | class StringSorter 8 | def initialize alphabet 9 | @alphabet = alphabet 10 | end 11 | 12 | def lsd str_array, str_width 13 | n = str_array.length 14 | r = @alphabet.radix 15 | (0..str_width - 1).reverse_each do |d| 16 | count = Array.new(r + 1).fill(0) 17 | 18 | n.times do |i| 19 | key = @alphabet.to_index(str_array[i][d]) 20 | count[key + 1] += 1 21 | end 22 | 23 | r.times do |i| 24 | count[i + 1] += count[i] 25 | end 26 | 27 | tmp = [] 28 | n.times do |i| 29 | key = @alphabet.to_index(str_array[i][d]) 30 | tmp[count[key]] = str_array[i] 31 | count[key] += 1 32 | end 33 | 34 | str_array = tmp 35 | end 36 | str_array 37 | end 38 | 39 | def msd str_array 40 | n = str_array.length 41 | msd_sort(str_array, 0, n - 1, 0) 42 | str_array 43 | end 44 | 45 | def msd_sort str_array, l, h, d 46 | if h <= l 47 | return 48 | end 49 | 50 | r = @alphabet.radix 51 | count = Array.new(r + 2).fill(0) 52 | 53 | # print l, " ", h, " ", d, "\n" 54 | # print str_array, "\n" 55 | 56 | (l..h).each do |i| 57 | count[msd_to_index(str_array[i], d) + 1] += 1 58 | end 59 | 60 | r.times do |i| 61 | count[i + 1] += count[i] 62 | end 63 | 64 | tmp = [] 65 | (l..h).each do |i| 66 | key = msd_to_index(str_array[i], d) 67 | tmp[count[key]] = str_array[i] 68 | count[key] += 1 69 | end 70 | 71 | (l..h).each do |i| 72 | str_array[i] = tmp[i - l] 73 | end 74 | 75 | # print count, "\n" 76 | r.times do |i| 77 | msd_sort(str_array, l + count[i], l + count[i + 1] - 1, d + 1) 78 | end 79 | end 80 | private :msd_sort 81 | 82 | def msd_to_index str, d 83 | (@alphabet.to_index str[d]) + 1 84 | end 85 | private :msd_to_index 86 | 87 | def q3w str_array 88 | q3w_sort str_array, 0, str_array.length - 1, 0 89 | str_array 90 | end 91 | 92 | def q3w_sort str_array, l, h, d 93 | if h <= l 94 | return 95 | end 96 | 97 | lt = l 98 | gt = h 99 | i = l + 1 100 | v = @alphabet.to_index str_array[l][d] 101 | 102 | while i <= gt 103 | t = @alphabet.to_index str_array[i][d] 104 | if t < v 105 | exch(str_array, lt, i) 106 | lt += 1 107 | i += 1 108 | elsif t > v 109 | exch(str_array, i, gt) 110 | gt -= 1 111 | else 112 | i += 1 113 | end 114 | end 115 | 116 | q3w_sort str_array, l, lt - 1, d 117 | if v >= 0 118 | q3w_sort(str_array, lt, gt, d + 1) 119 | end 120 | q3w_sort(str_array, gt + 1, h, d) 121 | end 122 | private :q3w_sort 123 | 124 | def exch str, i, j 125 | tmp = str[i] 126 | str[i] = str[j] 127 | str[j] = tmp 128 | end 129 | private :exch 130 | end 131 | end -------------------------------------------------------------------------------- /Ruby/String/sorting_test.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | Author: Dai Tianyu(dtysky) 3 | Github: https://github.com/dtysky 4 | Created: 2017/3/25 5 | =end 6 | require 'test/unit' 7 | require './alphabet' 8 | require './sorting' 9 | 10 | class MyTest < Test::Unit::TestCase 11 | 12 | # Called before every test method runs. Can be used 13 | # to set up fixture information. 14 | def setup 15 | @sorter = MyString::StringSorter.new MyString::Alphabet.new '0123456789' 16 | end 17 | 18 | # Called after every test method runs. Can be used to tear 19 | # down fixture information. 20 | 21 | def teardown 22 | # Do nothing 23 | end 24 | 25 | # Fake test 26 | def test_lsd 27 | str_array = %w[ 28 | 1234 29 | 3256 30 | 2345 31 | 1367 32 | 0927 33 | 0928 34 | 4823 35 | 4028 36 | 8123 37 | 1234 38 | ] 39 | puts 'lsd' 40 | puts @sorter.lsd str_array, 4 41 | end 42 | 43 | def test_msd 44 | str_array = %w[ 45 | 12345 46 | 325 47 | 235 48 | 137 49 | 0928 50 | 0927 51 | 423 52 | 4028 53 | 8123 54 | 1234 55 | ] 56 | puts 'msd' 57 | puts @sorter.msd str_array 58 | end 59 | 60 | def test_q3w 61 | str_array = %w[ 62 | 12345 63 | 325 64 | 235 65 | 137 66 | 0928 67 | 0927 68 | 423 69 | 4028 70 | 8123 71 | 1234 72 | ] 73 | puts 'q3w' 74 | puts @sorter.q3w str_array 75 | end 76 | end -------------------------------------------------------------------------------- /Tests/avl_tree.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // avl_tree 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/12/11. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include "avl_tree.h" 13 | 14 | 15 | namespace data_structures { 16 | using std::cout; 17 | using std::endl; 18 | 19 | void testAVLTree() { 20 | AVLTree tree; 21 | // AVLTree tree; 22 | cout << tree.isEmpty() << endl; 23 | 24 | // for (auto key: std::vector{"e", "b", "c", "a", "d", "f", "aa", "bb", "cc", "dd", "ee"}) { 25 | // cout << key << ":" << endl << tree.set(key, key) << endl; 26 | // } 27 | // 28 | tree.set("e", 0) 29 | .set("b", 1) 30 | .set("c", 2) 31 | .set("a", 3) 32 | .set("d", 4) 33 | .set("f", 5) 34 | .set("aa", 12) 35 | .set("bb", 32) 36 | .set("cc", 2231) 37 | .set("dd", 4233) 38 | .set("ee", 444); 39 | cout << tree << endl; 40 | cout << tree.size() << endl; 41 | cout << tree.get("a") << endl; 42 | tree.set("a", 334); 43 | cout << tree.get("a") << endl; 44 | 45 | for (auto key: std::vector{"a", "b", "c", "d", "e", "f", "aa", "bb", "cc", "dd", "ee"}) { 46 | cout << key << " " << tree.rank(key) << endl; 47 | } 48 | 49 | for (auto rank: std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) { 50 | cout << rank << " " << tree.select(rank) << endl; 51 | } 52 | 53 | auto tree1 = tree; 54 | cout << (tree == tree1) << endl; 55 | 56 | for (auto key: std::vector{"a", "b", "c", "d", "e", "f", "aa", "bb", "cc", "dd", "ee"}) { 57 | cout << "key, value: " << endl << key << ", " << tree.del(key) << endl; 58 | cout << "tree:" << endl << tree << endl; 59 | } 60 | 61 | cout << tree << endl; 62 | cout << tree1.isEmpty() << endl; 63 | tree1.clear(); 64 | cout << tree1 << endl; 65 | cout << tree1.isEmpty() << endl; 66 | cout << tree.get("a") << endl; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Tests/binary_heap.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // binary_heap 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/8. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include "binary_heap.h" 10 | 11 | 12 | namespace data_structures { 13 | using std::cout; 14 | using std::endl; 15 | 16 | void testBinaryHeap() { 17 | MaxBinaryHeap max_heap; 18 | max_heap.insert(0) 19 | .insert(1) 20 | .insert(2) 21 | .insert(3) 22 | .insert(4) 23 | .insert(5) 24 | .insert(6) 25 | .insert(7) 26 | .insert(8) 27 | .insert(9) 28 | .insert(10); 29 | cout << max_heap << endl; 30 | cout << max_heap.top() << endl; 31 | cout << max_heap.isEmpty() << endl; 32 | auto max_heap1 = max_heap; 33 | while (!max_heap.isEmpty()) { 34 | cout << max_heap.deleteTop() << endl; 35 | cout << max_heap << endl; 36 | } 37 | cout << max_heap.isEmpty() << endl; 38 | cout << max_heap1 << endl; 39 | max_heap1.clear(); 40 | cout << max_heap1 << endl; 41 | MinBinaryHeap min_heap; 42 | min_heap.insert(0) 43 | .insert(1) 44 | .insert(2) 45 | .insert(3) 46 | .insert(4) 47 | .insert(5) 48 | .insert(6) 49 | .insert(7) 50 | .insert(8) 51 | .insert(9) 52 | .insert(10); 53 | cout << min_heap << endl; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Tests/binary_search.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // binary_search 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/13. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "binary_search.h" 11 | #include "utils.h" 12 | #include 13 | 14 | 15 | namespace my_algorithm { 16 | using std::cout; 17 | using std::endl; 18 | using std::vector; 19 | 20 | void testBinarySearch(){ 21 | auto v1 = vector(10000); 22 | fillVectorWithRangeNumbers(v1, 10000); 23 | auto tmp = refSort(v1); 24 | 25 | auto tStart = clock(); 26 | cout << binarySearch(v1, 9328) << endl; 27 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 28 | 29 | v1 = vector(20000); 30 | fillVectorWithRangeNumbers(v1, 20000); 31 | 32 | tStart = clock(); 33 | cout << binarySearch(v1, 19328) << endl; 34 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Tests/binary_search_tree.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // binary_search_tree 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/24. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "binary_search_tree.h" 11 | #include 12 | #include 13 | 14 | 15 | namespace data_structures { 16 | using std::cout; 17 | using std::endl; 18 | void testBinarySearchTree(){ 19 | BinarySearchTree tree; 20 | cout << tree.isEmpty() << endl; 21 | 22 | tree.set("e", 0) 23 | .set("b", 1) 24 | .set("c", 2) 25 | .set("a", 3) 26 | .set("d", 4) 27 | .set("f", 5) 28 | .set("aa", 12) 29 | .set("bb", 32) 30 | .set("cc", 2231) 31 | .set("dd", 4233) 32 | .set("ee", 444); 33 | cout << tree << endl; 34 | cout << tree.size() << endl; 35 | cout << tree.get("a") << endl; 36 | tree.set("a", 334); 37 | cout << tree.get("a") << endl; 38 | 39 | for (auto key: std::vector{"a", "b", "c", "d", "e", "f", "aa", "bb", "cc", "dd", "ee"}) { 40 | cout << key << " " << tree.rank(key) << endl; 41 | } 42 | 43 | for (auto rank: std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) { 44 | cout << rank << " " << tree.select(rank) << endl; 45 | } 46 | 47 | auto tree1 = tree; 48 | cout << (tree == tree1) << endl; 49 | 50 | for (auto key: std::vector{"a", "b", "c", "d", "e", "f", "aa", "bb", "cc", "dd", "ee"}) { 51 | cout << key << ":" << tree.del(key) << endl; 52 | cout << tree << endl; 53 | } 54 | 55 | cout << tree << endl; 56 | cout << tree1.isEmpty() << endl; 57 | tree1.clear(); 58 | cout << tree1 << endl; 59 | cout << tree1.isEmpty() << endl; 60 | cout << tree.get("a") << endl; 61 | } 62 | } -------------------------------------------------------------------------------- /Tests/bucket_sort.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // bucket_sort.hpp 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/31. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "bucket_sort.h" 11 | #include "utils.h" 12 | 13 | 14 | namespace my_algorithm { 15 | using std::cout; 16 | using std::endl; 17 | using std::vector; 18 | 19 | void testBucketSort(){ 20 | 21 | auto v1 = vector(10000); 22 | fillVectorWithRandomNumbers(v1, 10000); 23 | auto tmp = refSort(v1); 24 | printVector(tmp); 25 | 26 | auto tStart = clock(); 27 | bucketSort(v1, 10000); 28 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 29 | 30 | printVector(v1); 31 | compareTwoVectorsWithAssert(v1, tmp); 32 | 33 | tStart = clock(); 34 | bucketSort(v1, 10000, true); 35 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 36 | 37 | printVector(v1); 38 | 39 | v1 = vector(20000); 40 | fillVectorWithRandomNumbers(v1, 20000); 41 | 42 | tStart = clock(); 43 | bucketSort(v1, 20000); 44 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 45 | 46 | printVector(v1); 47 | } 48 | } -------------------------------------------------------------------------------- /Tests/digraph.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // digraph 3 | // Algorithm 4 | // 5 | // Created by dtysky on 2017/2/19. 6 | // Copyright © 2017 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_DIGRAPH_TEST_H 10 | #define ALGORITHM_DIGRAPH_TEST_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include "digraph.h" 16 | 17 | 18 | namespace data_structures { 19 | using std::cout; 20 | using std::endl; 21 | 22 | void testDigraph() { 23 | Digraph graph; 24 | cout << graph.isEmpty() << endl; 25 | cout << graph.vertexCount() << endl; 26 | cout << graph.edgeCount() << endl; 27 | 28 | // for (auto key: std::vector{"e", "b", "c", "a", "d", "f", "aa", "bb", "cc", "dd", "ee"}) { 29 | // cout << key << ":" << endl << graph.addVertex(key) << endl; 30 | // } 31 | 32 | graph.addVertex("e") 33 | .addVertex("b") 34 | .addVertex("c") 35 | .addVertex("a") 36 | .addVertex("d") 37 | .addVertex("f") 38 | .addVertex("aa") 39 | .addVertex("bb") 40 | .addVertex("cc") 41 | .addVertex("dd") 42 | .addVertex("ee"); 43 | cout << graph; 44 | cout << graph.vertexCount() << endl; 45 | cout << graph.edgeCount() << endl; 46 | cout << endl; 47 | 48 | graph.addEdge("e", "e") 49 | .addEdge("e", "a") 50 | .addEdge("e", "a") 51 | .addEdge("b", "a") 52 | .addEdge("c", "a") 53 | .addEdge("a", "b") 54 | .addEdge("d", "e") 55 | .addEdge("f", "e") 56 | .addEdge("aa", "e") 57 | .addEdge("bb", "e") 58 | .addEdge("cc", "e") 59 | .addEdge("dd", "e"); 60 | cout << graph; 61 | cout << graph.vertexCount() << endl; 62 | cout << graph.edgeCount() << endl; 63 | cout << graph.selfLoopsCount() << endl; 64 | for (auto &v: graph.adjVertex("e")) { 65 | cout << v << " "; 66 | } 67 | cout << endl; 68 | cout << graph.degree("e") << endl; 69 | cout << graph.degree("ee") << endl; 70 | cout << graph.maxDegree() << endl; 71 | cout << graph.avgDegree() << endl; 72 | cout << graph.hasVertex("e") << endl; 73 | cout << graph.hasVertex("eee") << endl; 74 | cout << graph.hasEdge("e", "a") << endl; 75 | cout << graph.hasEdge("ee", "a") << endl; 76 | cout << endl; 77 | 78 | cout << "<---- Copy ---->" << endl; 79 | auto graph1 = graph; 80 | cout << graph1; 81 | cout << (graph == graph1) << endl; 82 | cout << endl; 83 | 84 | cout << "<---- Delete ---->" << endl; 85 | graph.deleteEdge("e", "e") 86 | .deleteEdge("e", "a") 87 | .deleteEdge("b", "a") 88 | .deleteEdge("a", "b") 89 | .deleteEdge("c", "a") 90 | .deleteEdge("d", "e") 91 | .deleteEdge("f", "e"); 92 | cout << graph; 93 | cout << graph.vertexCount() << endl; 94 | cout << graph.edgeCount() << endl; 95 | cout << graph.selfLoopsCount() << endl; 96 | cout << endl; 97 | 98 | graph.deleteEdge("aa", "e") 99 | .deleteEdge("bb", "e") 100 | .deleteEdge("cc", "e") 101 | .deleteEdge("dd", "e"); 102 | cout << graph; 103 | cout << endl; 104 | 105 | graph.deleteVertex("e") 106 | .deleteVertex("b") 107 | .deleteVertex("c") 108 | .deleteVertex("a") 109 | .deleteVertex("d") 110 | .deleteVertex("f") 111 | .deleteVertex("aa") 112 | .deleteVertex("bb") 113 | .deleteVertex("cc") 114 | .deleteVertex("dd") 115 | .deleteVertex("ee"); 116 | cout << graph; 117 | cout << graph.vertexCount() << endl; 118 | cout << graph.edgeCount() << endl; 119 | cout << endl; 120 | 121 | cout << (graph == graph1) << endl << endl; 122 | 123 | cout << "<---- Reverse ---->" << endl; 124 | Digraph reversed_graph; 125 | graph1.reverse(reversed_graph); 126 | cout << graph1 << endl << "↓" << endl << endl << reversed_graph << endl; 127 | } 128 | } 129 | 130 | 131 | #endif //ALGORITHM_DIGRAPH_TEST_H 132 | -------------------------------------------------------------------------------- /Tests/digraph_algorithm.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // digraph_algorithm 3 | // Algorithm 4 | // 5 | // Created by dtysky on 2017/2/21. 6 | // Copyright © 2017 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_DIGRAPH_ALGORITHM_TEST_H 10 | #define ALGORITHM_DIGRAPH_ALGORITHM_TEST_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include "digraph.h" 16 | #include "digraph_algorithm.h" 17 | 18 | 19 | namespace my_algorithm { 20 | using std::cout; 21 | using std::endl; 22 | using data_structures::Digraph; 23 | 24 | void testDiraphAlgorithm() { 25 | Digraph graph; 26 | 27 | graph.addVertex("e") 28 | .addVertex("b") 29 | .addVertex("c") 30 | .addVertex("a") 31 | .addVertex("d") 32 | .addVertex("f") 33 | .addVertex("aa") 34 | .addVertex("bb") 35 | .addVertex("cc") 36 | .addVertex("dd") 37 | .addVertex("ee"); 38 | 39 | graph.addEdge("e", "a") 40 | .addEdge("e", "a") 41 | .addEdge("b", "a") 42 | .addEdge("a", "c") 43 | .addEdge("c", "d") 44 | .addEdge("d", "e") 45 | .addEdge("aa", "e") 46 | .addEdge("bb", "e") 47 | .addEdge("cc", "e") 48 | .addEdge("dd", "e") 49 | .addEdge("b", "c") 50 | .addEdge("c", "f") 51 | .addEdge("f", "d"); 52 | 53 | cout << graph << endl; 54 | 55 | cout << "<---- DigraphFindCycle ---->" << endl; 56 | auto a_find_cycle = DigraphFindCycle(graph); 57 | cout << a_find_cycle.hasCycle() << endl; 58 | if (a_find_cycle.hasCycle()) { 59 | for (auto &v: a_find_cycle.firstCycle()) { 60 | cout << v << " "; 61 | } 62 | } 63 | cout << endl << endl; 64 | 65 | graph.deleteEdge("e", "a") 66 | .deleteEdge("b", "a") 67 | .deleteEdge("a", "c") 68 | .deleteEdge("c", "d"); 69 | 70 | cout << "<---- DigraphDFO ---->" << endl; 71 | auto a_dfo = DigraphDFO(graph); 72 | cout << "<-- pre -->" << endl; 73 | for (auto &v: a_dfo.pre()) { 74 | cout << v << " "; 75 | } 76 | cout << endl; 77 | cout << "<-- post -->" << endl; 78 | for (auto &v: a_dfo.post()) { 79 | cout << v << " "; 80 | } 81 | cout << endl; 82 | cout << "<-- reversePost -->" << endl; 83 | for (auto &v: a_dfo.reversePost()) { 84 | cout << v << " "; 85 | } 86 | cout << endl << endl; 87 | 88 | cout << "<---- DigraphTopological ---->" << endl; 89 | auto a_topo = DigraphTopological(graph); 90 | for (auto &v: a_topo.order()) { 91 | cout << v << " "; 92 | } 93 | cout << endl << endl; 94 | 95 | 96 | Digraph graph1; 97 | for (int i = 0; i <= 12; i++) { 98 | graph1.addVertex(i); 99 | } 100 | 101 | graph1.addEdge(0, 1) 102 | .addEdge(0, 5) 103 | .addEdge(2, 0) 104 | .addEdge(2, 3) 105 | .addEdge(3, 2) 106 | .addEdge(3, 5) 107 | .addEdge(4, 2) 108 | .addEdge(4, 3) 109 | .addEdge(5, 4) 110 | .addEdge(6, 0) 111 | .addEdge(6, 4) 112 | .addEdge(6, 9) 113 | .addEdge(7, 6) 114 | .addEdge(7, 8) 115 | .addEdge(8, 7) 116 | .addEdge(8, 9) 117 | .addEdge(9, 10) 118 | .addEdge(9, 11) 119 | .addEdge(10, 12) 120 | .addEdge(11, 4) 121 | .addEdge(11, 12) 122 | .addEdge(12, 9); 123 | 124 | cout << "<---- DigraphSCCKosaraju ---->" << endl; 125 | cout << graph1 << endl; 126 | cout << "<---- scc ---->" << endl; 127 | auto a_scc = DigraphSCCKosaraju(graph1); 128 | for (auto &ccs: a_scc.scc()) { 129 | for (auto &v: ccs) { 130 | cout << v << " "; 131 | } 132 | cout << endl; 133 | } 134 | } 135 | } 136 | 137 | #endif //ALGORITHM_DIGRAPH_ALGORITHM_TEST_H 138 | -------------------------------------------------------------------------------- /Tests/graph.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // graph 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/12/16. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include "graph.h" 13 | 14 | 15 | namespace data_structures { 16 | using std::cout; 17 | using std::endl; 18 | 19 | void testGraph() { 20 | Graph graph; 21 | cout << graph.isEmpty() << endl; 22 | cout << graph.vertexCount() << endl; 23 | cout << graph.edgeCount() << endl; 24 | 25 | // for (auto key: std::vector{"e", "b", "c", "a", "d", "f", "aa", "bb", "cc", "dd", "ee"}) { 26 | // cout << key << ":" << endl << graph.addVertex(key) << endl; 27 | // } 28 | 29 | graph.addVertex("e") 30 | .addVertex("b") 31 | .addVertex("c") 32 | .addVertex("a") 33 | .addVertex("d") 34 | .addVertex("f") 35 | .addVertex("aa") 36 | .addVertex("bb") 37 | .addVertex("cc") 38 | .addVertex("dd") 39 | .addVertex("ee"); 40 | cout << graph; 41 | cout << graph.vertexCount() << endl; 42 | cout << graph.edgeCount() << endl; 43 | cout << endl; 44 | 45 | graph.addEdge("e", "e") 46 | .addEdge("e", "a") 47 | .addEdge("e", "a") 48 | .addEdge("b", "a") 49 | .addEdge("c", "a") 50 | .addEdge("a", "b") 51 | .addEdge("d", "e") 52 | .addEdge("f", "e") 53 | .addEdge("aa", "e") 54 | .addEdge("bb", "e") 55 | .addEdge("cc", "e") 56 | .addEdge("dd", "e"); 57 | cout << graph; 58 | cout << graph.vertexCount() << endl; 59 | cout << graph.edgeCount() << endl; 60 | cout << graph.selfLoopsCount() << endl; 61 | for (auto &v: graph.adjVertex("e")) { 62 | cout << v << " "; 63 | } 64 | cout << endl; 65 | cout << graph.degree("e") << endl; 66 | cout << graph.degree("ee") << endl; 67 | cout << graph.maxDegree() << endl; 68 | cout << graph.avgDegree() << endl; 69 | cout << graph.hasVertex("e") << endl; 70 | cout << graph.hasVertex("eee") << endl; 71 | cout << graph.hasEdge("e", "a") << endl; 72 | cout << graph.hasEdge("ee", "a") << endl; 73 | cout << endl; 74 | 75 | auto graph1 = graph; 76 | cout << graph1; 77 | cout << (graph == graph1) << endl; 78 | cout << endl; 79 | 80 | graph.deleteEdge("e", "e") 81 | .deleteEdge("e", "a") 82 | .deleteEdge("b", "a") 83 | .deleteEdge("c", "a") 84 | .deleteEdge("d", "e") 85 | .deleteEdge("f", "e"); 86 | cout << graph; 87 | cout << graph.vertexCount() << endl; 88 | cout << graph.edgeCount() << endl; 89 | cout << graph.selfLoopsCount() << endl; 90 | cout << endl; 91 | 92 | graph.deleteEdge("aa", "e") 93 | .deleteEdge("bb", "e") 94 | .deleteEdge("cc", "e") 95 | .deleteEdge("dd", "e"); 96 | cout << graph; 97 | cout << endl; 98 | 99 | graph.deleteVertex("e") 100 | .deleteVertex("b") 101 | .deleteVertex("c") 102 | .deleteVertex("a") 103 | .deleteVertex("d") 104 | .deleteVertex("f") 105 | .deleteVertex("aa") 106 | .deleteVertex("bb") 107 | .deleteVertex("cc") 108 | .deleteVertex("dd") 109 | .deleteVertex("ee"); 110 | cout << graph; 111 | cout << graph.vertexCount() << endl; 112 | cout << graph.edgeCount() << endl; 113 | cout << endl; 114 | 115 | cout << (graph == graph1) << endl; 116 | 117 | graph1.clear(); 118 | cout << graph1 << endl; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Tests/grapha_algorithm.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // grapha_algorithm 3 | // Algorithm 4 | // 5 | // Created by dtysky on 17/1/26. 6 | // Copyright © 2017 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_GRAPHA_ALGORITHM_TEST_H 10 | #define ALGORITHM_GRAPHA_ALGORITHM_TEST_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include "graph.h" 16 | #include "graph_algorithm.h" 17 | 18 | 19 | namespace my_algorithm { 20 | using std::cout; 21 | using std::endl; 22 | using data_structures::Graph; 23 | 24 | void testGraphAlgorithm() { 25 | Graph graph; 26 | 27 | graph.addVertex("e") 28 | .addVertex("b") 29 | .addVertex("c") 30 | .addVertex("a") 31 | .addVertex("d") 32 | .addVertex("f") 33 | .addVertex("aa") 34 | .addVertex("bb") 35 | .addVertex("cc") 36 | .addVertex("dd") 37 | .addVertex("ee"); 38 | 39 | graph.addEdge("e", "e") 40 | .addEdge("e", "a") 41 | .addEdge("e", "a") 42 | .addEdge("b", "a") 43 | .addEdge("c", "a") 44 | .addEdge("a", "b") 45 | .addEdge("d", "e") 46 | .addEdge("aa", "e") 47 | .addEdge("bb", "e") 48 | .addEdge("cc", "e") 49 | .addEdge("dd", "e") 50 | .addEdge("b", "c") 51 | .addEdge("c", "f") 52 | .addEdge("f", "d"); 53 | 54 | cout << graph << endl; 55 | 56 | cout << "<---- GraphDFS ---->" << endl; 57 | auto a_dfs = GraphDFS(graph, "e"); 58 | cout << a_dfs.count() << endl; 59 | a_dfs.print(); 60 | cout << endl; 61 | for (auto key: std::vector{"e", "b", "c", "a", "d", "f", "aa", "bb", "cc", "dd", "ee"}) { 62 | cout << key << ":" << a_dfs.marked(key) << endl; 63 | } 64 | cout << endl; 65 | 66 | cout << "<---- GraphPathsDFS ---->" << endl; 67 | auto a_path_dfs = GraphPathsDFS(graph, "e"); 68 | for (auto key: std::vector{"e", "b", "c", "a", "d", "f", "aa", "bb", "cc", "dd", "ee"}) { 69 | cout << "-> " << key << " - " << a_path_dfs.hasPathTo(key) << endl; 70 | } 71 | a_path_dfs.print(); 72 | cout << endl; 73 | 74 | cout << "<---- GraphPathsBFS ---->" << endl; 75 | auto a_path_bfs = GraphPathsBFS(graph, "e"); 76 | for (auto key: std::vector{"e", "b", "c", "a", "d", "f", "aa", "bb", "cc", "dd", "ee"}) { 77 | cout << "-> " << key << " - " << a_path_bfs.hasPathTo(key) << endl; 78 | } 79 | a_path_bfs.print(); 80 | } 81 | } 82 | 83 | #endif //ALGORITHM_GRAPHA_ALGORITHM_TEST_H 84 | -------------------------------------------------------------------------------- /Tests/hash_table.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // hash_table 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/12/13. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "hash_table.h" 11 | #include 12 | 13 | 14 | namespace data_structures { 15 | using std::cout; 16 | using std::endl; 17 | void testHashTable(){ 18 | auto table = HashTable(); 19 | cout << table.isEmpty() << endl; 20 | table.set("a", 0) 21 | .set("b", 1) 22 | .set("c", 2) 23 | .set("d", 3) 24 | .set("e", 4) 25 | .set("f", 5) 26 | .set("aa", 12) 27 | .set("bb", 32) 28 | .set("cc", 2231) 29 | .set("dd", 4233) 30 | .set("ee", 444); 31 | cout << table << endl; 32 | cout << table.size() << endl; 33 | cout << table.get("a") << endl; 34 | table.set("a", 334); 35 | cout << table.get("a") << endl; 36 | auto table1 = table; 37 | cout << table1 << endl; 38 | cout << (table == table1) << endl; 39 | for (auto element: table.elements()) { 40 | cout << element; 41 | } 42 | cout << endl; 43 | for (auto key: table.keys()) { 44 | cout << key << ": " << table.del(key) << endl; 45 | cout << table << table.size() << endl << endl; 46 | } 47 | cout << table.isEmpty() << endl; 48 | table1.clear(); 49 | cout << table1 << endl; 50 | cout << table.get("aaa") << endl; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /Tests/heap_sort.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // shell_sort 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/13. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "heap_sort.h" 11 | #include "utils.h" 12 | #include 13 | 14 | 15 | namespace my_algorithm { 16 | using std::cout; 17 | using std::endl; 18 | using std::vector; 19 | 20 | void testHeapSort(){ 21 | 22 | auto v1 = vector(10000); 23 | fillVectorWithRandomNumbers(v1, 10000); 24 | auto tmp = refSort(v1); 25 | printVector(tmp); 26 | 27 | auto tStart = clock(); 28 | heapSort(v1); 29 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 30 | 31 | printVector(v1); 32 | compareTwoVectorsWithAssert(v1, tmp); 33 | 34 | tStart = clock(); 35 | heapSort(v1, true); 36 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 37 | 38 | printVector(v1); 39 | 40 | v1 = vector(20000); 41 | fillVectorWithRandomNumbers(v1, 20000); 42 | 43 | tStart = clock(); 44 | heapSort(v1); 45 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 46 | 47 | printVector(v1); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Tests/insertion_sort.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // insertion_sort 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/11. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "insertion_sort.h" 11 | #include "utils.h" 12 | #include 13 | 14 | 15 | namespace my_algorithm { 16 | using std::cout; 17 | using std::endl; 18 | using std::vector; 19 | 20 | void testInsertionSort(){ 21 | 22 | auto v1 = vector(10000); 23 | fillVectorWithRandomNumbers(v1, 10000); 24 | auto tmp = refSort(v1); 25 | printVector(tmp); 26 | 27 | auto tStart = clock(); 28 | insertionSort(v1); 29 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 30 | 31 | printVector(v1); 32 | compareTwoVectorsWithAssert(v1, tmp); 33 | 34 | tStart = clock(); 35 | insertionSort(v1, true); 36 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 37 | 38 | printVector(v1); 39 | 40 | v1 = vector(20000); 41 | fillVectorWithRandomNumbers(v1, 20000); 42 | 43 | tStart = clock(); 44 | insertionSort(v1); 45 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 46 | 47 | printVector(v1); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Tests/linked_list.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // linked_list 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/24. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include "linked_list.h" 10 | 11 | 12 | namespace data_structures { 13 | void testLinkedList(){ 14 | LinkedList* list = new LinkedList(); 15 | cout << list->isEmpty() << "\n"; 16 | cout << list->header() << "\n"; 17 | cout << list->tail() << "\n"; 18 | list->insertToTail(1) 19 | ->insertToTail(2) 20 | ->insertToTail(3) 21 | ->insertToTail(4) 22 | ->insertToTail(5) 23 | ->insertToTail(6) 24 | ->insertToTail(7) 25 | ->insertToTail(8) 26 | ->insertToTail(9) 27 | ->insertToTail(10); 28 | cout << *list << "\n"; 29 | cout << list->size() << "\n"; 30 | cout << *list->getKthNode(5) << "\n"; 31 | cout << *list->getKthNode(0) << "\n"; 32 | cout << *list->getKthNode(9) << "\n"; 33 | cout << list->isEmpty() << "\n"; 34 | cout << list->header() << "\n"; 35 | cout << list->tail() << "\n"; 36 | cout << list->find(4) << "\n"; 37 | cout << list->findPrevious(9) << "\n"; 38 | cout << list->find(0) << "\n"; 39 | cout << list->findPrevious(1) << "\n"; 40 | cout << list->isTail(10) << "\n"; 41 | LinkedList* copy_list = new LinkedList(*list); 42 | cout << *copy_list << "\n"; 43 | LinkedList copy_list2 = *list; 44 | cout << copy_list2 << "\n"; 45 | cout << (*copy_list == copy_list2) << "\n"; 46 | list->del(1) 47 | ->del(5) 48 | ->del(10); 49 | cout << *list << "\n"; 50 | cout << list->size() << "\n"; 51 | list->insertToHeader(1); 52 | list->insert(4, 5) 53 | ->insert(9, 10) 54 | ->deleteFromHeader(); 55 | cout << *list << "\n"; 56 | list->clear(); 57 | cout << *list << "\n"; 58 | cout << list->size() << "\n"; 59 | list->del(1); 60 | delete list; 61 | delete copy_list; 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /Tests/list_node.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // list_node 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/22. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include "list_node.h" 10 | 11 | 12 | namespace data_structures { 13 | void testListNode(){ 14 | ListNode node; 15 | ListNode next_node = *new ListNode(1000, &node); 16 | ListNode copy_node = *new ListNode(next_node); 17 | cout << "node:\n" << node << "\n\n"; 18 | cout << "next_node:\n" << next_node << "\n\n"; 19 | cout << "copy_node:\n" << copy_node << "\n\n"; 20 | 21 | copy_node = node; 22 | cout << "copy_node:\n" << copy_node << "\n\n"; 23 | 24 | node.insertAfter(&next_node); 25 | node.element = next_node.element; 26 | cout << "insertAfter, setElement, getElement, getNext:\n" << node << " should equal " << node.next() << "\n" << "Equal: " << (*node.next() == next_node) << "\n\n"; 27 | 28 | node.deleteAfter(); 29 | cout << "deleteAfter:\n" << node << "\n"; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /Tests/merge_sort.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // merge_sort 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/13. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "merge_sort.h" 11 | #include "utils.h" 12 | #include 13 | 14 | 15 | namespace my_algorithm { 16 | using std::cout; 17 | using std::endl; 18 | using std::vector; 19 | 20 | void testMergeSort(){ 21 | 22 | auto v1 = vector(10000); 23 | fillVectorWithRandomNumbers(v1, 10000); 24 | auto tmp = refSort(v1); 25 | printVector(tmp); 26 | 27 | auto tStart = clock(); 28 | mergeSort(v1); 29 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 30 | 31 | printVector(v1); 32 | compareTwoVectorsWithAssert(v1, tmp); 33 | 34 | tStart = clock(); 35 | mergeSort(v1, true); 36 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 37 | 38 | printVector(v1); 39 | 40 | v1 = vector(20000); 41 | fillVectorWithRandomNumbers(v1, 20000); 42 | 43 | tStart = clock(); 44 | mergeSort(v1); 45 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 46 | 47 | printVector(v1); 48 | } 49 | } -------------------------------------------------------------------------------- /Tests/orderly_symbol_table.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // orderly_symbol_table 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/24. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include "orderly_symbol_table.h" 12 | 13 | 14 | namespace data_structures { 15 | using std::cout; 16 | using std::endl; 17 | void testOrderlySymbolTable(){ 18 | OrderlySymbolTable table; 19 | cout << table.isEmpty() << endl; 20 | table.set("a", 0) 21 | .set("b", 1) 22 | .set("c", 2) 23 | .set("d", 3) 24 | .set("e", 4) 25 | .set("f", 5) 26 | .set("aa", 12) 27 | .set("bb", 32) 28 | .set("cc", 2231) 29 | .set("dd", 4233) 30 | .set("ee", 444); 31 | cout << table << endl; 32 | cout << table.size() << endl; 33 | cout << table.get("a") << endl; 34 | table.set("a", 334); 35 | cout << table.get("a") << endl; 36 | auto table1 = table; 37 | cout << (table == table1) << endl; 38 | for (auto element: table.elements()) { 39 | cout << element << " "; 40 | } 41 | cout << endl; 42 | for (auto key: table.keys()) { 43 | cout << key << ": " << table.del(key) << endl; 44 | cout << table << endl; 45 | } 46 | cout << table.isEmpty() << endl; 47 | cout << table1.rankKey("aa") << endl; 48 | cout << table1.sizeBetweenKeys("aa", "ee") << endl; 49 | cout << table1.maxNKey(1) << endl; 50 | cout << table1.minNKey(1) << endl; 51 | cout << table1.deleteMaxNKey(1) << endl; 52 | cout << table1.deleteMinNKey(1) << endl; 53 | table1.clear(); 54 | cout << table1 << endl; 55 | cout << table.get("aaa") << endl; 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /Tests/polynomial.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // polynomial.cpp 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/28. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include "polynomial.h" 10 | 11 | namespace data_structures { 12 | using std::endl; 13 | 14 | void testPolynomail() { 15 | auto py1 = Polynomail(vector{ 16 | {6, 4}, 17 | {5, 3}, 18 | {2, 2}, 19 | {1, 1} 20 | }); 21 | auto py2 = Polynomail(vector{ 22 | {6, 5}, 23 | {3, 3}, 24 | {2, 2}, 25 | {1, 2} 26 | }); 27 | cout << py1 << endl; 28 | cout << py1.eval(2) << endl; 29 | cout << py2 << endl; 30 | cout << -py1 << endl; 31 | cout << (py2 + py1) << endl; 32 | cout << (py2 - py1) << endl; 33 | cout << (py2 * py1) << endl; 34 | } 35 | } -------------------------------------------------------------------------------- /Tests/postfix_expression_manager.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // postfix_expression_manager 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/6. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_POSTFIX_EXPRESSION_MANAGER_TEST_H 10 | #define ALGORITHM_POSTFIX_EXPRESSION_MANAGER_TEST_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include "utils.h" 16 | #include "postfix_expression_manager.h" 17 | 18 | 19 | namespace my_algorithm { 20 | 21 | class MyInt { 22 | protected: 23 | int _value; 24 | public: 25 | static const std::vector> operators; 26 | MyInt() { _value = 0; } 27 | MyInt(const MyInt& i) { _value = i._value; } 28 | MyInt(const int i) { _value = i; } 29 | MyInt(const float f) { _value = int(f); } 30 | MyInt(const double d) { _value = int(d); } 31 | MyInt(const std::string& str) { _value = std::stoi(str); } 32 | void operator=(const MyInt& i) { _value = i._value; } 33 | void operator=(const int i) { _value = i; } 34 | void operator=(const double f) { _value = int(f); } 35 | void operator=(const float d) { _value = int(d); } 36 | void operator=(const std::string& str) { _value = std::stoi(str); } 37 | friend std::ostream& operator<<(std::ostream& out, const MyInt& i){ 38 | std::cout << i._value; 39 | return out; 40 | }; 41 | MyInt exec(const std::string& opt, const MyInt& i = 0) { 42 | if(opt == "+") { return _value + i._value; } 43 | if(opt == "-") { return _value - i._value; } 44 | if(opt == "*") { return _value * i._value; } 45 | if(opt == "/") { return _value / i._value; } 46 | if(opt == "%") { return _value % i._value; } 47 | if(opt == "&") { return _value & i._value; } 48 | if(opt == "|") { return _value | i._value; } 49 | if(opt == "^") { return _value ^ i._value; } 50 | if(opt == "**") { return pow(i._value, _value); } 51 | return _value; 52 | } 53 | }; 54 | 55 | const std::vector> MyInt::operators = { 56 | {"+", "-"}, 57 | {"*", "/", "%"}, 58 | {"&", "|", "^", "!", "**"} 59 | }; 60 | 61 | void testPostfixExpressionManager() { 62 | 63 | my_algorithm::PostfixExpressionManager manager; 64 | auto expression = std::vector{ 65 | "5", "1", "*", "6", "+", "7", "1", "*", "+" 66 | }; 67 | printVector(expression); 68 | std::cout << manager.eval(expression) << std::endl; 69 | 70 | expression = { 71 | "1", "2", "+", "3", "*", "4", "-", "5", "/", "6", "%", "7", "&", "8", "|", "9", "^", "10", "**" 72 | }; 73 | printVector(expression); 74 | std::cout << manager.eval(expression) << std::endl; 75 | 76 | expression = { 77 | "(", "1", "+", "2", ")", "*", "3", "-", "4", "/", "5", "%", "6", "&", "7", "|", "8", "^", "9", "**", "10" 78 | }; 79 | printVector(expression); 80 | expression = manager.fromInfixExpression(expression); 81 | printVector(expression); 82 | std::cout << manager.eval(expression) << std::endl; 83 | } 84 | } 85 | 86 | #endif //ALGORITHM_POSTFIX_EXPRESSION_MANAGER_TEST_H 87 | -------------------------------------------------------------------------------- /Tests/priority_queue.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // priority_queue 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/20. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include "priority_queue.h" 10 | 11 | 12 | namespace data_structures { 13 | using std::endl; 14 | 15 | void testPriorityQueue(){ 16 | PriorityQueue queue; 17 | queue.enqueue(0) 18 | .enqueue(10) 19 | .enqueue(4) 20 | .enqueue(3) 21 | .enqueue(2) 22 | .enqueue(8) 23 | .enqueue(6) 24 | .enqueue(7) 25 | .enqueue(5) 26 | .enqueue(9) 27 | .enqueue(1); 28 | cout << queue << endl; 29 | cout << queue.maxN() << endl; 30 | cout << queue.minN() << endl; 31 | auto queue1 = PriorityQueue(queue); 32 | cout << queue1 << endl; 33 | while (!queue.isEmpty()) { 34 | cout << queue.dequeueMaxN() << endl; 35 | cout << queue << endl; 36 | } 37 | while (!queue1.isEmpty()) { 38 | cout << queue1.dequeueMinN() << endl; 39 | cout << queue1 << endl; 40 | } 41 | cout << queue.isEmpty() << endl; 42 | queue1.clear(); 43 | cout << queue1 << endl; 44 | } 45 | } -------------------------------------------------------------------------------- /Tests/queue.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // queue 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/8. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include "queue.h" 10 | 11 | 12 | namespace data_structures { 13 | using std::endl; 14 | 15 | void testQueue() { 16 | auto queue = Queue(); 17 | queue.enqueue(0) 18 | .enqueue(1) 19 | .enqueue(2) 20 | .enqueue(3) 21 | .enqueue(4) 22 | .enqueue(5) 23 | .enqueue(6) 24 | .enqueue(7) 25 | .enqueue(8) 26 | .enqueue(9) 27 | .enqueue(10); 28 | cout << queue << endl; 29 | cout << queue.front() << endl; 30 | cout << queue.rear() << endl; 31 | auto queue1 = Queue(queue); 32 | cout << queue1 << endl; 33 | while (!queue.isEmpty()) { 34 | cout << queue.dequeue() << endl; 35 | cout << queue << endl; 36 | } 37 | cout << queue.isEmpty() << endl; 38 | queue.clear(); 39 | cout << queue << endl; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Tests/queue_based_on_array.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // queue_based_on_array 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/8. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include "queue_based_on_array.h" 10 | 11 | 12 | namespace data_structures { 13 | using std::endl; 14 | 15 | void testQueueBasedOnArray() { 16 | auto queue = QueueBasedOnArray(); 17 | queue.enqueue(0) 18 | .enqueue(1) 19 | .enqueue(2) 20 | .enqueue(3) 21 | .enqueue(4) 22 | .enqueue(5) 23 | .enqueue(6) 24 | .enqueue(7) 25 | .enqueue(8) 26 | .enqueue(9) 27 | .enqueue(10); 28 | cout << queue << endl; 29 | cout << queue.front() << endl; 30 | cout << queue.rear() << endl; 31 | cout << queue.isFull() << endl; 32 | auto queue1 = QueueBasedOnArray(queue); 33 | cout << queue1 << endl; 34 | while (!queue.isEmpty()) { 35 | cout << queue.dequeue() << endl; 36 | cout << queue << endl; 37 | } 38 | cout << queue.isEmpty() << endl; 39 | queue.enqueue(20) 40 | .enqueue(21) 41 | .enqueue(22) 42 | .enqueue(23) 43 | .enqueue(24) 44 | .enqueue(25) 45 | .enqueue(26) 46 | .enqueue(27) 47 | .enqueue(28) 48 | .enqueue(29) 49 | .enqueue(30); 50 | cout << queue << endl; 51 | queue.clear(); 52 | cout << queue << endl; 53 | } 54 | } -------------------------------------------------------------------------------- /Tests/quick_sort.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // quick_sort 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/15. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "quick_sort.h" 11 | #include "utils.h" 12 | #include 13 | 14 | 15 | namespace my_algorithm { 16 | using std::cout; 17 | using std::endl; 18 | using std::vector; 19 | 20 | void testQuickSort(){ 21 | 22 | auto v1 = vector(10000); 23 | fillVectorWithRandomNumbers(v1, 10000); 24 | auto tmp = refSort(v1); 25 | printVector(tmp); 26 | 27 | auto tStart = clock(); 28 | quickSort(v1); 29 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 30 | 31 | printVector(v1); 32 | compareTwoVectorsWithAssert(v1, tmp); 33 | 34 | tStart = clock(); 35 | quickSort(v1, true); 36 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 37 | 38 | printVector(v1); 39 | 40 | v1 = vector(20000); 41 | fillVectorWithRandomNumbers(v1, 20000); 42 | 43 | tStart = clock(); 44 | quickSort(v1); 45 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 46 | 47 | printVector(v1); 48 | 49 | for (size_t i = 0; i < 20000; i++) { 50 | v1[i] = 1; 51 | } 52 | 53 | tStart = clock(); 54 | quickSort(v1, false); 55 | printf("Use3Way - Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 56 | tStart = clock(); 57 | quickSort(v1, false, false); 58 | printf("No Use3Way - Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 59 | } 60 | } -------------------------------------------------------------------------------- /Tests/radix_sort.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // bucket_sort.hpp 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/31. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "radix_sort.h" 11 | #include "utils.h" 12 | #include 13 | 14 | 15 | namespace my_algorithm { 16 | using std::cout; 17 | using std::endl; 18 | using std::vector; 19 | 20 | void testRadixSort(){ 21 | 22 | auto v1 = vector(10000); 23 | fillVectorWithRandomNumbers(v1, 10000); 24 | auto tmp = refSort(v1); 25 | printVector(tmp); 26 | 27 | auto tStart = clock(); 28 | radixSort(v1, 4, 10); 29 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 30 | 31 | printVector(v1); 32 | compareTwoVectorsWithAssert(v1, tmp); 33 | 34 | tStart = clock(); 35 | radixSort(v1, 4, 10, true); 36 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 37 | 38 | printVector(v1); 39 | 40 | v1 = vector(20000); 41 | fillVectorWithRandomNumbers(v1, 20000); 42 | 43 | tStart = clock(); 44 | radixSort(v1, 5, 10); 45 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 46 | 47 | printVector(v1); 48 | } 49 | } -------------------------------------------------------------------------------- /Tests/red_black_tree.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // red_black_tree 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/12/4. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "red_black_tree.h" 11 | #include 12 | #include 13 | 14 | 15 | namespace data_structures { 16 | using std::cout; 17 | using std::endl; 18 | 19 | void testRBTree() { 20 | RBTree tree; 21 | // RBTree tree; 22 | cout << tree.isEmpty() << endl; 23 | 24 | // for (auto key: std::vector{"e", "b", "c", "a", "d", "f", "aa", "bb", "cc", "dd", "ee"}) { 25 | // cout << key << ":" << endl << tree.set(key, key) << endl; 26 | // } 27 | 28 | tree.set("e", 0) 29 | .set("b", 1) 30 | .set("c", 2) 31 | .set("a", 3) 32 | .set("d", 4) 33 | .set("f", 5) 34 | .set("aa", 12) 35 | .set("bb", 32) 36 | .set("cc", 2231) 37 | .set("dd", 4233) 38 | .set("ee", 444); 39 | cout << tree << endl; 40 | cout << tree.size() << endl; 41 | cout << tree.get("a") << endl; 42 | tree.set("a", 334); 43 | cout << tree.get("a") << endl; 44 | 45 | for (auto key: std::vector{"a", "b", "c", "d", "e", "f", "aa", "bb", "cc", "dd", "ee"}) { 46 | cout << key << " " << tree.rank(key) << endl; 47 | } 48 | 49 | for (auto rank: std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) { 50 | cout << rank << " " << tree.select(rank) << endl; 51 | } 52 | 53 | for (auto node: tree.getAllNodes()) { 54 | cout << node << "[" << node->element << "]" << endl; 55 | } 56 | 57 | auto tree1 = tree; 58 | cout << (tree == tree1) << endl; 59 | 60 | for (auto key: std::vector{"a", "b", "c", "d", "e", "f", "aa", "bb", "cc", "dd", "ee"}) { 61 | cout << "key, value: " << endl << key << ", " << tree.del(key) << endl; 62 | cout << "tree:" << endl << tree << endl; 63 | } 64 | 65 | cout << tree << endl; 66 | cout << tree1.isEmpty() << endl; 67 | tree1.clear(); 68 | cout << tree1 << endl; 69 | cout << tree1.isEmpty() << endl; 70 | cout << tree.get("a") << endl; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Tests/selection_sort.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // selection_sort 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/9. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "selection_sort.h" 11 | #include "utils.h" 12 | #include 13 | 14 | namespace my_algorithm { 15 | using std::cout; 16 | using std::endl; 17 | using std::vector; 18 | 19 | void testSelectionSort(){ 20 | 21 | auto v1 = vector(10000); 22 | fillVectorWithRandomNumbers(v1, 10000); 23 | auto tmp = refSort(v1); 24 | printVector(tmp); 25 | 26 | auto tStart = clock(); 27 | selectionSort(v1); 28 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 29 | 30 | printVector(v1); 31 | compareTwoVectorsWithAssert(v1, tmp); 32 | 33 | tStart = clock(); 34 | selectionSort(v1, true); 35 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 36 | 37 | printVector(v1); 38 | 39 | v1 = vector(20000); 40 | fillVectorWithRandomNumbers(v1, 20000); 41 | 42 | tStart = clock(); 43 | selectionSort(v1); 44 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 45 | 46 | printVector(v1); 47 | } 48 | } -------------------------------------------------------------------------------- /Tests/shell_sort.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // shell_sort 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/13. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "shell_sort.h" 11 | #include "utils.h" 12 | #include 13 | 14 | 15 | namespace my_algorithm { 16 | using std::cout; 17 | using std::endl; 18 | using std::vector; 19 | 20 | void testShellSort(){ 21 | 22 | vector step_queue = {4, 3, 2, 1}; 23 | 24 | auto v1 = vector(10000); 25 | fillVectorWithRandomNumbers(v1, 10000); 26 | auto tmp = refSort(v1); 27 | printVector(tmp); 28 | 29 | auto tStart = clock(); 30 | shellSort(v1, step_queue); 31 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 32 | 33 | printVector(v1); 34 | compareTwoVectorsWithAssert(v1, tmp); 35 | 36 | tStart = clock(); 37 | shellSort(v1, step_queue, true); 38 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 39 | 40 | printVector(v1); 41 | 42 | v1 = vector(20000); 43 | fillVectorWithRandomNumbers(v1, 20000); 44 | 45 | tStart = clock(); 46 | shellSort(v1, step_queue); 47 | printf("Time taken: %.6fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC); 48 | 49 | printVector(v1); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Tests/stack.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // stack 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/4. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | 10 | #include "stack.h" 11 | 12 | 13 | namespace data_structures { 14 | using std::endl; 15 | 16 | void testStack() { 17 | auto stack = Stack(); 18 | stack.push(0) 19 | .push(1) 20 | .push(2) 21 | .push(3) 22 | .push(4) 23 | .push(5) 24 | .push(6) 25 | .push(7) 26 | .push(8) 27 | .push(9) 28 | .push(10); 29 | cout << stack << endl; 30 | cout << stack.top() << endl; 31 | auto stack1 = Stack(stack); 32 | cout << stack1 << endl; 33 | while (!stack.isEmpty()) { 34 | cout << stack.pop() << endl; 35 | cout << stack << endl; 36 | } 37 | cout << stack.isEmpty() << endl; 38 | stack.clear(); 39 | cout << stack << endl; 40 | } 41 | } -------------------------------------------------------------------------------- /Tests/stack_based_on_array.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // stack_based_on_array 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/4. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | 10 | #include "stack_based_on_array.h" 11 | 12 | 13 | namespace data_structures { 14 | using std::endl; 15 | 16 | void testStackBasedOnArray() { 17 | auto stack = StackBasedOnArray(); 18 | stack.push(0) 19 | .push(1) 20 | .push(2) 21 | .push(3) 22 | .push(4) 23 | .push(5) 24 | .push(6) 25 | .push(7) 26 | .push(8) 27 | .push(9) 28 | .push(10); 29 | cout << stack << endl; 30 | cout << stack.top() << endl; 31 | auto stack1 = StackBasedOnArray(stack); 32 | cout << stack1 << endl; 33 | while (!stack.isEmpty()) { 34 | cout << stack.pop() << endl; 35 | cout << stack << endl; 36 | } 37 | cout << stack.isEmpty() << endl; 38 | stack.clear(); 39 | cout << stack << endl; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Tests/symbol_pair_checker.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // symbol_pair_checker 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/9/6. 6 | // Copyright © 2016 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_SYMBOL_PAIR_CHECKER_TEST_H 10 | #define ALGORITHM_SYMBOL_PAIR_CHECKER_TEST_H 11 | 12 | #include 13 | #include 14 | #include "symbol_pair_checker.h" 15 | 16 | 17 | namespace my_algorithm { 18 | 19 | void checkWithPrint(SymbolPairChecker& checker, const std::string& str) { 20 | auto result = checker.check(str); 21 | auto position = checker.position(); 22 | std::cout << result << " " << position << " " << str[position] << std::endl; 23 | } 24 | 25 | void testSymbolPairChecker() { 26 | 27 | auto checker = SymbolPairChecker( 28 | std::vector{ 29 | "{}", 30 | "[]", 31 | "()", 32 | "<>", 33 | "''", 34 | "\"\"" 35 | } 36 | ); 37 | 38 | checkWithPrint(checker, "hello world"); 39 | checkWithPrint(checker, "{}[]()<>''\"\""); 40 | checkWithPrint(checker, "template void fun(int i[]) {print \"'hello world'\";}"); 41 | checkWithPrint(checker, "{[hello}world"); 42 | checkWithPrint(checker, "hello]world{}"); 43 | } 44 | } 45 | 46 | #endif //ALGORITHM_SYMBOL_PAIR_CHECKER_TEST_H 47 | -------------------------------------------------------------------------------- /Tests/symbol_table.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // symbol_table 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/24. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include 10 | #include "symbol_table.h" 11 | #include 12 | 13 | 14 | namespace data_structures { 15 | using std::cout; 16 | using std::endl; 17 | void testSymbolTable(){ 18 | auto table = SymbolTable(); 19 | cout << table.isEmpty() << endl; 20 | table.set("a", 0) 21 | .set("b", 1) 22 | .set("c", 2) 23 | .set("d", 3) 24 | .set("e", 4) 25 | .set("f", 5) 26 | .set("aa", 12) 27 | .set("bb", 32) 28 | .set("cc", 2231) 29 | .set("dd", 4233) 30 | .set("ee", 444); 31 | cout << table << endl; 32 | cout << table.size() << endl; 33 | cout << table.get("a") << endl; 34 | table.set("a", 334); 35 | cout << table.get("a") << endl; 36 | auto table1 = table; 37 | cout << (table == table1) << endl; 38 | for (auto element: table.elements()) { 39 | cout << element << " "; 40 | } 41 | cout << endl; 42 | for (auto key: table.keys()) { 43 | cout << key << ": " << table.del(key) << endl; 44 | cout << table << endl; 45 | } 46 | cout << table.isEmpty() << endl; 47 | table1.clear(); 48 | cout << table1 << endl; 49 | cout << table.get("aaa") << endl; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /Tests/weighted_digraph.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // weighted_digraph 3 | // Algorithm 4 | // 5 | // Created by dtysky on 2017/3/11. 6 | // Copyright © 2017 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_WEIGHTED_DIGRAPH_TEST_H 10 | #define ALGORITHM_WEIGHTED_DIGRAPH_TEST_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include "weighted_digraph.h" 16 | 17 | 18 | namespace data_structures { 19 | using std::cout; 20 | using std::endl; 21 | 22 | void testWeightDigraph() { 23 | WeightedDigraph graph; 24 | cout << graph.isEmpty() << endl; 25 | cout << graph.vertexCount() << endl; 26 | cout << graph.edgeCount() << endl; 27 | 28 | // for (auto key: std::vector{"e", "b", "c", "a", "d", "f", "aa", "bb", "cc", "dd", "ee"}) { 29 | // cout << key << ":" << endl << graph.addVertex(key) << endl; 30 | // } 31 | 32 | cout << "<---- AddVertex ---->" << endl; 33 | graph.addVertex("e") 34 | .addVertex("b") 35 | .addVertex("c") 36 | .addVertex("a") 37 | .addVertex("d") 38 | .addVertex("f") 39 | .addVertex("aa") 40 | .addVertex("bb") 41 | .addVertex("cc") 42 | .addVertex("dd") 43 | .addVertex("ee"); 44 | cout << graph; 45 | cout << graph.vertexCount() << endl; 46 | cout << graph.edgeCount() << endl; 47 | cout << endl; 48 | 49 | cout << "<---- AddEdges ---->" << endl; 50 | graph.addEdge("e", "e", 1) 51 | .addEdge("e", "a", 2) 52 | .addEdge("e", "a", 3) 53 | .addEdge("b", "a", 4) 54 | .addEdge("c", "a", 5) 55 | .addEdge("a", "b", 6) 56 | .addEdge("d", "e", 7) 57 | .addEdge("f", "e", 8) 58 | .addEdge("aa", "e", -1) 59 | .addEdge("bb", "e", -2) 60 | .addEdge("cc", "e", -3) 61 | .addEdge("dd", "e", -4); 62 | cout << graph; 63 | cout << "<---- Edges ---->" << endl; 64 | 65 | for (auto &e: graph.getAllEdges()) { 66 | cout << e << endl; 67 | } 68 | cout << endl; 69 | cout << graph.vertexCount() << endl; 70 | cout << graph.edgeCount() << endl; 71 | cout << graph.selfLoopsCount() << endl; 72 | for (auto &v: graph.adjVertex("e")) { 73 | cout << v << " "; 74 | } 75 | cout << endl; 76 | cout << graph.degree("e") << endl; 77 | cout << graph.degree("ee") << endl; 78 | cout << graph.maxDegree() << endl; 79 | cout << graph.avgDegree() << endl; 80 | cout << graph.hasVertex("e") << endl; 81 | cout << graph.hasVertex("eee") << endl; 82 | cout << graph.hasEdge("e", "a") << endl; 83 | cout << graph.hasEdge("ee", "a") << endl; 84 | cout << endl; 85 | 86 | auto graph1 = graph; 87 | cout << graph1; 88 | cout << (graph == graph1) << endl; 89 | cout << endl; 90 | 91 | graph.deleteEdge("e", "a") 92 | .deleteEdge("b", "a") 93 | .deleteEdge("c", "a") 94 | .deleteEdge("d", "e") 95 | .deleteEdge("f", "e"); 96 | cout << graph; 97 | cout << graph.vertexCount() << endl; 98 | cout << graph.edgeCount() << endl; 99 | cout << graph.selfLoopsCount() << endl; 100 | cout << endl; 101 | 102 | graph.deleteEdge("aa", "e") 103 | .deleteEdge("bb", "e") 104 | .deleteEdge("cc", "e") 105 | .deleteEdge("dd", "e"); 106 | cout << graph; 107 | cout << endl; 108 | 109 | graph.deleteVertex("e") 110 | .deleteVertex("b") 111 | .deleteVertex("c") 112 | .deleteVertex("a") 113 | .deleteVertex("d") 114 | .deleteVertex("f") 115 | .deleteVertex("aa") 116 | .deleteVertex("bb") 117 | .deleteVertex("cc") 118 | .deleteVertex("dd") 119 | .deleteVertex("ee"); 120 | cout << graph; 121 | cout << graph.vertexCount() << endl; 122 | cout << graph.edgeCount() << endl; 123 | cout << endl; 124 | 125 | cout << (graph == graph1) << endl; 126 | 127 | graph1.clear(); 128 | cout << graph1 << endl; 129 | } 130 | } 131 | 132 | #endif //ALGORITHM_WEIGHTED_DIGRAPH_TEST_H 133 | -------------------------------------------------------------------------------- /Tests/weighted_digraph_algorithm.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // weighted_digraph_algorithm 3 | // Algorithm 4 | // 5 | // Created by dtysky on 2017/3/19. 6 | // Copyright © 2017 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_WEIGHTED_DIGRAPH_ALGORITHM_TEST_H 10 | #define ALGORITHM_WEIGHTED_DIGRAPH_ALGORITHM_TEST_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include "weighted_digraph.h" 16 | #include "weighted_digraph_algorithm.h" 17 | 18 | 19 | namespace my_algorithm { 20 | using std::cout; 21 | using std::endl; 22 | using data_structures::WeightedDigraph; 23 | 24 | void testWeightDigraphAlgorithm() { 25 | WeightedDigraph graph; 26 | for (int i = 0; i <= 7; i++) { 27 | graph.addVertex(i); 28 | } 29 | 30 | graph.addEdge(4, 5, 35) 31 | .addEdge(5, 4, 35) 32 | .addEdge(4, 7, 37) 33 | .addEdge(5, 7, 28) 34 | .addEdge(7, 5, 28) 35 | .addEdge(5, 1, 32) 36 | .addEdge(0, 4, 38) 37 | .addEdge(0, 2, 26) 38 | .addEdge(7, 3, 39) 39 | .addEdge(1, 3, 29) 40 | .addEdge(2, 7, 34) 41 | .addEdge(6, 2, 40) 42 | .addEdge(3, 6, 52) 43 | .addEdge(6, 0, 58) 44 | .addEdge(6, 4, 93); 45 | 46 | cout << graph << endl; 47 | 48 | cout << "<---- WeightedDigraphSPDijkstra ---->" << endl; 49 | auto a_sp_dij = WeightedDigraphSPDijkstra(graph, 0); 50 | for (int i = 0; i <= 7; i++) { 51 | if (!a_sp_dij.hasPathTo(i)) { 52 | continue; 53 | } 54 | cout << 0 << " to " << i << ":" << endl; 55 | cout << "weight: " << a_sp_dij.weightTo(i) << endl; 56 | cout << "path: "; 57 | for (auto &edge: a_sp_dij.pathTo(i)) { 58 | cout << edge << " "; 59 | } 60 | cout << endl; 61 | } 62 | 63 | cout << endl << endl; 64 | 65 | graph.clear(); 66 | for (int i = 0; i <= 7; i++) { 67 | graph.addVertex(i); 68 | } 69 | graph.addEdge(5, 4, 35) 70 | .addEdge(4, 7, 37) 71 | .addEdge(5, 7, 28) 72 | .addEdge(5, 1, 32) 73 | .addEdge(4, 0, 38) 74 | .addEdge(0, 2, 26) 75 | .addEdge(3, 7, 39) 76 | .addEdge(1, 3, 29) 77 | .addEdge(7, 2, 34) 78 | .addEdge(6, 2, 40) 79 | .addEdge(3, 6, 52) 80 | .addEdge(6, 0, 58) 81 | .addEdge(6, 4, 93); 82 | 83 | cout << graph << endl; 84 | 85 | cout << "<---- WeightedDigraphSPAcyclic ---->" << endl; 86 | auto a_sp_ac = WeightedDigraphSPAcyclic(graph); 87 | auto start = a_sp_ac.start(); 88 | for (int i = 0; i <= 7; i++) { 89 | if (!a_sp_ac.hasPathTo(i)) { 90 | continue; 91 | } 92 | cout << start << " to " << i << ":" << endl; 93 | cout << "weight: " << a_sp_ac.weightTo(i) << endl; 94 | cout << "path: "; 95 | for (auto &edge: a_sp_ac.pathTo(i)) { 96 | cout << edge << " "; 97 | } 98 | cout << endl; 99 | } 100 | 101 | } 102 | } 103 | 104 | #endif //ALGORITHM_WEIGHTED_DIGRAPH_ALGORITHM_TEST_H 105 | -------------------------------------------------------------------------------- /Tests/weighted_graph.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // weighted_graph 3 | // Algorithm 4 | // 5 | // Created by dtysky on 2017/2/25. 6 | // Copyright © 2017 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_WEIGHTED_GRAPH_TEST_H 10 | #define ALGORITHM_WEIGHTED_GRAPH_TEST_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include "weighted_graph.h" 16 | 17 | 18 | namespace data_structures { 19 | using std::cout; 20 | using std::endl; 21 | 22 | void testWeightGraph() { 23 | WeightedGraph graph; 24 | cout << graph.isEmpty() << endl; 25 | cout << graph.vertexCount() << endl; 26 | cout << graph.edgeCount() << endl; 27 | 28 | // for (auto key: std::vector{"e", "b", "c", "a", "d", "f", "aa", "bb", "cc", "dd", "ee"}) { 29 | // cout << key << ":" << endl << graph.addVertex(key) << endl; 30 | // } 31 | 32 | cout << "<---- AddVertex ---->" << endl; 33 | graph.addVertex("e") 34 | .addVertex("b") 35 | .addVertex("c") 36 | .addVertex("a") 37 | .addVertex("d") 38 | .addVertex("f") 39 | .addVertex("aa") 40 | .addVertex("bb") 41 | .addVertex("cc") 42 | .addVertex("dd") 43 | .addVertex("ee"); 44 | cout << graph; 45 | cout << graph.vertexCount() << endl; 46 | cout << graph.edgeCount() << endl; 47 | cout << endl; 48 | 49 | cout << "<---- AddEdges ---->" << endl; 50 | graph.addEdge("e", "e", 1) 51 | .addEdge("e", "a", 2) 52 | .addEdge("e", "a", 3) 53 | .addEdge("b", "a", 4) 54 | .addEdge("c", "a", 5) 55 | .addEdge("a", "b", 6) 56 | .addEdge("d", "e", 7) 57 | .addEdge("f", "e", 8) 58 | .addEdge("aa", "e", -1) 59 | .addEdge("bb", "e", -2) 60 | .addEdge("cc", "e", -3) 61 | .addEdge("dd", "e", -4); 62 | cout << graph; 63 | cout << "<---- Edges ---->" << endl; 64 | 65 | for (auto &e: graph.getAllEdges()) { 66 | cout << e << endl; 67 | } 68 | cout << endl; 69 | cout << graph.vertexCount() << endl; 70 | cout << graph.edgeCount() << endl; 71 | cout << graph.selfLoopsCount() << endl; 72 | for (auto &v: graph.adjVertex("e")) { 73 | cout << v << " "; 74 | } 75 | cout << endl; 76 | cout << graph.degree("e") << endl; 77 | cout << graph.degree("ee") << endl; 78 | cout << graph.maxDegree() << endl; 79 | cout << graph.avgDegree() << endl; 80 | cout << graph.hasVertex("e") << endl; 81 | cout << graph.hasVertex("eee") << endl; 82 | cout << graph.hasEdge("e", "a") << endl; 83 | cout << graph.hasEdge("ee", "a") << endl; 84 | cout << endl; 85 | 86 | auto graph1 = graph; 87 | cout << graph1; 88 | cout << (graph == graph1) << endl; 89 | cout << endl; 90 | 91 | graph.deleteEdge("e", "a") 92 | .deleteEdge("b", "a") 93 | .deleteEdge("c", "a") 94 | .deleteEdge("d", "e") 95 | .deleteEdge("f", "e"); 96 | cout << graph; 97 | cout << graph.vertexCount() << endl; 98 | cout << graph.edgeCount() << endl; 99 | cout << graph.selfLoopsCount() << endl; 100 | cout << endl; 101 | 102 | graph.deleteEdge("aa", "e") 103 | .deleteEdge("bb", "e") 104 | .deleteEdge("cc", "e") 105 | .deleteEdge("dd", "e"); 106 | cout << graph; 107 | cout << endl; 108 | 109 | graph.deleteVertex("e") 110 | .deleteVertex("b") 111 | .deleteVertex("c") 112 | .deleteVertex("a") 113 | .deleteVertex("d") 114 | .deleteVertex("f") 115 | .deleteVertex("aa") 116 | .deleteVertex("bb") 117 | .deleteVertex("cc") 118 | .deleteVertex("dd") 119 | .deleteVertex("ee"); 120 | cout << graph; 121 | cout << graph.vertexCount() << endl; 122 | cout << graph.edgeCount() << endl; 123 | cout << endl; 124 | 125 | cout << (graph == graph1) << endl; 126 | 127 | graph1.clear(); 128 | cout << graph1 << endl; 129 | } 130 | } 131 | 132 | 133 | #endif //ALGORITHM_WEIGHTED_GRAPH_TEST_H 134 | -------------------------------------------------------------------------------- /Tests/weighted_graph_algorithm.test.h: -------------------------------------------------------------------------------- 1 | // 2 | // weighted_graph_algorithm 3 | // Algorithm 4 | // 5 | // Created by dtysky on 2017/2/27. 6 | // Copyright © 2017 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef ALGORITHM_WEIGHTED_GRAPH_ALGORITHM_TEST_H 10 | #define ALGORITHM_WEIGHTED_GRAPH_ALGORITHM_TEST_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include "weighted_graph.h" 16 | #include "weighted_graph_algorithm.h" 17 | 18 | 19 | namespace my_algorithm { 20 | using std::cout; 21 | using std::endl; 22 | using data_structures::WeightedGraph; 23 | 24 | void testWeightGraphAlgorithm() { 25 | WeightedGraph graph; 26 | for (int i = 0; i <= 7; i++) { 27 | graph.addVertex(i); 28 | } 29 | 30 | graph.addEdge(4, 5, 35) 31 | .addEdge(4, 7, 47) 32 | .addEdge(5, 7, 28) 33 | .addEdge(0, 7, 16) 34 | .addEdge(1, 5, 32) 35 | .addEdge(0, 4, 38) 36 | .addEdge(2, 3, 17) 37 | .addEdge(1, 7, 19) 38 | .addEdge(0, 2, 26) 39 | .addEdge(1, 2, 36) 40 | .addEdge(1, 3, 29) 41 | .addEdge(2, 7, 34) 42 | .addEdge(6, 2, 40) 43 | .addEdge(3, 6, 52) 44 | .addEdge(6, 0, 58) 45 | .addEdge(6, 4, 93); 46 | 47 | cout << graph << endl; 48 | 49 | cout << "<---- WeightedGraphMSTPrim ---->" << endl; 50 | auto a_mst_prim = WeightedGraphMSTPrim(graph); 51 | for (auto &edge: a_mst_prim.edges()) { 52 | cout << edge << endl; 53 | } 54 | cout << a_mst_prim.weight() << endl << endl; 55 | 56 | cout << "<---- WeightedGraphMSTKruskal ---->" << endl; 57 | auto a_mst_kruskal = WeightedGraphMSTKruskal(graph); 58 | for (auto &edge: a_mst_kruskal.edges()) { 59 | cout << edge << endl; 60 | } 61 | cout << a_mst_kruskal.weight() << endl; 62 | } 63 | } 64 | 65 | #endif //ALGORITHM_WEIGHTED_GRAPH_ALGORITHM_TEST_H 66 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // main.cpp 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/22. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #include "main.h" 10 | 11 | //#include "selection_sort.test.h" 12 | //#include "insertion_sort.test.h" 13 | //#include "bucket_sort.test.h" 14 | //#include "radix_sort.test.h" 15 | //#include "shell_sort.test.h" 16 | //#include "merge_sort.test.h" 17 | //#include "quick_sort.test.h" 18 | //#include "heap_sort.test.h" 19 | #include "weighted_digraph_algorithm.test.h" 20 | 21 | 22 | int main(int argc, const char * argv[]) { 23 | // printf("quick\n"); 24 | // my_algorithm::testQuickSort(); 25 | // printf("\nmerge\n"); 26 | // my_algorithm::testMergeSort(); 27 | // printf("\nshell\n"); 28 | // my_algorithm::testShellSort(); 29 | // printf("\ninsertion\n"); 30 | // my_algorithm::testInsertionSort(); 31 | // printf("\nselection\n"); 32 | // my_algorithm::testSelectionSort(); 33 | // printf("\nbucket\n"); 34 | // my_algorithm::testBucketSort(); 35 | // printf("\nradix\n"); 36 | // my_algorithm::testRadixSort(); 37 | // printf("\nheap\n"); 38 | // my_algorithm::testHeapSort(); 39 | my_algorithm::testWeightDigraphAlgorithm(); 40 | return 0; 41 | } -------------------------------------------------------------------------------- /main.h: -------------------------------------------------------------------------------- 1 | // 2 | // main.hpp 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/22. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef main_hpp 10 | #define main_hpp 11 | 12 | #include 13 | 14 | #endif /* main_hpp */ 15 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | CMake 2 | C++14 3 | Ruby 4 | -------------------------------------------------------------------------------- /utils.h: -------------------------------------------------------------------------------- 1 | // 2 | // utils.hpp 3 | // Algorithm 4 | // 5 | // Created by dtysky on 16/8/31. 6 | // Copyright © 2016年 dtysky@outlook.com. All rights reserved. 7 | // 8 | 9 | #ifndef utils_hpp 10 | #define utils_hpp 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | 26 | template 27 | void printVector(std::vector& a) { 28 | for (auto i: a) { 29 | std::cout << i << " "; 30 | } 31 | std::cout << std::endl; 32 | } 33 | 34 | template 35 | bool isInVector(const std::vector& v, const T& e) { 36 | return std::find(v.begin(), v.end(), e) != v.end(); 37 | } 38 | 39 | void fillVectorWithRandomNumbers(std::vector& v, const uint32_t max, const uint32_t seed = 0) { 40 | auto size = v.size(); 41 | srand(seed); 42 | 43 | for (size_t i = 0; i < size; i++) { 44 | v[i] = float(max) * rand() / RAND_MAX; 45 | } 46 | } 47 | 48 | void fillVectorWithRangeNumbers(std::vector& v, const uint32_t max, const uint32_t seed = 0) { 49 | auto size = v.size(); 50 | for (size_t i = 0; i < size; i++) { 51 | v[i] = i; 52 | } 53 | } 54 | 55 | void compareTwoVectorsWithAssert(std::vector& v1, std::vector& v2) { 56 | std::cout << std::endl; 57 | assert(v1 == v2); 58 | } 59 | 60 | template 61 | std::vector refSort(const std::vector& v) { 62 | auto tmp = v; 63 | std::sort(tmp.begin(), tmp.end()); 64 | return tmp; 65 | } 66 | 67 | 68 | 69 | template 70 | std::string nodeToString(BinaryTreeNode* node) { 71 | std::ostringstream ss; 72 | ss << node->element << "(" << node->node_count << ")"; 73 | return ss.str(); 74 | } 75 | 76 | // Find the maximum height of the binary tree 77 | template 78 | int maxHeight(BinaryTreeNode *p) { 79 | if (!p) return 0; 80 | int leftHeight = maxHeight(p->left()); 81 | int rightHeight = maxHeight(p->right()); 82 | return (leftHeight > rightHeight) ? leftHeight + 1: rightHeight + 1; 83 | } 84 | 85 | // Print the arm branches (eg, / \ ) on a line 86 | template 87 | void printBranches(int branchLen, int nodeSpaceLen, int startLen, int nodesInThisLevel, const std::deque& nodesQueue, std::ostream& out) { 88 | typename std::deque::const_iterator iter = nodesQueue.begin(); 89 | for (int i = 0; i < nodesInThisLevel / 2; i++) { 90 | out << ((i == 0) ? std::setw(startLen-1) : std::setw(nodeSpaceLen-2)) << "" << ((*iter++) ? "/" : " "); 91 | out << std::setw(2*branchLen+2) << "" << ((*iter++) ? "\\" : " "); 92 | } 93 | out << std::endl; 94 | } 95 | 96 | // Print the branches and node (eg, ___10___ ) 97 | template 98 | void printNodes(int branchLen, int nodeSpaceLen, int startLen, int nodesInThisLevel, const std::deque& nodesQueue, std::ostream& out) { 99 | typename std::deque::const_iterator iter = nodesQueue.begin(); 100 | for (int i = 0; i < nodesInThisLevel; i++, iter++) { 101 | out << ((i == 0) ? std::setw(startLen) : std::setw(nodeSpaceLen)) << "" << ((*iter && (*iter)->left()) ? std::setfill('_') : std::setfill(' ')); 102 | out << std::setw(branchLen+2); 103 | if ((*iter)) { 104 | out << (*iter)->toString(); 105 | } else { 106 | out << ""; 107 | } 108 | out << ((*iter && (*iter)->right()) ? std::setfill('_') : std::setfill(' ')) << std::setw(branchLen) << "" << std::setfill(' '); 109 | } 110 | out << std::endl; 111 | } 112 | 113 | // Print the leaves only (just for the bottom row) 114 | template 115 | void printLeaves(int indentSpace, int level, int nodesInThisLevel, const std::deque& nodesQueue, std::ostream& out) { 116 | typename std::deque::const_iterator iter = nodesQueue.begin(); 117 | for (int i = 0; i < nodesInThisLevel; i++, iter++) { 118 | out << ((i == 0) ? std::setw(indentSpace+2) : std::setw(2*level+2)); 119 | if ((*iter)) { 120 | out << (*iter)->toString(); 121 | } else { 122 | out << ""; 123 | } 124 | } 125 | out << std::endl; 126 | } 127 | 128 | // Pretty formatting of a binary tree to the output stream 129 | // @ param 130 | // level Control how wide you want the tree to sparse (eg, level 1 has the minimum space between nodes, while level 2 has a larger space between nodes) 131 | // indentSpace Change this to add some indent space to the left (eg, indentSpace of 0 means the lowest level of the left node will stick to the left margin) 132 | template 133 | void printBinaryTree(BinaryTreeNode *root, int level, int indentSpace, std::ostream& out) { 134 | int h = maxHeight(root); 135 | int nodesInThisLevel = 1; 136 | 137 | int branchLen = 2*((int)pow(2.0,h)-1) - (3-level)*(int)pow(2.0,h-1); // eq of the length of branch for each node of each level 138 | int nodeSpaceLen = 2 + (level+1)*(int)pow(2.0,h); // distance between left neighbor node's right arm and right neighbor node's left arm 139 | int startLen = branchLen + (3-level) + indentSpace; // starting space to the first node to print of each level (for the left most node of each level only) 140 | 141 | typename std::deque nodesQueue; 142 | nodesQueue.push_back(root); 143 | for (int r = 1; r < h; r++) { 144 | printBranches(branchLen, nodeSpaceLen, startLen, nodesInThisLevel, nodesQueue, out); 145 | branchLen = branchLen/2 - 1; 146 | nodeSpaceLen = nodeSpaceLen/2 + 1; 147 | startLen = branchLen + (3-level) + indentSpace; 148 | printNodes(branchLen, nodeSpaceLen, startLen, nodesInThisLevel, nodesQueue, out); 149 | 150 | for (int i = 0; i < nodesInThisLevel; i++) { 151 | BinaryTreeNode *currNode = nodesQueue.front(); 152 | nodesQueue.pop_front(); 153 | if (currNode) { 154 | nodesQueue.push_back(currNode->left()); 155 | nodesQueue.push_back(currNode->right()); 156 | } else { 157 | nodesQueue.push_back(NULL); 158 | nodesQueue.push_back(NULL); 159 | } 160 | } 161 | nodesInThisLevel *= 2; 162 | } 163 | printBranches(branchLen, nodeSpaceLen, startLen, nodesInThisLevel, nodesQueue, out); 164 | printLeaves(indentSpace, level, nodesInThisLevel, nodesQueue, out); 165 | } 166 | 167 | 168 | #endif /* utils_hpp */ 169 | --------------------------------------------------------------------------------