#define BST_TEMPLATE template < typename Key, typename T, typename Compare, typename Allocator > #define BST map namespace ft { ////////////////////// // Member functions // BST_TEMPLATE BST:: map(const Compare& comp, const Allocator& alloc) : _size(0), _root(NULL), _comp(comp), _allocator(alloc) { _init_sentinel(); } BST_TEMPLATE template < typename InputIt > BST:: map(InputIt first, InputIt last, const Compare& comp, const Allocator& alloc) : _size(0), _root(NULL), _comp(comp), _allocator(alloc) { _init_sentinel(); insert(first, last); } BST_TEMPLATE BST:: map(const map& src) : _size(0), _root(NULL), _comp(src._comp), _allocator(src._allocator) { _init_sentinel(); *this = src; } BST_TEMPLATE BST:: ~map() { clear(); _allocator_node_sentinel.destroy(_sentinel); _allocator_node_sentinel.deallocate(_sentinel, 1); } BST_TEMPLATE BST& BST:: operator=(const map& rhs) { if (this == &rhs) return (*this); map new_bst(rhs.begin(), rhs.end()); swap(new_bst); return (*this); } //////////////////// // Element access // BST_TEMPLATE T& BST:: operator[](const Key& key) { node* n = _root; //node* prev = NULL; while (n) { //prev = 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); } // TODO : Call insert with hint (prev) n = insert( ft::make_pair(key, mapped_type()) ).first.getNode(); return (n->value.second); } /////////////// // Iterators // BST_TEMPLATE typename BST::iterator BST:: begin() { if (_root) return iterator(_root->min(), _sentinel); else return end(); } BST_TEMPLATE typename BST::const_iterator BST:: begin() const { if (_root) return const_iterator(_root->min(), _sentinel); else return end(); } BST_TEMPLATE typename BST::iterator BST:: end() { return iterator(NULL, _sentinel); } BST_TEMPLATE typename BST::const_iterator BST:: end() const { return const_iterator(NULL, _sentinel); } BST_TEMPLATE typename BST::reverse_iterator BST:: rbegin() { return reverse_iterator(end()); } BST_TEMPLATE typename BST::const_reverse_iterator BST:: rbegin() const { return const_reverse_iterator(end()); } BST_TEMPLATE typename BST::reverse_iterator BST:: rend() { return reverse_iterator(begin()); } BST_TEMPLATE typename BST::const_reverse_iterator BST:: rend() const { return const_reverse_iterator(begin()); } ////////////// // Capacity // BST_TEMPLATE bool BST:: empty() const { return (_size == 0); } BST_TEMPLATE typename BST::size_type BST:: size() const { return (_size); } BST_TEMPLATE typename BST::size_type BST:: max_size() const { return ( _allocator_node.max_size() ); } /////////////// // Modifiers // BST_TEMPLATE void BST:: clear() { // TODO : optimisation jouable ? erase(begin(), end()); //_size = 0; } BST_TEMPLATE pair BST:: insert(const value_type& value) { pair ret; ret = _insert(value); if (ret.second == true) _insert_rebalancing(ret.first.getNode()->up); return (ret); } BST_TEMPLATE typename BST::iterator BST:: insert(iterator hint, const value_type& value) { // TODO : optimise with hint (void)hint; return insert(value).first; } BST_TEMPLATE template < typename InputIt > void BST:: insert(InputIt first, InputIt last) { //static int i = 0; // Debug while (first != last) { insert(*first); ++first; //std::cout << "c|" << i << "\n"; //++i; } } BST_TEMPLATE void BST:: erase(iterator pos) { node* delete_point; delete_point = _erase(pos); _erase_rebalancing(delete_point); } BST_TEMPLATE void BST:: erase(iterator first, iterator last) { while (first != last) erase(first++); } BST_TEMPLATE typename BST::size_type BST:: erase(const Key& key) { iterator pos = find(key); if (pos == end()) return (0); else { erase(pos); return (1); } } BST_TEMPLATE void BST:: 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; } //////////// // Lookup // BST_TEMPLATE typename BST::iterator BST:: 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()); } BST_TEMPLATE typename BST::const_iterator BST:: 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()); } BST_TEMPLATE typename BST::size_type BST:: count(const Key& key) const { if (find(key) != end()) return (1); else return (0); } /////////////////////// // Private functions // BST_TEMPLATE void BST:: _init_sentinel() { _sentinel = _allocator_node_sentinel.allocate(1); _allocator_node_sentinel.construct(_sentinel, node_sentinel()); } BST_TEMPLATE pair BST:: _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) // if (_size == 0) { _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); } BST_TEMPLATE node* BST:: _erase(iterator pos) { node* n = pos.getNode(); node* delete_point = NULL; if (n->left && n->right) // 2 child { 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) // no child (leaf) delete_point = _subtree_shift(n, NULL); // bug ? else if (n->left) // 1 child delete_point = _subtree_shift(n, n->left); else if (n->right) // 1 child delete_point = _subtree_shift(n, n->right); // bug ? _allocator_node.destroy(n); _allocator_node.deallocate(n, 1); --_size; return (delete_point); } BST_TEMPLATE node* BST:: _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); // return deletion point st_new->up = p; return (st_new); // return deletion point } BST_TEMPLATE void BST:: _insert_rebalancing(node* n) { node* old_n; node* parent = NULL; while (n) { n->height = _compute_height(n); if (_bf(n) > 1) // Left Heavy { parent = n->up; if (_bf(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 (_bf(n) < -1) // Right Heavy { parent = n->up; if (_bf(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; break; } n = n->up; } while (n) { n->height = _compute_height(n); n = n->up; } } BST_TEMPLATE void BST:: _erase_rebalancing(node* n) { node* old_n; node* parent = NULL; while (n) { n->height = _compute_height(n); if (_bf(n) > 1) // Left Heavy { parent = n->up; if (_bf(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 (_bf(n) < -1) // Right Heavy { parent = n->up; if (_bf(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; } } BST_TEMPLATE short BST:: _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; } BST_TEMPLATE short BST:: _bf(node* n) // optimisation possible if assume n have at least one child ? { 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; } BST_TEMPLATE node* BST:: _rotate_left(node* n) // assume n->right != NULL { 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; // return new sub-tree root } BST_TEMPLATE node* BST:: _rotate_right(node* n) // assume n->left != NULL { 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; // return new sub-tree root } ////////////////////////// // Non-member functions // BST_TEMPLATE bool operator==(const BST& lhs, const BST& rhs) { if (lhs.size() != rhs.size()) return false; return ft::equal(lhs.begin(), lhs.end(), rhs.begin()); } BST_TEMPLATE bool operator!=(const BST& lhs, const BST& rhs) { return !(lhs == rhs); } BST_TEMPLATE bool operator<(const BST& lhs, const BST& rhs) { return ft::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } BST_TEMPLATE bool operator>(const BST& lhs, const BST& rhs) { return (rhs < lhs); } BST_TEMPLATE bool operator<=(const BST& lhs, const BST& rhs) { return !(lhs > rhs); } BST_TEMPLATE bool operator>=(const BST& lhs, const BST& rhs) { return !(lhs < rhs); } BST_TEMPLATE void swap(BST& lhs, BST& rhs) { lhs.swap(rhs); } } // namespace ft #undef BST #undef BST_TEMPLATE