#define MP_TPL template < typename Key, typename T, typename Compare, typename Allocator > #define MP map namespace ft { /************ * copliens : ************/ // constructors ------------------------------ MP_TPL MP:: map (const key_compare & comp, const allocator_type & alloc) : _size(0) , _root(NULL) , _comp(comp) , _allocator(alloc) { _init_sentinel(); } MP_TPL template < typename InputIt > MP:: map (InputIt first, InputIt last, const key_compare& comp, const allocator_type& alloc) : _size(0) , _root(NULL) , _comp(comp) , _allocator(alloc) { _init_sentinel(); insert(first, last); } MP_TPL MP:: map(const map& src) : _size(0) , _root(NULL) , _comp(src._comp) , _allocator(src._allocator) { _init_sentinel(); *this = src; } // destructor -------------------------------- MP_TPL MP:: ~map() { clear(); _allocator_sentinel.destroy(_sentinel); _allocator_sentinel.deallocate(_sentinel, 1); } // operator= --------------------------------- MP_TPL MP& MP:: operator=(const map& rhs) { if (this == &rhs) return (*this); map new_bst(rhs.begin(), rhs.end()); swap(new_bst); return (*this); } /************* * iterators : *************/ // begin ------------------------------------- MP_TPL typename MP::iterator MP:: begin() { if (_root) return iterator(_root->min(), _sentinel); else return end(); } MP_TPL typename MP::const_iterator MP:: begin() const { if (_root) return const_iterator(_root->min(), _sentinel); else return end(); } // end --------------------------------------- MP_TPL typename MP::iterator MP:: end() { return iterator(NULL, _sentinel); } MP_TPL typename MP::const_iterator MP:: end() const { return const_iterator(NULL, _sentinel); } // rbegin ------------------------------------ MP_TPL typename MP::reverse_iterator MP:: rbegin() { return reverse_iterator(end()); } MP_TPL typename MP::const_reverse_iterator MP:: rbegin() const { return const_reverse_iterator(end()); } // rend -------------------------------------- MP_TPL typename MP::reverse_iterator MP:: rend() { return reverse_iterator(begin()); } MP_TPL typename MP::const_reverse_iterator MP:: rend() const { return const_reverse_iterator(begin()); } /************ * capacity : ************/ // empty ------------------------------------- MP_TPL bool MP:: empty() const { return (_size == 0); } // size -------------------------------------- MP_TPL typename MP::size_type MP:: size() const { return (_size); } // max_size ---------------------------------- MP_TPL typename MP::size_type MP:: max_size() const { return ( _allocator_node.max_size() ); } /****************** * element access : ******************/ // operator[] -------------------------------- MP_TPL typename MP::mapped_type& MP:: operator[](const Key& key) { node* n = _root; while (n) { if (_comp(key, n->value.first)) n = n->left; else if (_comp(n->value.first, key)) n = n->right; else return (n->value.second); } n = insert( ft::make_pair(key, mapped_type()) ).first.getNode(); return (n->value.second); } /************* * modifiers : *************/ // insert ------------------------------------ MP_TPL pair MP:: insert(const value_type& value) { node* n = _root; node* next = n; while (next != NULL) { if (value.first == n->value.first) return ft::make_pair(iterator(n, _sentinel), false); n = next; if (value.first < n->value.first) next = n->left; else if (value.first > n->value.first) next = n->right; } next = _allocator_node.allocate(1); _allocator_node.construct(next, node(value)); if (_root == NULL) { _root = next; _sentinel->child = next; } else { if (value.first < n->value.first) n->left = next; else if (value.first > n->value.first) n->right = next; } next->up = n; _size++; _balance(n, INSERT); return (ft::make_pair(iterator(next, _sentinel), true)); } MP_TPL typename MP::iterator MP:: insert(iterator hint, const value_type& value) { (void)hint; return insert(value).first; } MP_TPL template < typename InputIt > void MP:: insert(InputIt first, InputIt last) { for (; first != last; first++) insert(*first); } // erase ------------------------------------- // https://www.geeksforgeeks.org/binary-search-tree-set-2-delete MP_TPL void MP:: erase(iterator pos) { node* n = pos.getNode(); node* n_del = NULL; node* next; if (n->left && n->right) { next = n->right->min(); if (next->up != n) { _subtree_shift(next, next->right); next->right = n->right; next->right->up = next; } n_del = _subtree_shift(n, next); next->left = n->left; next->left->up = next; } else { if (n->left) n_del = _subtree_shift(n, n->left); else if (n->right) n_del = _subtree_shift(n, n->right); else n_del = _subtree_shift(n, NULL); } _allocator_node.destroy(n); _allocator_node.deallocate(n, 1); _size--; _balance(n_del, ERASE); } MP_TPL void MP:: erase(iterator first, iterator last) { while (first != last) erase(first++); } MP_TPL typename MP::size_type MP:: erase(const Key& key) { iterator pos; pos = find(key); if (pos == end()) return (0); erase(pos); return (1); } // swap -------------------------------------- MP_TPL void MP:: swap(map& other) { node* tmp_root = _root; sentinel* tmp_sentinel = _sentinel; size_type tmp_size = _size; _root = other._root; _sentinel = other._sentinel; _size = other._size; other._root = tmp_root; other._sentinel = tmp_sentinel; other._size = tmp_size; } // clear ------------------------------------- MP_TPL void MP:: clear() { erase(begin(), end()); } /************* * observers : *************/ // key_comp ---------------------------------- MP_TPL typename MP::key_compare MP:: key_comp() const { return (value_compare(_comp).comp); } // value_comp -------------------------------- MP_TPL typename MP::value_compare MP:: value_comp() const { return (value_compare(_comp)); } /************** * operations : **************/ // find -------------------------------------- MP_TPL typename MP::iterator MP:: find(const Key& key) { node* n = _root; while (n) { if (_comp(key, n->value.first)) n = n->left; else if (_comp(n->value.first, key)) n = n->right; else return (iterator(n, _sentinel)); } return (end()); } MP_TPL typename MP::const_iterator MP:: find(const Key& key) const { node* n = _root; while (n) { if (_comp(key, n->value.first)) n = n->left; else if (_comp(n->value.first, key)) n = n->right; else return (const_iterator(n, _sentinel)); } return (end()); } // count ------------------------------------- MP_TPL typename MP::size_type MP:: count(const Key& key) const { if (find(key) != end()) return (1); else return (0); } // lower_bound ------------------------------- MP_TPL typename MP::iterator MP:: lower_bound (const key_type& k) { iterator it = begin(); iterator it_end = end(); while (it != it_end) { if (_comp(it->first, k) == false) return (it); ++it; } return (it_end); } MP_TPL typename MP::const_iterator MP:: lower_bound (const key_type& k) const { const_iterator it = begin(); const_iterator it_end = end(); while (it != it_end) { if (_comp(it->first, k) == false) return (it); ++it; } return (it_end); } // upper_bound ------------------------------- MP_TPL typename MP::iterator MP:: upper_bound (const key_type& k) { iterator it = begin(); iterator it_end = end(); while (it != it_end) { if (_comp(k, it->first)) return (it); ++it; } return (it_end); } MP_TPL typename MP::const_iterator MP:: upper_bound (const key_type& k) const { const_iterator it = begin(); const_iterator it_end = end(); while (it != it_end) { if (_comp(k, it->first)) return (it); ++it; } return (it_end); } // equal_range ------------------------------- MP_TPL pair MP:: equal_range (const key_type& k) const { return ft::make_pair( lower_bound(k), upper_bound(k) ); } MP_TPL pair MP:: equal_range (const key_type& k) { return ft::make_pair( lower_bound(k), upper_bound(k) ); } /************* * allocator : *************/ // get_allocator ----------------------------- MP_TPL typename MP::allocator_type MP:: get_allocator() const { return (_allocator); } /********************* * private functions : *********************/ MP_TPL void MP:: _init_sentinel() { _sentinel = _allocator_sentinel.allocate(1); _allocator_sentinel.construct(_sentinel, sentinel()); } MP_TPL node* MP:: _subtree_shift(node* n_old, node* n_new) { node* p = n_old->up; if (n_old == _root) { _root = n_new; _sentinel->child = _root; } else if (n_old == p->left) p->left = n_new; else p->right = n_new; if (n_new == NULL) return (p); n_new->up = p; return (n_new); } MP_TPL void MP:: _balance(node* n, bool action) { node* old_n; node* parent = NULL; while (n) { n->height = _compute_height(n); if (_balance_factor(n) > 1) // Left Heavy { parent = n->up; if (_balance_factor(n->left) < 0) // Left-Right Case (BF == -1) n->left = _rotate_left(n->left); // Left-Left Case n = _rotate_right(n); old_n = n->right; } else if (_balance_factor(n) < -1) // Right Heavy { parent = n->up; if (_balance_factor(n->right) > 0) // Right-Left Case (BF == 1) n->right = _rotate_right(n->right); // Right-Right Case n = _rotate_left(n); old_n = n->left; } if (parent) { if (parent->left == old_n) parent->left = n; else parent->right = n; if (action == INSERT) break; else if (action == ERASE) parent = NULL; } n = n->up; } if (action == INSERT) { while (n) { n->height = _compute_height(n); n = n->up; } } } MP_TPL short MP:: _compute_height(node* n) { if (n->left && n->right) return std::max(n->left->height, n->right->height) + 1; else if (n->left) return n->left->height + 1; else if (n->right) return n->right->height + 1; else return 1; } MP_TPL short MP:: _balance_factor(node* n) { if (n->left && n->right) return n->left->height - n->right->height; else if (n->left) return n->left->height; else if (n->right) return (-(n->right->height)); else return 0; } MP_TPL node* MP:: _rotate_left(node* n) { node* ori_right = n->right; ori_right->up = n->up; n->up = ori_right; n->right = ori_right->left; if (n->right != NULL) n->right->up = n; ori_right->left = n; n->height = _compute_height(n); ori_right->height = _compute_height(ori_right); if (n == _root) { _root = ori_right; _sentinel->child = _root; } return ori_right; } MP_TPL node* MP:: _rotate_right(node* n) { node* ori_left = n->left; ori_left->up = n->up; n->up = ori_left; n->left = ori_left->right; if (n->left != NULL) n->left->up = n; ori_left->right = n; n->height = _compute_height(n); ori_left->height = _compute_height(ori_left); if (n == _root) { _root = ori_left; _sentinel->child = _root; } return ori_left; } /************************ * non-member functions : ************************/ // operator == ------------------------------- MP_TPL bool operator== (const MP& lhs, const MP& rhs) { if (lhs.size() != rhs.size()) return false; return ft::equal(lhs.begin(), lhs.end(), rhs.begin()); } // operator < -------------------------------- MP_TPL bool operator< (const MP& lhs, const MP& rhs) { return ft::lexicographical_compare( lhs.begin(), lhs.end(), rhs.begin(), rhs.end() ); } // operator != ------------------------------- MP_TPL bool operator!= (const MP& lhs, const MP& rhs) { return !(lhs == rhs); } // operator <= ------------------------------- MP_TPL bool operator<= (const MP& lhs, const MP& rhs) { return !(lhs > rhs); } // operator > -------------------------------- MP_TPL bool operator> (const MP& lhs, const MP& rhs) { return (rhs < lhs); } // operator >= ------------------------------- MP_TPL bool operator>= (const MP& lhs, const MP& rhs) { return !(lhs < rhs); } // swap (map) ----------------------------- MP_TPL void swap(MP& lhs, MP& rhs) { lhs.swap(rhs); } } // namespace ft #undef MP #undef MP_TPL