From 58d417742b8638bb4e97994bf9d61f5b9170759c Mon Sep 17 00:00:00 2001 From: hugogogo Date: Wed, 22 Jun 2022 00:22:04 +0200 Subject: [PATCH] map is bst --- Makefile | 17 +- headers/{bst.hpp => bak__bst.hpp} | 0 ...bst_iterator.hpp => bak__bst_iterator.hpp} | 0 headers/{bst_node.hpp => bak__bst_node.hpp} | 0 headers/bak__map.hpp | 207 ++++++ headers/map.hpp | 265 +++----- headers/map_iterator.hpp | 207 ++++++ headers/map_node.hpp | 50 ++ templates/bst.tpp | 16 +- templates/bst_bak.tpp | 628 ++++++++++++++++++ tests/main.cpp | 12 +- tests/tests_map.cpp | 4 + 12 files changed, 1228 insertions(+), 178 deletions(-) rename headers/{bst.hpp => bak__bst.hpp} (100%) rename headers/{bst_iterator.hpp => bak__bst_iterator.hpp} (100%) rename headers/{bst_node.hpp => bak__bst_node.hpp} (100%) create mode 100644 headers/bak__map.hpp create mode 100644 headers/map_iterator.hpp create mode 100644 headers/map_node.hpp create mode 100644 templates/bst_bak.tpp diff --git a/Makefile b/Makefile index 27780ad..a581397 100644 --- a/Makefile +++ b/Makefile @@ -67,18 +67,21 @@ HEADERS = colors.h \ equal.hpp \ lexicographical_compare.hpp \ pair.hpp \ - bst.hpp \ - bst_node.hpp \ - bst_iterator.hpp \ \ - vector.hpp \ - map.hpp + map.hpp \ + map_node.hpp \ + map_iterator.hpp \ + vector.hpp +# map.hpp +# bst.hpp +# bst_node.hpp +# bst_iterator.hpp D_TEMPLATES = ./templates TEMPLATES = bst.tpp \ \ - vector.tpp \ - map.tpp + vector.tpp +# map.tpp D_TESTS = ./tests/includes TESTS = main.hpp \ diff --git a/headers/bst.hpp b/headers/bak__bst.hpp similarity index 100% rename from headers/bst.hpp rename to headers/bak__bst.hpp diff --git a/headers/bst_iterator.hpp b/headers/bak__bst_iterator.hpp similarity index 100% rename from headers/bst_iterator.hpp rename to headers/bak__bst_iterator.hpp diff --git a/headers/bst_node.hpp b/headers/bak__bst_node.hpp similarity index 100% rename from headers/bst_node.hpp rename to headers/bak__bst_node.hpp diff --git a/headers/bak__map.hpp b/headers/bak__map.hpp new file mode 100644 index 0000000..76bea02 --- /dev/null +++ b/headers/bak__map.hpp @@ -0,0 +1,207 @@ + +#ifndef MAP_HPP +# define MAP_HPP + +# include "colors.h" +# include // std::allocator +# include // NULL, std::size_t, std::ptrdiff_t +# include // std::less, std::binary_function + +# include "pair.hpp" +# include "bst.hpp" + +namespace ft { + +template < + class Key, // map::key_type + class T, // map::mapped_type + class Compare = std::less, // map::key_compare + class Alloc = std::allocator< ft::pair > // map::allocator_type +> class map { + +public: + + typedef Key key_type; + typedef T mapped_type; + typedef pair value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef Compare key_compare; + typedef Alloc allocator_type; + +// typedef typename allocator_type::reference reference; +// typedef typename allocator_type::const_reference const_reference; +// typedef typename allocator_type::pointer pointer; +// typedef typename allocator_type::const_pointer const_pointer; + + typedef Bst bst_map; + + typedef typename bst_map::iterator iterator; + typedef typename bst_map::const_iterator const_iterator; + typedef typename bst_map::reverse_iterator reverse_iterator; + typedef typename bst_map::const_reverse_iterator const_reverse_iterator; + + + /**************** + * member class : + ****************/ + // https://en.cppreference.com/w/cpp/container/map/value_compare + // https://stackoverflow.com/questions/4571355/why-would-one-use-nested-classes-in-c + class value_compare : public std::binary_function { + + friend class map; + protected: + Compare comp; + value_compare(Compare c) : comp(c) {} + public: + bool operator() (const value_type& x, const value_type& y) const + { return comp(x.first, y.first); } + }; + + + /************ + * copliens : + ************/ +// constructors ------------------------------ + explicit map (const key_compare& comp = key_compare(), + const allocator_type& alloc = allocator_type()); + template + map (InputIterator first, InputIterator last, + const key_compare& comp = key_compare(), + const allocator_type& alloc = allocator_type()); + map (const map& x); +// destructor -------------------------------- + ~map(); +// operator= --------------------------------- + map& operator= (const map& x); + + + /************* + * iterators : + *************/ +// begin ------------------------------------- + iterator begin(); + const_iterator begin() const; +// end --------------------------------------- + iterator end(); + const_iterator end() const; +// rbegin ------------------------------------ + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; +// rend -------------------------------------- + reverse_iterator rend(); + const_reverse_iterator rend() const; + + + /************ + * capacity : + ************/ +// empty ------------------------------------- + bool empty() const; +// size -------------------------------------- + size_type size() const; +// max_size ---------------------------------- + size_type max_size() const; + + + /****************** + * element access : + ******************/ +// operator[] -------------------------------- + mapped_type & operator[] (const key_type& k); + + + /************* + * modifiers : + *************/ +// insert ------------------------------------ + pair insert (const value_type& val); + iterator insert (iterator position, const value_type& val); + template + void insert (InputIterator first, InputIterator last); +// erase ------------------------------------- + void erase (iterator position); + size_type erase (const key_type& k); + void erase (iterator first, iterator last); +// swap -------------------------------------- + void swap (map& x); +// clear ------------------------------------- + void clear(); + + + /************* + * observers : + *************/ +// key_comp ---------------------------------- + key_compare key_comp() const; +// value_comp -------------------------------- + value_compare value_comp() const; + + + /************** + * operations : + **************/ +// find -------------------------------------- + iterator find (const key_type& k); + const_iterator find (const key_type& k) const; +// count ------------------------------------- + size_type count (const key_type& k) const; +// lower_bound ------------------------------- + iterator lower_bound (const key_type& k); + const_iterator lower_bound (const key_type& k) const; +// upper_bound ------------------------------- + iterator upper_bound (const key_type& k); + const_iterator upper_bound (const key_type& k) const; +// equal_range ------------------------------- + pair equal_range (const key_type& k) const; + pair equal_range (const key_type& k); + + + /************* + * allocator : + *************/ +// get_allocator ----------------------------- + allocator_type get_allocator() const; + + // TMP non privat + bst_map _bst; +private: + + allocator_type _allocator; + key_compare _comp; + +}; + + + /************************ + * non-member functions : + ************************/ +// operator == ------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator== + ( const std::map& lhs, const std::map& rhs ); +// operator != ------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator!= + ( const std::map& lhs, const std::map& rhs ); +// operator < -------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator< + ( const std::map& lhs, const std::map& rhs ); +// operator <= ------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator<= + ( const std::map& lhs, const std::map& rhs ); +// operator > -------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator> + ( const std::map& lhs, const std::map& rhs ); +// operator >= ------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator>= + ( const std::map& lhs, const std::map& rhs ); +// swap (map) ----------------------------- +template< class Key, class T, class Compare, class Alloc > void swap + ( std::map& lhs, std::map& rhs ); + + +} // namespace ft + +# include "map.tpp" + +#endif + diff --git a/headers/map.hpp b/headers/map.hpp index 76bea02..9ab5e19 100644 --- a/headers/map.hpp +++ b/headers/map.hpp @@ -2,13 +2,18 @@ #ifndef MAP_HPP # define MAP_HPP -# include "colors.h" # include // std::allocator # include // NULL, std::size_t, std::ptrdiff_t +# include // max() # include // std::less, std::binary_function +# include "reverse_iterator.hpp" +# include "equal.hpp" +# include "lexicographical_compare.hpp" + # include "pair.hpp" -# include "bst.hpp" +# include "map_node.hpp" +# include "map_iterator.hpp" namespace ft { @@ -17,36 +22,27 @@ template < class T, // map::mapped_type class Compare = std::less, // map::key_compare class Alloc = std::allocator< ft::pair > // map::allocator_type -> class map { +> class map +{ + public: + typedef Key key_type; + typedef T mapped_type; + typedef pair value_type; + typedef Compare key_compare; + typedef Alloc allocator_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; -public: + // typedef typename Alloc::pointer pointer; + // typedef typename Alloc::const_pointer const_pointer; + // typedef typename Alloc::reference reference; + // typedef typename Alloc::const_reference const_reference; - typedef Key key_type; - typedef T mapped_type; - typedef pair value_type; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef Compare key_compare; - typedef Alloc allocator_type; + typedef map_iterator iterator; + typedef map_const_iterator const_iterator; + typedef ft::reverse_iterator reverse_iterator; + typedef ft::reverse_iterator const_reverse_iterator; -// typedef typename allocator_type::reference reference; -// typedef typename allocator_type::const_reference const_reference; -// typedef typename allocator_type::pointer pointer; -// typedef typename allocator_type::const_pointer const_pointer; - - typedef Bst bst_map; - - typedef typename bst_map::iterator iterator; - typedef typename bst_map::const_iterator const_iterator; - typedef typename bst_map::reverse_iterator reverse_iterator; - typedef typename bst_map::const_reverse_iterator const_reverse_iterator; - - - /**************** - * member class : - ****************/ - // https://en.cppreference.com/w/cpp/container/map/value_compare - // https://stackoverflow.com/questions/4571355/why-would-one-use-nested-classes-in-c class value_compare : public std::binary_function { friend class map; @@ -58,150 +54,105 @@ public: { return comp(x.first, y.first); } }; + // Member functions + explicit map(const Compare& comp = Compare(), const Alloc& alloc = Alloc() ); + template < typename InputIt > + map(InputIt first, InputIt last, const Compare& comp = Compare(), const Alloc& alloc = Alloc()); + map(const map& src); + ~map(); - /************ - * copliens : - ************/ -// constructors ------------------------------ - explicit map (const key_compare& comp = key_compare(), - const allocator_type& alloc = allocator_type()); - template - map (InputIterator first, InputIterator last, - const key_compare& comp = key_compare(), - const allocator_type& alloc = allocator_type()); - map (const map& x); -// destructor -------------------------------- - ~map(); -// operator= --------------------------------- - map& operator= (const map& x); + map& operator=(const map& rhs); + // Element access + T& operator[](const Key& key); - /************* - * iterators : - *************/ -// begin ------------------------------------- - iterator begin(); - const_iterator begin() const; -// end --------------------------------------- - iterator end(); - const_iterator end() const; -// rbegin ------------------------------------ - reverse_iterator rbegin(); - const_reverse_iterator rbegin() const; -// rend -------------------------------------- - reverse_iterator rend(); - const_reverse_iterator rend() const; + // Iterators + iterator begin(); + const_iterator begin() const; + iterator end(); + const_iterator end() const; + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; + reverse_iterator rend(); + const_reverse_iterator rend() const; + // Capacity + bool empty() const; + size_type size() const; + size_type max_size() const; - /************ - * capacity : - ************/ -// empty ------------------------------------- - bool empty() const; -// size -------------------------------------- - size_type size() const; -// max_size ---------------------------------- - size_type max_size() const; + // Modifiers + void clear(); + pair insert(const value_type& value); + iterator insert(iterator hint, const value_type& value); + template < typename InputIt > + void insert(InputIt first, InputIt last); + void erase(iterator pos); + void erase(iterator first, iterator last); + size_type erase(const Key& key); + void swap(map& other); + // Lookup + iterator find(const Key& key); + const_iterator find(const Key& key) const; + size_type count(const Key& key) const; - /****************** - * element access : - ******************/ -// operator[] -------------------------------- - mapped_type & operator[] (const key_type& k); + private: + size_type _size; + node* _root; + node_sentinel* _sentinel; + Compare _comp; + Alloc _allocator; + // TODO : rebind syntaxe pas clair. + typename Alloc::template rebind< node >::other _allocator_node; // Peu clair, verifier syntaxe + typename Alloc::template rebind< node_sentinel >::other _allocator_node_sentinel; // Peu clair, verifier syntaxe - /************* - * modifiers : - *************/ -// insert ------------------------------------ - pair insert (const value_type& val); - iterator insert (iterator position, const value_type& val); - template - void insert (InputIterator first, InputIterator last); -// erase ------------------------------------- - void erase (iterator position); - size_type erase (const key_type& k); - void erase (iterator first, iterator last); -// swap -------------------------------------- - void swap (map& x); -// clear ------------------------------------- - void clear(); + void _init_sentinel(); + pair _insert(const value_type& value); + node* _erase(iterator pos); + node* _subtree_shift(node* st_old, node* st_new); + // AVL Balancing + void _insert_rebalancing(node* n); + void _erase_rebalancing(node* n); - /************* - * observers : - *************/ -// key_comp ---------------------------------- - key_compare key_comp() const; -// value_comp -------------------------------- - value_compare value_comp() const; + short _compute_height(node* n); + short _bf(node* n); // balance factor + node* _rotate_left(node* n); + node* _rotate_right(node* n); + }; + // Non-member functions + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator==(const map& lhs, const map& rhs); + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator!=(const map& lhs, const map& rhs); + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator<(const map& lhs, const map& rhs); + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator>(const map& lhs, const map& rhs); + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator<=(const map& lhs, const map& rhs); + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator>=(const map& lhs, const map& rhs); - /************** - * operations : - **************/ -// find -------------------------------------- - iterator find (const key_type& k); - const_iterator find (const key_type& k) const; -// count ------------------------------------- - size_type count (const key_type& k) const; -// lower_bound ------------------------------- - iterator lower_bound (const key_type& k); - const_iterator lower_bound (const key_type& k) const; -// upper_bound ------------------------------- - iterator upper_bound (const key_type& k); - const_iterator upper_bound (const key_type& k) const; -// equal_range ------------------------------- - pair equal_range (const key_type& k) const; - pair equal_range (const key_type& k); - - - /************* - * allocator : - *************/ -// get_allocator ----------------------------- - allocator_type get_allocator() const; - - // TMP non privat - bst_map _bst; -private: - - allocator_type _allocator; - key_compare _comp; - -}; - - - /************************ - * non-member functions : - ************************/ -// operator == ------------------------------- -template< class K, class T, class Comp, class Alloc > bool operator== - ( const std::map& lhs, const std::map& rhs ); -// operator != ------------------------------- -template< class K, class T, class Comp, class Alloc > bool operator!= - ( const std::map& lhs, const std::map& rhs ); -// operator < -------------------------------- -template< class K, class T, class Comp, class Alloc > bool operator< - ( const std::map& lhs, const std::map& rhs ); -// operator <= ------------------------------- -template< class K, class T, class Comp, class Alloc > bool operator<= - ( const std::map& lhs, const std::map& rhs ); -// operator > -------------------------------- -template< class K, class T, class Comp, class Alloc > bool operator> - ( const std::map& lhs, const std::map& rhs ); -// operator >= ------------------------------- -template< class K, class T, class Comp, class Alloc > bool operator>= - ( const std::map& lhs, const std::map& rhs ); -// swap (map) ----------------------------- -template< class Key, class T, class Compare, class Alloc > void swap - ( std::map& lhs, std::map& rhs ); - + template < typename Key, typename T, typename Compare, typename Alloc > + void swap(map& lhs, map& rhs); } // namespace ft -# include "map.tpp" +# include "bst.tpp" + +// https://en.wikipedia.org/wiki/Binary_search_tree +// https://en.wikipedia.org/wiki/AVL_tree + +// https://fr.wikipedia.org/wiki/Arbre_binaire_de_recherche +// https://fr.wikipedia.org/wiki/Arbre_AVL + +// https://visualgo.net/en/bst +// https://visualgo.net/en/bst?slide=14-8 // --> to 14-13 + #endif diff --git a/headers/map_iterator.hpp b/headers/map_iterator.hpp new file mode 100644 index 0000000..9a70567 --- /dev/null +++ b/headers/map_iterator.hpp @@ -0,0 +1,207 @@ +#ifndef MAP_ITERATOR_HPP +# define MAP_ITERATOR_HPP + +# include // NULL, ptrdiff_t +# include // iterator_tag + +# include "pair.hpp" +# include "map_node.hpp" + +namespace ft { + +template < + typename Key, + typename T, + typename Compare, + typename Allocator +> class map_iterator +{ + private: + typedef map_iterator Self; + + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef pair value_type; + typedef std::ptrdiff_t difference_type; + typedef value_type* pointer; + typedef value_type& reference; + + map_iterator() : _node(), _sentinel() {} + map_iterator(node* n, node_sentinel* sentinel) : _node(n), _sentinel(sentinel) {} + //map_iterator(const map_iterator& src) : _node(src._node), _sentinel(src._sentinel) {} //implicit + + reference operator*() const + { return _node->value; } + pointer operator->() const + { return &_node->value; } + + Self& operator++() + { + if (_node == NULL) + _node = _sentinel->child->min(); + else if (_node->right) + _node = _node->right->min(); + else + { + node* up = _node->up; + while (up != NULL && _node == up->right) + { + _node = up; + up = up->up; + } + _node = up; + } + return *this; + } + + Self& operator--() + { + if (_node == NULL) + _node = _sentinel->child->max(); + else if (_node->left) + _node = _node->left->max(); + else + { + node* up = _node->up; + while (up != NULL && _node == up->left) + { + _node = up; + up = up->up; + } + _node = up; + } + return *this; + } + + Self operator++(int) + { + //Self old(*this); + Self old = *this; + ++(*this); + return old; + } + + Self operator--(int) + { + //Self old(*this); + Self old = *this; + --(*this); + return old; + } + + node* getNode() + { return _node; } + const node* getNode() const + { return _node; } + const node_sentinel* getSentinel() const + { return _sentinel; } + + // TODO : friend Non-member functions syntaxe pas clair. + friend bool operator==(const Self &lhs, const Self &rhs) + { return lhs._node == rhs._node; } + friend bool operator!=(const Self &lhs, const Self &rhs) + { return !(lhs._node == rhs._node); } + + private: + node* _node; + node_sentinel* _sentinel; +}; + +template < + typename Key, + typename T, + typename Compare, + typename Allocator +> class map_const_iterator +{ + private: + typedef map_const_iterator Self; + + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef pair value_type; + typedef std::ptrdiff_t difference_type; + typedef const value_type* pointer; + typedef const value_type& reference; + + map_const_iterator() : _node(), _sentinel() {} + map_const_iterator(const node* node, const node_sentinel* sentinel) : _node(node), _sentinel(sentinel) {} + //map_const_iterator(const map_const_iterator& src) : _node(src._node), _sentinel(src._sentinel) {} //implicit + map_const_iterator(const map_iterator& src) : _node(src.getNode()), _sentinel(src.getSentinel()) {} + + reference operator*() const + { return _node->value; } + pointer operator->() const + { return &_node->value; } + + Self& operator++() + { + if (_node == NULL) + _node = _sentinel->child->min(); + else if (_node->right) + _node = _node->right->min(); + else + { + node* up = _node->up; + while (up != NULL && _node == up->right) + { + _node = up; + up = up->up; + } + _node = up; + } + return *this; + } + + Self& operator--() + { + if (_node == NULL) + _node = _sentinel->child->max(); + else if (_node->left) + _node = _node->left->max(); + else + { + node* up = _node->up; + while (up != NULL && _node == up->left) + { + _node = up; + up = up->up; + } + _node = up; + } + return *this; + } + + Self operator++(int) + { + //Self old(*this); + Self old = *this; + ++(*this); + return old; + } + + Self operator--(int) + { + //Self old(*this); + Self old = *this; + --(*this); + return old; + } + + node* getNode() const + { return _node; } + + friend bool operator==(const Self &lhs, const Self &rhs) + { return lhs._node == rhs._node; } + friend bool operator!=(const Self &lhs, const Self &rhs) + { return !(lhs._node == rhs._node); } + + private: + const node* _node; + const node_sentinel* _sentinel; +}; + +} // namespace ft + +#endif + diff --git a/headers/map_node.hpp b/headers/map_node.hpp new file mode 100644 index 0000000..3481ca9 --- /dev/null +++ b/headers/map_node.hpp @@ -0,0 +1,50 @@ + +#ifndef MAP_NODE_HPP +# define MAP_NODE_HPP + +# include // NULL + +namespace ft { + +template < typename ValueType > +struct node +{ + ValueType value; + node *up; + node *left; + node *right; + short height; + + node(const ValueType& val) : value(val), up(NULL), left(NULL), right(NULL), height(1) {} + + node* min() + { + node* n = this; + + while (n->left) + n = n->left; + return n; + } + + node* max() + { + node* n = this; + + while (n->right) + n = n->right; + return n; + } +}; + +template < typename ValueType > +struct node_sentinel +{ + node *child; + + node_sentinel() : child(NULL) {} +}; + +} // namespace ft + +#endif + diff --git a/templates/bst.tpp b/templates/bst.tpp index 0ade6c0..77a5f5a 100644 --- a/templates/bst.tpp +++ b/templates/bst.tpp @@ -1,6 +1,6 @@ #define BST_TEMPLATE template < typename Key, typename T, typename Compare, typename Allocator > -#define BST Bst +#define BST map namespace ft { @@ -10,7 +10,7 @@ namespace ft { BST_TEMPLATE BST:: - Bst(const Compare& comp, const Allocator& alloc) : + map(const Compare& comp, const Allocator& alloc) : _size(0), _root(NULL), _comp(comp), @@ -22,7 +22,7 @@ _allocator(alloc) BST_TEMPLATE template < typename InputIt > BST:: - Bst(InputIt first, InputIt last, const Compare& comp, const Allocator& alloc) : + map(InputIt first, InputIt last, const Compare& comp, const Allocator& alloc) : _size(0), _root(NULL), _comp(comp), @@ -34,7 +34,7 @@ _allocator(alloc) BST_TEMPLATE BST:: - Bst(const Bst& src) : + map(const map& src) : _size(0), _root(NULL), _comp(src._comp), @@ -46,7 +46,7 @@ _allocator(src._allocator) BST_TEMPLATE BST:: - ~Bst() + ~map() { clear(); _allocator_node_sentinel.destroy(_sentinel); @@ -55,11 +55,11 @@ BST:: BST_TEMPLATE BST& BST:: - operator=(const Bst& rhs) + operator=(const map& rhs) { if (this == &rhs) return (*this); - Bst new_bst(rhs.begin(), rhs.end()); + map new_bst(rhs.begin(), rhs.end()); swap(new_bst); return (*this); } @@ -241,7 +241,7 @@ typename BST::size_type BST:: BST_TEMPLATE void BST:: - swap(Bst& other) + swap(map& other) { node* tmp_root = _root; node_sentinel* tmp_sentinel = _sentinel; diff --git a/templates/bst_bak.tpp b/templates/bst_bak.tpp new file mode 100644 index 0000000..0ade6c0 --- /dev/null +++ b/templates/bst_bak.tpp @@ -0,0 +1,628 @@ + +#define BST_TEMPLATE template < typename Key, typename T, typename Compare, typename Allocator > +#define BST Bst + +namespace ft { + + + ////////////////////// + // Member functions // + +BST_TEMPLATE +BST:: + Bst(const Compare& comp, const Allocator& alloc) : +_size(0), +_root(NULL), +_comp(comp), +_allocator(alloc) +{ + _init_sentinel(); +} + +BST_TEMPLATE +template < typename InputIt > +BST:: + Bst(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:: + Bst(const Bst& src) : +_size(0), +_root(NULL), +_comp(src._comp), +_allocator(src._allocator) +{ + _init_sentinel(); + *this = src; +} + +BST_TEMPLATE +BST:: + ~Bst() +{ + clear(); + _allocator_node_sentinel.destroy(_sentinel); + _allocator_node_sentinel.deallocate(_sentinel, 1); +} + +BST_TEMPLATE +BST& BST:: + operator=(const Bst& rhs) +{ + if (this == &rhs) + return (*this); + Bst 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(Bst& 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 + diff --git a/tests/main.cpp b/tests/main.cpp index 05fe950..b5696e7 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -49,14 +49,14 @@ int main() { tests_map_erase(); tests_map_swap(); tests_map_clear(); - tests_map_key_comp(); - tests_map_value_comp(); +// tests_map_key_comp(); +// tests_map_value_comp(); tests_map_find(); tests_map_count(); - tests_map_lower_bound(); - tests_map_upper_bound(); - tests_map_equal_range(); - tests_map_get_allocator(); +// tests_map_lower_bound(); +// tests_map_upper_bound(); +// tests_map_equal_range(); +// tests_map_get_allocator(); // tests_map_relational_operators(); tests_map_swap_non_member(); diff --git a/tests/tests_map.cpp b/tests/tests_map.cpp index 1472110..54373fc 100644 --- a/tests/tests_map.cpp +++ b/tests/tests_map.cpp @@ -336,6 +336,7 @@ TEST_M(tests_map_clear) DELETE } +/* TEST_M(tests_map_key_comp) { // title @@ -385,6 +386,7 @@ TEST_M(tests_map_value_comp) DELETE } +*/ TEST_M(tests_map_find) { @@ -437,6 +439,7 @@ TEST_M(tests_map_count) DELETE } +/* TEST_M(tests_map_lower_bound) { // title @@ -529,6 +532,7 @@ TEST_M(tests_map_get_allocator) DELETE } +*/ TEST_M(tests_map_relational_operators) {