From 49051b5571ca48c65e33f5472198fc773ba48523 Mon Sep 17 00:00:00 2001 From: kinou-p Date: Sat, 26 Nov 2022 17:05:21 +0100 Subject: [PATCH] map work? --- .../iterators/bidirectionnal_iterator.hpp | 80 +- containers/iterators/pair.hpp | 18 +- containers/map.hpp | 807 ++++++++++------- containers/set.hpp | 809 +++++++++++++++++- 4 files changed, 1365 insertions(+), 349 deletions(-) diff --git a/containers/iterators/bidirectionnal_iterator.hpp b/containers/iterators/bidirectionnal_iterator.hpp index a8ae353..72b17eb 100644 --- a/containers/iterators/bidirectionnal_iterator.hpp +++ b/containers/iterators/bidirectionnal_iterator.hpp @@ -6,12 +6,14 @@ /* By: apommier +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/11/22 14:50:53 by apommier #+# #+# */ -/* Updated: 2022/11/25 18:27:27 by apommier ### ########.fr */ +/* Updated: 2022/11/26 16:26:57 by apommier ### ########.fr */ /* */ /* ************************************************************************** */ #pragma once +#define _end 0 + namespace ft { @@ -31,13 +33,14 @@ class bidirectionnal_iterator private : + node_type *_root; node_type *_node; public : bidirectionnal_iterator() : _node(NULL) {} - bidirectionnal_iterator(node_type *cpy) { _node = cpy; } - bidirectionnal_iterator(bidirectionnal_iterator const &rhs) { this->_node = rhs._node; } + bidirectionnal_iterator(node_type *root, node_type *node) : _root(root), _node(node) {} + bidirectionnal_iterator(bidirectionnal_iterator const &rhs) { *this = rhs; } ~bidirectionnal_iterator() {} @@ -45,6 +48,8 @@ class bidirectionnal_iterator { if (this != &rhs) { + this->_root = rhs._root; + //this->_end = rhs._end; this->_node = rhs._node; } return (*this); @@ -52,20 +57,23 @@ class bidirectionnal_iterator operator bidirectionnal_iterator() const { - return (bidirectionnal_iterator(_node)); + return (bidirectionnal_iterator(_root, _node)); } - bool operator==(bidirectionnal_iterator &rhs) { return (_node == rhs._node); } - bool operator!=(bidirectionnal_iterator &rhs) { return (_node != rhs._node); } + node_type *base() { return (_node); } + + friend bool operator==(const bidirectionnal_iterator &rhs, const bidirectionnal_iterator &lhs) { return (lhs._node == rhs._node); } + friend bool operator!=(const bidirectionnal_iterator &rhs, const bidirectionnal_iterator &lhs) { return (lhs._node != rhs._node); } - reference operator*() { return (_node->pair); } - const_reference operator*() const { return (_node->pair); } - pointer operator->() { return (&(_node->pair)); } - const_pointer operator->() const { return (&(_node->pair)); } + reference operator*() { return (_node->data); } + const_reference operator*() const { return (_node->data); } + pointer operator->() { return (&(_node->data)); } + const_pointer operator->() const { return (&(_node->data)); } bidirectionnal_iterator &operator ++() { - //_node = ; + if (_node != NULL) + _node = successor(_node); return (*this); } @@ -78,7 +86,10 @@ class bidirectionnal_iterator bidirectionnal_iterator &operator --() { - //_node = ; + if (_node == _end) + _node = maximum(_root); + else + _node = predecessor(_node); return (*this); } @@ -88,7 +99,52 @@ class bidirectionnal_iterator ++(*this); return (tmp); } + + private : + + node_type *maximum(node_type *ptr) + { + while (ptr->right != _end) + ptr = ptr->right; + return (ptr); + } + node_type *minimum(node_type *ptr) + { + while (ptr->left != _end) + ptr = ptr->left; + return (ptr); + } + + node_type *predecessor(node_type *x) + { + if (x->left != _end) + { + return maximum(x->left); + } + node_type *y = x->parent; + while (y != NULL && x == y->left) + { + x = y; + y = y->parent; + } + return y; + } + + node_type *successor(node_type *x) + { + if (x->right != _end) + return minimum(x->right); + node_type *y = x->parent; + while (y != NULL && x == y->right) + { + x = y; + y = y->parent; + } + if (y == NULL) + return _end; + return y; + } }; } \ No newline at end of file diff --git a/containers/iterators/pair.hpp b/containers/iterators/pair.hpp index a2371e5..0a0972e 100644 --- a/containers/iterators/pair.hpp +++ b/containers/iterators/pair.hpp @@ -6,7 +6,7 @@ /* By: apommier +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/11/22 13:39:29 by apommier #+# #+# */ -/* Updated: 2022/11/25 18:21:34 by apommier ### ########.fr */ +/* Updated: 2022/11/26 13:39:18 by apommier ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,8 +19,8 @@ namespace ft typedef T1 first_type; typedef T2 second_type; - T1 first; - T2 second; + first_type first; + second_type second; pair(): first(), second() {} pair( const T1& x, const T2& y ) : first(x), second(y) {} @@ -28,12 +28,16 @@ namespace ft template pair(const pair& p): first(p.first), second(p.second) { } - pair& operator=(const pair& other) - { - first = other.first; - second = other.second; + pair& operator= (const pair& pr) { + if (this != &pr) + { + this->first = pr.first; + this->second = pr.second; + } return (*this); } + + ~pair() {} }; template diff --git a/containers/map.hpp b/containers/map.hpp index 28c6116..d504a71 100644 --- a/containers/map.hpp +++ b/containers/map.hpp @@ -5,8 +5,8 @@ /* +:+ +:+ +:+ */ /* By: apommier +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2022/11/24 08:50:18 by apommier #+# #+# */ -/* Updated: 2022/11/25 17:48:41 by apommier ### ########.fr */ +/* Created: 2022/11/26 15:23:32 by apommier #+# #+# */ +/* Updated: 2022/11/26 17:03:16 by apommier ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,10 +14,12 @@ #include "./iterators/bidirectionnal_iterator.hpp" #include "./iterators/pair.hpp" +#include "./iterators/make_pair.hpp" #include "vector.hpp" #define RED 1 #define BLACK 0 +#define _end 0 //typedef typename Alloc::template rebind >::other @@ -28,7 +30,7 @@ template< class Key, class T, class Compare = std::less, - class Allocator = std::allocator>> + class Allocator = std::allocator > > class map { @@ -45,7 +47,6 @@ class map typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef Compare key_compare; - typedef Compare value_compare; typedef Allocator allocator_type; typedef typename Allocator::template rebind::other node_allocator_type; typedef value_type& reference; @@ -56,29 +57,39 @@ class map typedef ft::bidirectionnal_iterator const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; + + class value_compare; - struct node{ - bool color; - node *parent; - node *right; - node *left; - value_type pair; - - node(key_type &key, mapped_type &val) - : pair(make_pair(key, val)), parent(0), right(this->_end), left(this->_end), color(0) {} - }; - //----------------------------- - //-----PRIVATE MEMBER TYPE----- - //----------------------------- - private : + protected : key_compare _comp; allocator_type _alloc; node_allocator_type _node_alloc; node *_root; - node *_end; + //node *_end; size_type _size; + + public : + + + struct node{ + value_type data; + node *parent; + node *right; + node *left; + bool color; + + //node() : parent(0), right(map::_end), left(map::_end), color(0) {} + node(key_type const &key, mapped_type const &val) + : data(ft::make_pair(key, val)), parent(0), right(_end), left(_end), color(0) + {} + //std::cout << "end in construct= " << _end << std::endl; + }; + //----------------------------- + //-----PRIVATE MEMBER TYPE----- + //----------------------------- + public : @@ -86,15 +97,20 @@ class map //---------COPLIEN FORM FUNCTION--------- //--------------------------------------- - explicit map( const Compare& comp = Compare(), const Allocator& alloc = Allocator() ) : _alloc(alloc) + explicit map( const Compare& comp = Compare(), const Allocator& alloc = Allocator() ) : _comp(comp), _alloc(alloc), _root(_end) { - + //_end = _node_alloc.allocate(1); + //_node_alloc.construct(_end, node()); + _size = 0; } template< class InputIt > - map( InputIt first, InputIt last, const Compare& comp = Compare(), const Allocator& alloc = Allocator() ) : _alloc(alloc) + map( InputIt first, InputIt last, const Compare& comp = Compare(), const Allocator& alloc = Allocator() ) : _comp(comp), _alloc(alloc), _root(_end) { - + _size = 0; + //_end = _node_alloc.allocate(1); + //_node_alloc.construct(_end, node()); + this->insert(first, last); } map( const map& x) @@ -109,14 +125,15 @@ class map map& operator=(const map& x) { - _comp = x->_comp; - _alloc = x->_alloc; - _node_alloc = x->_node_alloc; - _root = x->_root; - _end = x->_end; - _size = x->_size; + _comp = x._comp; + _alloc = x._alloc; + _node_alloc = x._node_alloc; + _root = x._root; + //_end = x._end; + _size = x._size; + return (*this); } - + //---------------------------------- //---------MEMBER FUNCTION---------- //---------------------------------- @@ -126,22 +143,22 @@ class map //------------------------- iterator begin() { - return iterator(_root); + return iterator(_root, _root); } const_iterator begin() const { - return const_iterator(_root); + return const_iterator(_root, _root); } iterator end() { - return iterator(_end); + return iterator(_root, _end); } const_iterator end() const { - return const_iterator(_end); + return const_iterator(_root, _end); } reverse_iterator rbegin() @@ -193,11 +210,13 @@ class map mapped_type& operator[] (const key_type& k) { iterator tmp = this->find(k); + //ft::pair<> new_pair = ft::make_pair(k, mapped_type()); + value_type new_pair = ft::make_pair(k, mapped_type()); - if (tmp->m == _end) - return (*((this->insert(make_pair(k, mapped_type()))).second)); //?????? + if (tmp.base() == _end) + return this->insert_node(new_pair.first, new_pair.second)->data.second; //?????? else - return (*tmp.pair->second); + return ((*tmp).second); } mapped_type& at (const key_type& k) @@ -207,7 +226,7 @@ class map if (tmp->m == _end) throw (std::out_of_range("ft::map::at")); else - return (*tmp.pair->second); + return (*tmp.pair.second); } const mapped_type& at (const key_type& k) const @@ -217,41 +236,66 @@ class map if (tmp->m == _end) throw (std::out_of_range("ft::map::at")); else - return (*tmp.pair->second); + return (*tmp.pair.second); } - //------------------------- //--------Modifiers-------- //------------------------- ft::pair insert (const value_type& val) { - + // if (this->insert_node(val.first, val.second)) + // _size++; + node *pt = new_node(val.first, val.second); + _root = insert_node(_root, pt); + fixViolation(_root, pt); } iterator insert (iterator position, const value_type& val) { - + (void)position; + // if (this->insert_node(val.first, val.second)) + // _size++; + node *pt = new_node(val.first, val.second); + _root = insert_node(_root, pt); + fixViolation(_root, pt); } - template void insert (InputIterator first, InputIterator last) + template + void insert (InputIterator first, InputIterator last) { - + int i = 0; + while (first != last) + { + // std::cout << "i === " << i++ << std::endl; + // if (this->insert_node(_root, new_node((*first).first, (*first).second))) + // _size++; + // first++; + node *pt = new_node((*first).first, (*first).second); + _root = insert_node(_root, pt); + fixViolation(_root, pt); + first++; + } } void erase (iterator position) { - + delete_node(position.base()); } size_type erase (const key_type& k) { - + delete_node(find(k).base()); + return(1); } void erase (iterator first, iterator last) { - + while (first != last) + { + delete_node(first.base()); + first++; + } } void swap (map& x) @@ -262,21 +306,21 @@ class map tmp->_alloc = _alloc; tmp->_node_alloc = _node_alloc; tmp->_root = _root; - tmp->_end = _end; + //tmp->_end = _end; tmp->_size = _size; _comp = x->_comp; _alloc = x->_alloc; _node_alloc = x->_node_alloc; _root = x->_root; - _end = x->_end; + //_end = x->_end; _size = x->_size; x->_comp = tmp-> _comp; x->_alloc = tmp->_alloc; x->_node_alloc = tmp->_node_alloc; x->_root = tmp->_root; - x->_end = tmp->_end; + //x->_end = tmp->_end; x->_size = tmp->_size; } @@ -291,12 +335,12 @@ class map key_compare key_comp() const { - + return (_comp); } value_compare value_comp() const { - + return (value_compare(_comp)); } @@ -307,29 +351,31 @@ class map iterator find (const key_type& k) { node *x = _root; - - while (x != _end && x->pair->first != k) + int i = 0; + while (x != _end && x->data.first != k) { - if (k > x->pair->first) + std::cout << "i === " << i << std::endl; + if (k > x->data.first) x = x->left; else x = x->right; + i++; } - return (iterator(x)); + return (iterator(_root, _end, x)); } const_iterator find (const key_type& k) const { node *x = _root; - while (x != _end && x->pair->first != k) + while (x != _end && x->data.first != k) { - if (k > x->pair->first) + if (k > x->data.first) x = x->left; else x = x->right; } - return (iterator(x)); + return (iterator(_root, _end, x)); } size_type count (const key_type& k) const @@ -341,319 +387,430 @@ class map iterator lower_bound (const key_type& k) { - + iterator it = begin(), ite = end(); + + while (it != ite && !(_comp((*it).first, k))) + it++; + return (it); } const_iterator lower_bound (const key_type& k) const { - + const_iterator it = begin(), ite = end(); + + while (it != ite && !(_comp((*it).first, k))) + it++; + return (it); } iterator upper_bound (const key_type& k) { - + iterator it = begin(), ite = end(); + + while (it != ite && !(_comp((*it).first, k))) + it++; + return (it); } const_iterator upper_bound (const key_type& k) const { - + const_iterator it = begin(), ite = end(); + + while (it != ite && _comp((*it).first, k)) + it++; + return (it); } ft::pair equal_range (const key_type& k) const { - + return (ft::make_pair(lower_bound(k), upper_bound(k))); } ft::pair equal_range (const key_type& k) { - + return (ft::make_pair(lower_bound(k), upper_bound(k))); } + /* ************************************************************************** */ + /* ************************************************************************** */ /* ************************************************************************** */ /* ******************************TREE FUNCTIONS****************************** */ /* ************************************************************************** */ + /* ************************************************************************** */ + /* ************************************************************************** */ private : - - void inorderHelper() + + void rotateLeft(node *&root, node *&pt) { - if (_root == NULL) - return; - inorderHelper(_root->left); - std::cout << _root->data << " "; - inorderHelper(_root->right); + node *pt_right = pt->right; + pt->right = pt_right->left; + if (pt->right != NULL) + pt->right->parent = pt; + pt_right->parent = pt->parent; + if (pt->parent == NULL) + root = pt_right; + else if (pt == pt->parent->left) + pt->parent->left = pt_right; + else + pt->parent->right = pt_right; + pt_right->left = pt; + pt->parent = pt_right; } - void levelOrderHelper() + + void rotateRight(node *&root, node *&pt) { - if (_root == NULL) - return; - ft::vector v; - v.push(_root); - while (!v.empty()) - { - node *temp = v.front(); - std::cout << temp->data << " "; - v.pop(); - if (temp->left != NULL) - v.push(temp->left); - if (temp->right != NULL) - v.push(temp->right); - } + + node *pt_left = pt->left; + pt->left = pt_left->right; + if (pt->left != NULL) + pt->left->parent = pt; + pt_left->parent = pt->parent; + if (pt->parent == NULL) + root = pt_left; + else if (pt == pt->parent->left) + pt->parent->left = pt_left; + else + pt->parent->right = pt_left; + pt_left->right = pt; + pt->parent = pt_left; } - template + node* insert_node(node* root, node *pt) + { + /* If the tree is empty, return a new node */ + if (root == NULL) + return pt; + /* Otherwise, recur down the tree */ + if (pt->data < root->data) + { + root->left = insert_node(root->left, pt); + root->left->parent = root; + } + else if (pt->data > root->data) + { + root->right = insert_node(root->right, pt); + root->right->parent = root; + } + /* return the (unchanged) node pointer */ + return root; + } + + void fixViolation(node *&root, node *&pt) + { + node *parent_pt = NULL; + node *grand_parent_pt = NULL; + while ((pt != root) && (pt->color != BLACK) && (pt->parent->color == RED)) + { + parent_pt = pt->parent; + grand_parent_pt = pt->parent->parent; + /* Case : A Parent of pt is left child of Grand-parent of pt */ + if (parent_pt == grand_parent_pt->left) + { + node *uncle_pt = grand_parent_pt->right; + /* Case : 1 The uncle of pt is also red Only Recoloring required */ + if (uncle_pt != NULL && uncle_pt->color == RED) + { + grand_parent_pt->color = RED; + parent_pt->color = BLACK; + uncle_pt->color = BLACK; + pt = grand_parent_pt; + } + else + { + /* Case : 2 pt is right child of its parent Left-rotation required */ + if (pt == parent_pt->right) + { + rotateLeft(root, parent_pt); + pt = parent_pt; + parent_pt = pt->parent; + } + /* Case : 3 pt is left child of its parent Right-rotation required */ + rotateRight(root, grand_parent_pt); + swapColors(parent_pt, grand_parent_pt); + pt = parent_pt; + } + } + /* Case : B Parent of pt is right child of Grand-parent of pt */ + else + { + node *uncle_pt = grand_parent_pt->left; + /* Case : 1 The uncle of pt is also red Only Recoloring required */ + if ((uncle_pt != NULL) && (uncle_pt->color == RED)) + { + grand_parent_pt->color = RED; + parent_pt->color = BLACK; + uncle_pt->color = BLACK; + pt = grand_parent_pt; + } + else + { + /* Case : 2 | pt is left child of its parent | Right-rotation required */ + if (pt == parent_pt->left) + { + rotateRight(root, parent_pt); + pt = parent_pt; + parent_pt = pt->parent; + } + /* Case : 3 pt is right child of its parent Left-rotation required */ + rotateLeft(root, grand_parent_pt); + swapColors(parent_pt, grand_parent_pt); + pt = parent_pt; + } + } + } + root->color = BLACK; + } + + /* ************************************************************************** */ + /* **********************************DELETE********************************** */ + /* ************************************************************************** */ + + + node *uncle(node *x) + { + if (x->parent == NULL or x->parent->parent == NULL) + return NULL; + if (x->parent->isOnLeft()) + return x->parent->parent->right; + else + return x->parent->parent->left; + } + + bool isOnLeft(node *x) { return this == x->parent->left; } + + // returns pointer to sibling + node *sibling(node *x) + { + // sibling null if no parent + if (x->parent == NULL) + return NULL; + if (isOnLeft()) + return x->parent->right; + return x->parent->left; + } + + // moves node down and moves given node in its place + void moveDown(node *nParent, node *x) + { + if (x->parent != NULL) + { + if (isOnLeft()) + x->parent->left = nParent; + else + x->parent->right = nParent; + } + nParent->parent = x->parent; + x->parent = nParent; + } + + bool hasRedChild(node *x) + { + return (x->left != NULL and x->left->color == RED) or (x->right != NULL and x->right->color == RED); + } + + void swapColors(node *x1, node *x2) + { + bool temp; + temp = x1->color; + x1->color = x2->color; + x2->color = temp; + } + + void swapValues(node *u, node *v) + { + int temp; + temp = u->val; + u->val = v->val; + v->val = temp; + } + + void fixRedRed(node *x) + { + // if x is root color it black and return + if (x == _root) + { + x->color = BLACK; + return; + } + // initialize parent, grandparent, uncle + node *parent = x->parent, *grandparent = parent->parent, + *uncle = x->uncle(); + if (parent->color != BLACK) + { + if (uncle != NULL && uncle->color == RED) + { + // uncle red, perform recoloring and recurse + parent->color = BLACK; + uncle->color = BLACK; + grandparent->color = RED; + fixRedRed(grandparent); + } + else + { + // Else perform LR, LL, RL, RR + if (parent->isOnLeft()) + { + if (x->isOnLeft()) + { + // for left right + swapColors(parent, grandparent); + } + else + { + leftRotate(parent); + swapColors(x, grandparent); + } + // for left left and left right + rightRotate(grandparent); + } + else + { + if (x->isOnLeft()) + { + // for right left + rightRotate(parent); + swapColors(x, grandparent); + } + else + swapColors(parent, grandparent); + // for right right and right left + leftRotate(grandparent); + } + } + } + } + + // find node that do not have a left child + // in the subtree of the given node + node *successor(node *x) + { + node *temp = x; + + while (temp->left != NULL) + temp = temp->left; + return temp; + } + + // find node that replaces a deleted node in BST + node *replace_node(node *x) + { + // when node have 2 children + if (x->left != NULL and x->right != NULL) + return successor(x->right); + // when leaf + if (x->left == NULL and x->right == NULL) + return NULL; + // when single child + if (x->left != NULL) + return x->left; + else + return x->right; + } + + // deletes the given node + void deleteNode(node *v) + { + node *u = replace_node(v); + + // True when u and v are both black + bool uvBlack = ((u == NULL or u->color == BLACK) and (v->color == BLACK)); + node *parent = v->parent; + if (u == NULL) + { + // u is NULL therefore v is leaf + if (v == _root) + _root = NULL;// v is root, making root null + else + { + if (uvBlack) + { + // u and v both black + // v is leaf, fix double black at v + fixDoubleBlack(v); + } + else + { + // u or v is red + if (v->sibling() != NULL) + // sibling is not null, make it red" + v->sibling()->color = RED; + } + // delete v from the tree + if (v->isOnLeft()) + parent->left = NULL; + else + parent->right = NULL; + } + delete v; + return; + } + if (v->left == NULL or v->right == NULL) + { + // v has 1 child + if (v == _root) + { + // v is root, assign the value of u to v, and delete u + v->val = u->val; + v->left = v->right = NULL; + delete u; + } + else + { + // Detach v from tree and move u up + if (v->isOnLeft()) + parent->left = u; + else + parent->right = u; + delete v; + u->parent = parent; + if (uvBlack) + fixDoubleBlack(u);// u and v both black, fix double black at u + else + u->color = BLACK;// u or v red, color u black + } + return; + } + // v has 2 children, swap values with successor and recurse + swapValues(u, v); + deleteNode(u); + } + + //template node *new_node(key_type key, mapped_type val) { node *ret; - ret = _alloc.allocate(1); - _alloc.construct(ret, node(key, val)); + ret = _node_alloc.allocate(1); + _node_alloc.construct(ret, node(key, val)); //ret = _node_alloc::allocate(1); //_node_alloc::construct(ret, node(key, val)); return (ret); } - - void left_rotate(node *elem) //x == elem - { - node *pt_right = elem->right; - - elem->right = pt_right->left; - if (elem->right != NULL) - elem->right->parent = elem; - pt_right->parent = elem->parent; - if (elem->parent == NULL) - _root = pt_right; - else if (elem == elem->parent->left) - elem->parent->left = pt_right; - else - elem->parent->right = pt_right; - pt_right->left = elem; - elem->parent = pt_right; - } - - void right_rotate(node *elem) - { - node *pt_left = elem->left; - - elem->left = pt_left->right; - if (elem->left != NULL) - elem->left->parent = elem; - pt_left->parent = elem->parent; - if (elem->parent == NULL) - _root = pt_left; - else if (elem == elem->parent->left) - elem->parent->left = pt_left; - else - elem->parent->right = pt_left; - pt_left->right = elem; - elem->parent = pt_left; - } - - void delete_node(node *z) - { - node *x; - node *y; - - if (z->left == _end || z->right == _end)//case1 - y = z; - // else //case2 - // y = TREE-SUCCESSOR(z); - if (y->left != _end) - x = y->left; - else - x = y->right; - x->parent = y->parent; // Do this, even if x is _end - if (y->parent == _end) - _root = x; - else if (y == y->parent->left) //(*if y is a left child.*) - y->parent->left = x; - else - y->parent->right = x; //(*if y is a right child.*) - if (y != z ) - z->pair->first = y->pair->first; - //copy y’s satellite data into z - if (y->color == BLACK) - delete_fix(x); - return (y); - } - - void delete_fix(node *x) - { - node *w; - node *z; - - while (x != _root && x->color == BLACK) - { - if (x == x->parent->left) - { - w = x->parent->right; - if (w->color == RED) // Case 1 - { - w->color = BLACK; - x->parent->color = RED; - left_rotate(x->parent); - w = x->parent->right; - } - if (w->left->color == BLACK && w->right->color == BLACK)// Case 2 - { - w->color = RED; - x = x->parent; - x->parent = z->parent->parent; - } - else if (w->right->color == BLACK) // Case 3 - { - w->left->color = BLACK; - w->color = RED; - right_rotate(w); - w = x->parent->right; - } - w->color = x->parent->color; // Case 4 - x->parent->color = BLACK; // Case 4 - w->right->color = BLACK; // Case 4 - left_rotate(x->parent); // Case 4 - x = _root; // Case 4 - } - else //same as 3 - 21 with “right” and “left” exchanged - { - w = x->parent->left; - if (w->color == RED) // Case 1 - { - w->color = BLACK; // Case 1 - x->parent->color = RED; // Case 1 - right_rotate(x->parent); // Case 1 - w = x->parent->left; // Case 1 - } - if (w->right->color == BLACK && w->left->color == BLACK) - { - w->color = RED; // Case 2 - x = x->parent; // Case 2 - x->parent = z->parent->parent; // Case 2 - } - else if (w->left->color == BLACK) // Case 3 - { - w->right->color = BLACK; // Case 3 - w->color = RED; // Case 3 - left_rotate(w); // Case 3 - w = x->parent->left; // Case 3 - } - w->color = x->parent->color; // Case 4 - x->parent->color = BLACK; // Case 4 - w->left->color = BLACK; // Case 4 - right_rotate(x->parent); // Case 4 - //x = _root; // Case 4 ??? - //left - } - } - x->color = BLACK; - } - - - - - - - - - - - - - - - +}; //end of map class - void insert_fix(node *new_elem, node *parent) - { - node *uncle = NULL; - - while (new_elem->parent->color == RED) - { - if (new_elem->parent->parent && new_elem->parent == new_elem->parent->parent->left ) - { - uncle = new_elem->parent->parent->right; - if (uncle != _end && uncle->color == RED) //uncle is red == only recoloring - { - new_elem->parent->color = BLACK; //parent - uncle->color = BLACK; - new_elem->parent->parent->color = RED; //grandparent - new_elem = new_elem->parent->parent; - } - else - { - if (new_elem == new_elem->parent->right) //if elem is right child - { - new_elem = new_elem->parent; - left_rotate(new_elem); - } - new_elem->parent->color = BLACK; - new_elem->parent->parent->color = RED; - right_rotate(new_elem->parent->parent); - } - } - else - { - uncle = new_elem->parent->parent->left; - if (uncle != _end && uncle->color == RED) //uncle is red == only recoloring - { - new_elem->parent->color = BLACK; //parent - uncle->color = BLACK; - new_elem->parent->parent->color = RED; //grandparent - new_elem = new_elem->parent->parent; - } - else - { - if (new_elem == new_elem->parent->left) //if elem is right child - { - new_elem = new_elem->parent; - right_rotate(new_elem); - } - new_elem->parent->color = BLACK; - new_elem->parent->parent->color = RED; - left_rotate(new_elem->parent->parent); - } - } - } - _root->color = BLACK; - } - - node *insert(key_type key, mapped_type val) - { - node *x = _root; - node *new_parent; +//---------------------------------- +//----------COMPARE CLASS----------- +//---------------------------------- - if (this->empty()) +template +class map::value_compare //man map::value_compare +{ // in C++98, it is required to inherit binary_function + friend class map; + protected: + Compare comp; + value_compare(Compare c) : comp(c) {} // constructed with map's comparison object + public: + typedef bool result_type; + typedef value_type first_argument_type; + typedef value_type second_argument_type; + bool operator() (const value_type& x, const value_type& y) const { - _root = new_node(key, val); - _end = _root; - _size = 1; - return _root; + return comp(x.first, y.first); } - else - { - while (x != _end) - { - new_parent = x; - if (key < x->key) - x = x->right; - else if (key > x->key) - x = x->left; - else - return (x); - } - x = new_node(key, val); - x->parent = new_parent; - if (key < new_parent->key) - new_parent->left = x; - else - new_parent->right = x; - x->color = RED; - return (x); - } - this->insert_fix(); - } }; } \ No newline at end of file diff --git a/containers/set.hpp b/containers/set.hpp index c263123..251cfe7 100644 --- a/containers/set.hpp +++ b/containers/set.hpp @@ -5,12 +5,811 @@ /* +:+ +:+ +:+ */ /* By: apommier +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2022/10/12 19:46:29 by apommier #+# #+# */ -/* Updated: 2022/10/18 10:18:12 by apommier ### ########.fr */ +/* Created: 2022/11/26 15:23:32 by apommier #+# #+# */ +/* Updated: 2022/11/26 17:04:29 by apommier ### ########.fr */ /* */ /* ************************************************************************** */ -#ifndef SET_HPP -# define SET_HPP +#pragma once -#endif \ No newline at end of file +#include "./iterators/bidirectionnal_iterator.hpp" +#include "./iterators/pair.hpp" +#include "./iterators/make_pair.hpp" +#include "vector.hpp" + +#define RED 1 +#define BLACK 0 +#define _end 0 + +//typedef typename Alloc::template rebind >::other + +namespace ft +{ + +template< + class Key, + class T, + class Compare = std::less, + class Allocator = std::allocator > > + +class set +{ + public : + + //----------------------------- + //---------MEMBER TYPE--------- + //----------------------------- + struct node; + + typedef Key key_type; + typedef T mapped_type; + typedef ft::pair value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef Compare key_compare; + typedef Allocator allocator_type; + typedef typename Allocator::template rebind::other node_allocator_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef typename Allocator::pointer pointer; + typedef typename Allocator::const_pointer const_pointer; + typedef ft::bidirectionnal_iterator iterator; + typedef ft::bidirectionnal_iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + class value_compare; + + protected : + + key_compare _comp; + allocator_type _alloc; + node_allocator_type _node_alloc; + + node *_root; + size_type _size; + + public : + + + struct node{ + value_type data; + node *parent; + node *right; + node *left; + bool color; + + //node() : parent(0), right(set::_end), left(set::_end), color(0) {} + node(key_type const &key, mapped_type const &val) + : data(ft::make_pair(key, val)), parent(0), right(_end), left(_end), color(0) + {} + //std::cout << "end in construct= " << _end << std::endl; + }; + //----------------------------- + //-----PRIVATE MEMBER TYPE----- + //----------------------------- + + + public : + + //--------------------------------------- + //---------COPLIEN FORM FUNCTION--------- + //--------------------------------------- + + explicit set( const Compare& comp = Compare(), const Allocator& alloc = Allocator() ) : _comp(comp), _alloc(alloc), _root(_end) + { + //_end = _node_alloc.allocate(1); + //_node_alloc.construct(_end, node()); + _size = 0; + } + + template< class InputIt > + set( InputIt first, InputIt last, const Compare& comp = Compare(), const Allocator& alloc = Allocator() ) : _comp(comp), _alloc(alloc), _root(_end) + { + _size = 0; + //_end = _node_alloc.allocate(1); + //_node_alloc.construct(_end, node()); + this->insert(first, last); + } + + set( const set& x) + { + *this = x; + } + + ~set() + { + + } + + set& operator=(const set& x) + { + _comp = x._comp; + _alloc = x._alloc; + _node_alloc = x._node_alloc; + _root = x._root; + //_end = x._end; + _size = x._size; + return (*this); + } + + //---------------------------------- + //---------MEMBER FUNCTION---------- + //---------------------------------- + + //------------------------- + //--------Iterators-------- + //------------------------- + iterator begin() + { + return iterator(_root, _root); + } + + const_iterator begin() const + { + return const_iterator(_root, _root); + } + + iterator end() + { + return iterator(_root, _end); + } + + const_iterator end() const + { + return const_iterator(_root, _end); + } + + reverse_iterator rbegin() + { + return reverse_iterator(this->end()); + } + + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(this->end()); + } + + reverse_iterator rend() + { + return reverse_iterator(this->begin()); + } + + const_reverse_iterator rend() const + { + return const_reverse_iterator(this->begin()); + } + + + //------------------------ + //--------Capacity-------- + //------------------------ + + bool empty() const + { + if (!_size) + return (1); + return(0); + } + + size_type size() const + { + return (_size); + } + + size_type max_size() const + { + return (_alloc.max_size()); + } + + + //------------------------------ + //--------Element access-------- + //------------------------------ + mapped_type& operator[] (const key_type& k) + { + iterator tmp = this->find(k); + //ft::pair<> new_pair = ft::make_pair(k, mapped_type()); + value_type new_pair = ft::make_pair(k, mapped_type()); + + if (tmp.base() == _end) + return this->insert_node(new_pair.first, new_pair.second)->data.second; //?????? + else + return ((*tmp).second); + } + + mapped_type& at (const key_type& k) + { + iterator tmp = this->find(k); + + if (tmp->m == _end) + throw (std::out_of_range("ft::set::at")); + else + return (*tmp.pair.second); + } + + const mapped_type& at (const key_type& k) const + { + iterator tmp = this->find(k); + + if (tmp->m == _end) + throw (std::out_of_range("ft::set::at")); + else + return (*tmp.pair.second); + } + + //------------------------- + //--------Modifiers-------- + //------------------------- + ft::pair insert (const value_type& val) + { + // if (this->insert_node(val.first, val.second)) + // _size++; + node *pt = new_node(val.first, val.second); + _root = insert_node(_root, pt); + fixViolation(_root, pt); + } + + iterator insert (iterator position, const value_type& val) + { + (void)position; + // if (this->insert_node(val.first, val.second)) + // _size++; + node *pt = new_node(val.first, val.second); + _root = insert_node(_root, pt); + fixViolation(_root, pt); + } + + template + void insert (InputIterator first, InputIterator last) + { + int i = 0; + while (first != last) + { + // std::cout << "i === " << i++ << std::endl; + // if (this->insert_node(_root, new_node((*first).first, (*first).second))) + // _size++; + // first++; + node *pt = new_node((*first).first, (*first).second); + _root = insert_node(_root, pt); + fixViolation(_root, pt); + first++; + } + } + + void erase (iterator position) + { + delete_node(position.base()); + } + + size_type erase (const key_type& k) + { + delete_node(find(k).base()); + return(1); + } + + void erase (iterator first, iterator last) + { + while (first != last) + { + delete_node(first.base()); + first++; + } + } + + void swap (set& x) + { + set tmp; + + tmp->_comp = _comp; + tmp->_alloc = _alloc; + tmp->_node_alloc = _node_alloc; + tmp->_root = _root; + //tmp->_end = _end; + tmp->_size = _size; + + _comp = x->_comp; + _alloc = x->_alloc; + _node_alloc = x->_node_alloc; + _root = x->_root; + //_end = x->_end; + _size = x->_size; + + x->_comp = tmp-> _comp; + x->_alloc = tmp->_alloc; + x->_node_alloc = tmp->_node_alloc; + x->_root = tmp->_root; + //x->_end = tmp->_end; + x->_size = tmp->_size; + } + + void clear() + { + + } + + //------------------------- + //--------Observers-------- + //------------------------- + + key_compare key_comp() const + { + return (_comp); + } + + value_compare value_comp() const + { + return (value_compare(_comp)); + } + + + //------------------------- + //-------Operations-------- + //------------------------- + + iterator find (const key_type& k) + { + node *x = _root; + int i = 0; + while (x != _end && x->data.first != k) + { + std::cout << "i === " << i << std::endl; + if (k > x->data.first) + x = x->left; + else + x = x->right; + i++; + } + return (iterator(_root, _end, x)); + } + + const_iterator find (const key_type& k) const + { + node *x = _root; + + while (x != _end && x->data.first != k) + { + if (k > x->data.first) + x = x->left; + else + x = x->right; + } + return (iterator(_root, _end, x)); + } + + size_type count (const key_type& k) const + { + if (find(k)->m == _end) + return (0); + return (1); + } + + iterator lower_bound (const key_type& k) + { + iterator it = begin(), ite = end(); + + while (it != ite && !(_comp((*it).first, k))) + it++; + return (it); + } + + const_iterator lower_bound (const key_type& k) const + { + const_iterator it = begin(), ite = end(); + + while (it != ite && !(_comp((*it).first, k))) + it++; + return (it); + } + + iterator upper_bound (const key_type& k) + { + iterator it = begin(), ite = end(); + + while (it != ite && !(_comp((*it).first, k))) + it++; + return (it); + } + + const_iterator upper_bound (const key_type& k) const + { + const_iterator it = begin(), ite = end(); + + while (it != ite && _comp((*it).first, k)) + it++; + return (it); + } + + ft::pair equal_range (const key_type& k) const + { + return (ft::make_pair(lower_bound(k), upper_bound(k))); + } + + ft::pair equal_range (const key_type& k) + { + return (ft::make_pair(lower_bound(k), upper_bound(k))); + } + + /* ************************************************************************** */ + /* ************************************************************************** */ + /* ************************************************************************** */ + /* ******************************TREE FUNCTIONS****************************** */ + /* ************************************************************************** */ + /* ************************************************************************** */ + /* ************************************************************************** */ + + private : + + void rotateLeft(node *&root, node *&pt) + { + node *pt_right = pt->right; + pt->right = pt_right->left; + if (pt->right != NULL) + pt->right->parent = pt; + pt_right->parent = pt->parent; + if (pt->parent == NULL) + root = pt_right; + else if (pt == pt->parent->left) + pt->parent->left = pt_right; + else + pt->parent->right = pt_right; + pt_right->left = pt; + pt->parent = pt_right; + } + + + void rotateRight(node *&root, node *&pt) + { + + node *pt_left = pt->left; + pt->left = pt_left->right; + if (pt->left != NULL) + pt->left->parent = pt; + pt_left->parent = pt->parent; + if (pt->parent == NULL) + root = pt_left; + else if (pt == pt->parent->left) + pt->parent->left = pt_left; + else + pt->parent->right = pt_left; + pt_left->right = pt; + pt->parent = pt_left; + } + + node* insert_node(node* root, node *pt) + { + /* If the tree is empty, return a new node */ + if (root == NULL) + return pt; + /* Otherwise, recur down the tree */ + if (pt->data < root->data) + { + root->left = insert_node(root->left, pt); + root->left->parent = root; + } + else if (pt->data > root->data) + { + root->right = insert_node(root->right, pt); + root->right->parent = root; + } + /* return the (unchanged) node pointer */ + return root; + } + + void fixViolation(node *&root, node *&pt) + { + node *parent_pt = NULL; + node *grand_parent_pt = NULL; + while ((pt != root) && (pt->color != BLACK) && (pt->parent->color == RED)) + { + parent_pt = pt->parent; + grand_parent_pt = pt->parent->parent; + /* Case : A Parent of pt is left child of Grand-parent of pt */ + if (parent_pt == grand_parent_pt->left) + { + node *uncle_pt = grand_parent_pt->right; + /* Case : 1 The uncle of pt is also red Only Recoloring required */ + if (uncle_pt != NULL && uncle_pt->color == RED) + { + grand_parent_pt->color = RED; + parent_pt->color = BLACK; + uncle_pt->color = BLACK; + pt = grand_parent_pt; + } + else + { + /* Case : 2 pt is right child of its parent Left-rotation required */ + if (pt == parent_pt->right) + { + rotateLeft(root, parent_pt); + pt = parent_pt; + parent_pt = pt->parent; + } + /* Case : 3 pt is left child of its parent Right-rotation required */ + rotateRight(root, grand_parent_pt); + swapColors(parent_pt, grand_parent_pt); + pt = parent_pt; + } + } + /* Case : B Parent of pt is right child of Grand-parent of pt */ + else + { + node *uncle_pt = grand_parent_pt->left; + /* Case : 1 The uncle of pt is also red Only Recoloring required */ + if ((uncle_pt != NULL) && (uncle_pt->color == RED)) + { + grand_parent_pt->color = RED; + parent_pt->color = BLACK; + uncle_pt->color = BLACK; + pt = grand_parent_pt; + } + else + { + /* Case : 2 | pt is left child of its parent | Right-rotation required */ + if (pt == parent_pt->left) + { + rotateRight(root, parent_pt); + pt = parent_pt; + parent_pt = pt->parent; + } + /* Case : 3 pt is right child of its parent Left-rotation required */ + rotateLeft(root, grand_parent_pt); + swapColors(parent_pt, grand_parent_pt); + pt = parent_pt; + } + } + } + root->color = BLACK; + } + + /* ************************************************************************** */ + /* **********************************DELETE********************************** */ + /* ************************************************************************** */ + + + node *uncle(node *x) + { + if (x->parent == NULL or x->parent->parent == NULL) + return NULL; + if (x->parent->isOnLeft()) + return x->parent->parent->right; + else + return x->parent->parent->left; + } + + bool isOnLeft(node *x) { return this == x->parent->left; } + + // returns pointer to sibling + node *sibling(node *x) + { + // sibling null if no parent + if (x->parent == NULL) + return NULL; + if (isOnLeft()) + return x->parent->right; + return x->parent->left; + } + + // moves node down and moves given node in its place + void moveDown(node *nParent, node *x) + { + if (x->parent != NULL) + { + if (isOnLeft()) + x->parent->left = nParent; + else + x->parent->right = nParent; + } + nParent->parent = x->parent; + x->parent = nParent; + } + + bool hasRedChild(node *x) + { + return (x->left != NULL and x->left->color == RED) or (x->right != NULL and x->right->color == RED); + } + + void swapColors(node *x1, node *x2) + { + bool temp; + temp = x1->color; + x1->color = x2->color; + x2->color = temp; + } + + void swapValues(node *u, node *v) + { + int temp; + temp = u->val; + u->val = v->val; + v->val = temp; + } + + void fixRedRed(node *x) + { + // if x is root color it black and return + if (x == _root) + { + x->color = BLACK; + return; + } + // initialize parent, grandparent, uncle + node *parent = x->parent, *grandparent = parent->parent, + *uncle = x->uncle(); + if (parent->color != BLACK) + { + if (uncle != NULL && uncle->color == RED) + { + // uncle red, perform recoloring and recurse + parent->color = BLACK; + uncle->color = BLACK; + grandparent->color = RED; + fixRedRed(grandparent); + } + else + { + // Else perform LR, LL, RL, RR + if (parent->isOnLeft()) + { + if (x->isOnLeft()) + { + // for left right + swapColors(parent, grandparent); + } + else + { + leftRotate(parent); + swapColors(x, grandparent); + } + // for left left and left right + rightRotate(grandparent); + } + else + { + if (x->isOnLeft()) + { + // for right left + rightRotate(parent); + swapColors(x, grandparent); + } + else + swapColors(parent, grandparent); + // for right right and right left + leftRotate(grandparent); + } + } + } + } + + // find node that do not have a left child + // in the subtree of the given node + node *successor(node *x) + { + node *temp = x; + + while (temp->left != NULL) + temp = temp->left; + return temp; + } + + // find node that replaces a deleted node in BST + node *replace_node(node *x) + { + // when node have 2 children + if (x->left != NULL and x->right != NULL) + return successor(x->right); + // when leaf + if (x->left == NULL and x->right == NULL) + return NULL; + // when single child + if (x->left != NULL) + return x->left; + else + return x->right; + } + + // deletes the given node + void deleteNode(node *v) + { + node *u = replace_node(v); + + // True when u and v are both black + bool uvBlack = ((u == NULL or u->color == BLACK) and (v->color == BLACK)); + node *parent = v->parent; + if (u == NULL) + { + // u is NULL therefore v is leaf + if (v == _root) + _root = NULL;// v is root, making root null + else + { + if (uvBlack) + { + // u and v both black + // v is leaf, fix double black at v + fixDoubleBlack(v); + } + else + { + // u or v is red + if (v->sibling() != NULL) + // sibling is not null, make it red" + v->sibling()->color = RED; + } + // delete v from the tree + if (v->isOnLeft()) + parent->left = NULL; + else + parent->right = NULL; + } + delete v; + return; + } + if (v->left == NULL or v->right == NULL) + { + // v has 1 child + if (v == _root) + { + // v is root, assign the value of u to v, and delete u + v->val = u->val; + v->left = v->right = NULL; + delete u; + } + else + { + // Detach v from tree and move u up + if (v->isOnLeft()) + parent->left = u; + else + parent->right = u; + delete v; + u->parent = parent; + if (uvBlack) + fixDoubleBlack(u);// u and v both black, fix double black at u + else + u->color = BLACK;// u or v red, color u black + } + return; + } + // v has 2 children, swap values with successor and recurse + swapValues(u, v); + deleteNode(u); + } + + //template + node *new_node(key_type key, mapped_type val) + { + node *ret; + + ret = _node_alloc.allocate(1); + _node_alloc.construct(ret, node(key, val)); + + //ret = _node_alloc::allocate(1); + //_node_alloc::construct(ret, node(key, val)); + return (ret); + } + +}; //end of set class + +//---------------------------------- +//----------COMPARE CLASS----------- +//---------------------------------- + +template +class set::value_compare //man set::value_compare +{ // in C++98, it is required to inherit binary_function + friend class set; + protected: + Compare comp; + value_compare(Compare c) : comp(c) {} // constructed with set's comparison object + public: + typedef bool result_type; + typedef value_type first_argument_type; + typedef value_type second_argument_type; + bool operator() (const value_type& x, const value_type& y) const + { + return comp(x.first, y.first); + } +}; + +} \ No newline at end of file