#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_node_sentinel.destroy(_sentinel); _allocator_node_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) { pair ret; ret = _insert(value); if (ret.second == true) _insert_rebalancing(ret.first.getNode()->up); return (ret); } 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) { while (first != last) { insert(*first); ++first; } } // erase ------------------------------------- MP_TPL void MP:: erase(iterator pos) { node* delete_point; delete_point = _erase(pos); _erase_rebalancing(delete_point); } 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 = find(key); if (pos == end()) return (0); else { erase(pos); return (1); } } // swap -------------------------------------- MP_TPL void MP:: swap(map& other) { node* tmp_root = _root; node_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_node_sentinel.allocate(1); _allocator_node_sentinel.construct(_sentinel, node_sentinel()); } MP_TPL pair MP:: _insert(const value_type& value) { node* n = _root; node* prev = NULL; while (n) { prev = n; if (_comp(value.first, n->value.first)) n = n->left; else if (_comp(n->value.first, value.first)) n = n->right; else return ft::make_pair(iterator(n, _sentinel), false); } n = _allocator_node.allocate(1); _allocator_node.construct(n, node(value)); if (_root == NULL) { _root = n; _sentinel->child = _root; } else if (_comp(value.first, prev->value.first)) prev->left = n; else prev->right = n; n->up = prev; ++_size; return ft::make_pair(iterator(n, _sentinel), true); } MP_TPL node* MP:: _erase(iterator pos) { node* n = pos.getNode(); node* delete_point = NULL; if (n->left && n->right) { node* next = n->right->min(); if (next->up != n) { _subtree_shift(next, next->right); next->right = n->right; next->right->up = next; } delete_point = _subtree_shift(n, next); next->left = n->left; next->left->up = next; } else if (!n->left && !n->right) delete_point = _subtree_shift(n, NULL); else if (n->left) delete_point = _subtree_shift(n, n->left); else if (n->right) delete_point = _subtree_shift(n, n->right); _allocator_node.destroy(n); _allocator_node.deallocate(n, 1); --_size; return (delete_point); } MP_TPL node* MP:: _subtree_shift(node* st_old, node* st_new) { node* p = st_old->up; if (st_old == _root) { _root = st_new; _sentinel->child = _root; } else if (st_old == p->left) p->left = st_new; else p->right = st_new; if (st_new == NULL) return (p); st_new->up = p; return (st_new); } MP_TPL void MP:: _insert_rebalancing(node* n) { 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 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 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; break; } n = n->up; } while (n) { n->height = _compute_height(n); n = n->up; } } MP_TPL void MP:: _erase_rebalancing(node* n) { 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; parent = NULL; } 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