|
@@ -1,746 +0,0 @@
|
|
|
-#pragma once
|
|
|
-#include <utility>
|
|
|
-#include <type_traits>
|
|
|
-
|
|
|
-#include <types/allocator.hpp>
|
|
|
-#include <types/types.h>
|
|
|
-
|
|
|
-namespace types {
|
|
|
-
|
|
|
-template <typename Key, typename Value, template <typename _T> class _Allocator = kernel_allocator>
|
|
|
-class map {
|
|
|
-public:
|
|
|
- using key_type = std::add_const_t<Key>;
|
|
|
- using value_type = Value;
|
|
|
- using pair_type = std::pair<key_type, value_type>;
|
|
|
-
|
|
|
- struct node {
|
|
|
- node* parent = nullptr;
|
|
|
-
|
|
|
- node* left = nullptr;
|
|
|
- node* right = nullptr;
|
|
|
-
|
|
|
- enum class node_color {
|
|
|
- RED,
|
|
|
- BLACK,
|
|
|
- } color
|
|
|
- = node_color::RED;
|
|
|
-
|
|
|
- pair_type v;
|
|
|
-
|
|
|
- constexpr node(pair_type&& pair)
|
|
|
- : v(std::move(pair))
|
|
|
- {
|
|
|
- }
|
|
|
- constexpr node(const pair_type& pair)
|
|
|
- : v(pair)
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- constexpr node* grandparent(void) const
|
|
|
- {
|
|
|
- return this->parent->parent;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr node* uncle(void) const
|
|
|
- {
|
|
|
- node* pp = this->grandparent();
|
|
|
- return (this->parent == pp->left) ? pp->right : pp->left;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr node* leftmost(void)
|
|
|
- {
|
|
|
- node* nd = this;
|
|
|
- while (nd->left)
|
|
|
- nd = nd->left;
|
|
|
- return nd;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr const node* leftmost(void) const
|
|
|
- {
|
|
|
- const node* nd = this;
|
|
|
- while (nd->left)
|
|
|
- nd = nd->left;
|
|
|
- return nd;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr node* rightmost(void)
|
|
|
- {
|
|
|
- node* nd = this;
|
|
|
- while (nd->right)
|
|
|
- nd = nd->right;
|
|
|
- return nd;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr const node* rightmost(void) const
|
|
|
- {
|
|
|
- const node* nd = this;
|
|
|
- while (nd->right)
|
|
|
- nd = nd->right;
|
|
|
- return nd;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr node* next(void)
|
|
|
- {
|
|
|
- if (this->right) {
|
|
|
- return this->right->leftmost();
|
|
|
- } else {
|
|
|
- if (this->is_root()) {
|
|
|
- return nullptr;
|
|
|
- } else if (this->is_left_child()) {
|
|
|
- return this->parent;
|
|
|
- } else {
|
|
|
- node* ret = this;
|
|
|
- do {
|
|
|
- ret = ret->parent;
|
|
|
- } while (!ret->is_root() && !ret->is_left_child());
|
|
|
- return ret->parent;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- constexpr const node* next(void) const
|
|
|
- {
|
|
|
- if (this->right) {
|
|
|
- return this->right->leftmost();
|
|
|
- } else {
|
|
|
- if (this->is_root()) {
|
|
|
- return nullptr;
|
|
|
- } else if (this->is_left_child()) {
|
|
|
- return this->parent;
|
|
|
- } else {
|
|
|
- const node* ret = this;
|
|
|
- do {
|
|
|
- ret = ret->parent;
|
|
|
- } while (!ret->is_root() && !ret->is_left_child());
|
|
|
- return ret->parent;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- constexpr node* prev(void)
|
|
|
- {
|
|
|
- if (this->left) {
|
|
|
- return this->left->rightmost();
|
|
|
- } else {
|
|
|
- if (this->is_root()) {
|
|
|
- return nullptr;
|
|
|
- } else if (this->is_right_child()) {
|
|
|
- return this->parent;
|
|
|
- } else {
|
|
|
- node* ret = this;
|
|
|
- do {
|
|
|
- ret = ret->parent;
|
|
|
- } while (!ret->is_root() && !ret->is_right_child());
|
|
|
- return ret->parent;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- static constexpr bool is_red(node* nd)
|
|
|
- {
|
|
|
- return nd && nd->color == node_color::RED;
|
|
|
- }
|
|
|
- static constexpr bool is_black(node* nd)
|
|
|
- {
|
|
|
- return !node::is_red(nd);
|
|
|
- }
|
|
|
-
|
|
|
- constexpr const node* prev(void) const
|
|
|
- {
|
|
|
- if (this->left) {
|
|
|
- return this->left->rightmost();
|
|
|
- } else {
|
|
|
- if (this->is_root()) {
|
|
|
- return nullptr;
|
|
|
- } else if (this->is_right_child()) {
|
|
|
- return this->parent;
|
|
|
- } else {
|
|
|
- const node* ret = this;
|
|
|
- do {
|
|
|
- ret = ret->parent;
|
|
|
- } while (!ret->is_root() && !ret->is_right_child());
|
|
|
- return ret->parent;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- constexpr bool is_root(void) const
|
|
|
- {
|
|
|
- return this->parent == nullptr;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr bool is_full(void) const
|
|
|
- {
|
|
|
- return this->left && this->right;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr bool has_child(void) const
|
|
|
- {
|
|
|
- return this->left || this->right;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr bool is_leaf(void) const
|
|
|
- {
|
|
|
- return !this->has_child();
|
|
|
- }
|
|
|
-
|
|
|
- constexpr bool is_left_child(void) const
|
|
|
- {
|
|
|
- return this == this->parent->left;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr bool is_right_child(void) const
|
|
|
- {
|
|
|
- return this == this->parent->right;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr void tored(void)
|
|
|
- {
|
|
|
- this->color = node_color::RED;
|
|
|
- }
|
|
|
- constexpr void toblack(void)
|
|
|
- {
|
|
|
- this->color = node_color::BLACK;
|
|
|
- }
|
|
|
-
|
|
|
- static constexpr void swap(node* first, node* second)
|
|
|
- {
|
|
|
- if (node::is_red(first)) {
|
|
|
- first->color = second->color;
|
|
|
- second->color = node_color::RED;
|
|
|
- } else {
|
|
|
- first->color = second->color;
|
|
|
- second->color = node_color::BLACK;
|
|
|
- }
|
|
|
-
|
|
|
- if (first->parent == second) {
|
|
|
- node* tmp = first;
|
|
|
- first = second;
|
|
|
- second = tmp;
|
|
|
- }
|
|
|
-
|
|
|
- bool f_is_left_child = first->parent ? first->is_left_child() : false;
|
|
|
- bool s_is_left_child = second->parent ? second->is_left_child() : false;
|
|
|
-
|
|
|
- node* fp = first->parent;
|
|
|
- node* fl = first->left;
|
|
|
- node* fr = first->right;
|
|
|
-
|
|
|
- node* sp = second->parent;
|
|
|
- node* sl = second->left;
|
|
|
- node* sr = second->right;
|
|
|
-
|
|
|
- if (second->parent != first) {
|
|
|
- first->parent = sp;
|
|
|
- if (sp) {
|
|
|
- if (s_is_left_child)
|
|
|
- sp->left = first;
|
|
|
- else
|
|
|
- sp->right = first;
|
|
|
- }
|
|
|
- first->left = sl;
|
|
|
- if (sl)
|
|
|
- sl->parent = first;
|
|
|
- first->right = sr;
|
|
|
- if (sr)
|
|
|
- sr->parent = first;
|
|
|
-
|
|
|
- second->parent = fp;
|
|
|
- if (fp) {
|
|
|
- if (f_is_left_child)
|
|
|
- fp->left = second;
|
|
|
- else
|
|
|
- fp->right = second;
|
|
|
- }
|
|
|
-
|
|
|
- second->left = fl;
|
|
|
- if (fl)
|
|
|
- fl->parent = second;
|
|
|
- second->right = fr;
|
|
|
- if (fr)
|
|
|
- fr->parent = second;
|
|
|
- } else {
|
|
|
- first->left = sl;
|
|
|
- if (sl)
|
|
|
- sl->parent = first;
|
|
|
- first->right = sr;
|
|
|
- if (sr)
|
|
|
- sr->parent = first;
|
|
|
-
|
|
|
- second->parent = fp;
|
|
|
- if (fp) {
|
|
|
- if (f_is_left_child)
|
|
|
- fp->left = second;
|
|
|
- else
|
|
|
- fp->right = second;
|
|
|
- }
|
|
|
- first->parent = second;
|
|
|
-
|
|
|
- if (s_is_left_child) {
|
|
|
- second->left = first;
|
|
|
- second->right = fr;
|
|
|
- if (fr)
|
|
|
- fr->parent = second;
|
|
|
- } else {
|
|
|
- second->right = first;
|
|
|
- second->left = fl;
|
|
|
- if (fl)
|
|
|
- fl->parent = second;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- using allocator_type = _Allocator<node>;
|
|
|
-
|
|
|
- template <bool Const>
|
|
|
- class iterator {
|
|
|
- public:
|
|
|
- using node_pointer_type = std::conditional_t<Const, const node*, node*>;
|
|
|
- using value_type = std::conditional_t<Const, const pair_type, pair_type>;
|
|
|
- using pointer_type = std::add_pointer_t<value_type>;
|
|
|
- using reference_type = std::add_lvalue_reference_t<value_type>;
|
|
|
-
|
|
|
- friend class map;
|
|
|
-
|
|
|
- private:
|
|
|
- node_pointer_type p;
|
|
|
-
|
|
|
- public:
|
|
|
- explicit constexpr iterator(node_pointer_type ptr)
|
|
|
- : p { ptr }
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- constexpr iterator(const iterator& iter)
|
|
|
- : p { iter.p }
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- constexpr iterator(iterator&& iter)
|
|
|
- : p { iter.p }
|
|
|
- {
|
|
|
- iter.p = nullptr;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr ~iterator()
|
|
|
- {
|
|
|
-#ifndef NDEBUG
|
|
|
- p = nullptr;
|
|
|
-#endif
|
|
|
- }
|
|
|
-
|
|
|
- constexpr iterator& operator=(const iterator& iter)
|
|
|
- {
|
|
|
- p = iter.p;
|
|
|
- return *this;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr iterator& operator=(iterator&& iter)
|
|
|
- {
|
|
|
- p = iter.p;
|
|
|
- iter.p = nullptr;
|
|
|
- return *this;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr bool operator==(const iterator& iter) const
|
|
|
- {
|
|
|
- return p == iter.p;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr bool operator!=(const iterator& iter) const
|
|
|
- {
|
|
|
- return !this->operator==(iter);
|
|
|
- }
|
|
|
-
|
|
|
- constexpr reference_type operator*(void) const
|
|
|
- {
|
|
|
- return p->v;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr pointer_type operator&(void) const
|
|
|
- {
|
|
|
- return &p->v;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr pointer_type operator->(void) const
|
|
|
- {
|
|
|
- return this->operator&();
|
|
|
- }
|
|
|
-
|
|
|
- constexpr iterator& operator++(void)
|
|
|
- {
|
|
|
- p = p->next();
|
|
|
- return *this;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr iterator operator++(int)
|
|
|
- {
|
|
|
- iterator ret(p);
|
|
|
-
|
|
|
- (void)this->operator++();
|
|
|
-
|
|
|
- return ret;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr iterator& operator--(void)
|
|
|
- {
|
|
|
- p = p->prev();
|
|
|
- return *this;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr iterator operator--(int)
|
|
|
- {
|
|
|
- iterator ret(p);
|
|
|
-
|
|
|
- (void)this->operator--();
|
|
|
-
|
|
|
- return ret;
|
|
|
- }
|
|
|
-
|
|
|
- explicit constexpr operator bool(void)
|
|
|
- {
|
|
|
- return p;
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- using iterator_type = iterator<false>;
|
|
|
- using const_iterator_type = iterator<true>;
|
|
|
-
|
|
|
-private:
|
|
|
- node* root = nullptr;
|
|
|
-
|
|
|
-private:
|
|
|
- static constexpr node* newnode(node* parent, const pair_type& val)
|
|
|
- {
|
|
|
- auto* ptr = allocator_traits<allocator_type>::allocate_and_construct(val);
|
|
|
- ptr->parent = parent;
|
|
|
- return ptr;
|
|
|
- }
|
|
|
- static constexpr node* newnode(node* parent, pair_type&& val)
|
|
|
- {
|
|
|
- auto* ptr = allocator_traits<allocator_type>::allocate_and_construct(std::move(val));
|
|
|
- ptr->parent = parent;
|
|
|
- return ptr;
|
|
|
- }
|
|
|
- static constexpr void delnode(node* nd)
|
|
|
- {
|
|
|
- allocator_traits<allocator_type>::deconstruct_and_deallocate(nd);
|
|
|
- }
|
|
|
-
|
|
|
- constexpr void rotateleft(node* rt)
|
|
|
- {
|
|
|
- node* nrt = rt->right;
|
|
|
-
|
|
|
- if (!rt->is_root()) {
|
|
|
- if (rt->is_left_child()) {
|
|
|
- rt->parent->left = nrt;
|
|
|
- } else {
|
|
|
- rt->parent->right = nrt;
|
|
|
- }
|
|
|
- } else {
|
|
|
- this->root = nrt;
|
|
|
- }
|
|
|
-
|
|
|
- nrt->parent = rt->parent;
|
|
|
- rt->parent = nrt;
|
|
|
-
|
|
|
- rt->right = nrt->left;
|
|
|
- nrt->left = rt;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr void rotateright(node* rt)
|
|
|
- {
|
|
|
- node* nrt = rt->left;
|
|
|
-
|
|
|
- if (!rt->is_root()) {
|
|
|
- if (rt->is_left_child()) {
|
|
|
- rt->parent->left = nrt;
|
|
|
- } else {
|
|
|
- rt->parent->right = nrt;
|
|
|
- }
|
|
|
- } else {
|
|
|
- this->root = nrt;
|
|
|
- }
|
|
|
-
|
|
|
- nrt->parent = rt->parent;
|
|
|
- rt->parent = nrt;
|
|
|
-
|
|
|
- rt->left = nrt->right;
|
|
|
- nrt->right = rt;
|
|
|
- }
|
|
|
-
|
|
|
- constexpr void balance(node* nd)
|
|
|
- {
|
|
|
- if (nd->is_root()) {
|
|
|
- nd->toblack();
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (node::is_black(nd->parent))
|
|
|
- return;
|
|
|
-
|
|
|
- node* p = nd->parent;
|
|
|
- node* pp = nd->grandparent();
|
|
|
- node* uncle = nd->uncle();
|
|
|
-
|
|
|
- if (node::is_red(uncle)) {
|
|
|
- p->toblack();
|
|
|
- uncle->toblack();
|
|
|
- pp->tored();
|
|
|
- this->balance(pp);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (p->is_left_child()) {
|
|
|
- if (nd->is_left_child()) {
|
|
|
- p->toblack();
|
|
|
- pp->tored();
|
|
|
- this->rotateright(pp);
|
|
|
- } else {
|
|
|
- this->rotateleft(p);
|
|
|
- this->balance(p);
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (nd->is_right_child()) {
|
|
|
- p->toblack();
|
|
|
- pp->tored();
|
|
|
- this->rotateleft(pp);
|
|
|
- } else {
|
|
|
- this->rotateright(p);
|
|
|
- this->balance(p);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- constexpr node* _find(const key_type& key) const
|
|
|
- {
|
|
|
- for (node* cur = root; cur;) {
|
|
|
- if (cur->v.first == key)
|
|
|
- return cur;
|
|
|
-
|
|
|
- if (key < cur->v.first)
|
|
|
- cur = cur->left;
|
|
|
- else
|
|
|
- cur = cur->right;
|
|
|
- }
|
|
|
-
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
-
|
|
|
- // this function DOES NOT dellocate the node
|
|
|
- // caller is responsible for freeing the memory
|
|
|
- // @param: nd is guaranteed to be a leaf node
|
|
|
- constexpr void _erase(node* nd)
|
|
|
- {
|
|
|
- if (nd->is_root())
|
|
|
- return;
|
|
|
-
|
|
|
- if (node::is_black(nd)) {
|
|
|
- node* p = nd->parent;
|
|
|
- node* s = nullptr;
|
|
|
- if (nd->is_left_child())
|
|
|
- s = p->right;
|
|
|
- else
|
|
|
- s = p->left;
|
|
|
-
|
|
|
- if (node::is_red(s)) {
|
|
|
- p->tored();
|
|
|
- s->toblack();
|
|
|
- if (nd->is_right_child()) {
|
|
|
- this->rotateright(p);
|
|
|
- s = p->left;
|
|
|
- } else {
|
|
|
- this->rotateleft(p);
|
|
|
- s = p->right;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- node* r = nullptr;
|
|
|
- if (node::is_red(s->left)) {
|
|
|
- r = s->left;
|
|
|
- if (s->is_left_child()) {
|
|
|
- r->toblack();
|
|
|
- s->color = p->color;
|
|
|
- this->rotateright(p);
|
|
|
- p->toblack();
|
|
|
- } else {
|
|
|
- r->color = p->color;
|
|
|
- this->rotateright(s);
|
|
|
- this->rotateleft(p);
|
|
|
- p->toblack();
|
|
|
- }
|
|
|
- } else if (node::is_red(s->right)) {
|
|
|
- r = s->right;
|
|
|
- if (s->is_left_child()) {
|
|
|
- r->color = p->color;
|
|
|
- this->rotateleft(s);
|
|
|
- this->rotateright(p);
|
|
|
- p->toblack();
|
|
|
- } else {
|
|
|
- r->toblack();
|
|
|
- s->color = p->color;
|
|
|
- this->rotateleft(p);
|
|
|
- p->toblack();
|
|
|
- }
|
|
|
- } else {
|
|
|
- s->tored();
|
|
|
- if (node::is_black(p))
|
|
|
- this->_erase(p);
|
|
|
- else
|
|
|
- p->toblack();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-public:
|
|
|
- constexpr iterator_type end(void)
|
|
|
- {
|
|
|
- return iterator_type(nullptr);
|
|
|
- }
|
|
|
- constexpr const_iterator_type end(void) const
|
|
|
- {
|
|
|
- return const_iterator_type(nullptr);
|
|
|
- }
|
|
|
- constexpr const_iterator_type cend(void) const
|
|
|
- {
|
|
|
- return const_iterator_type(nullptr);
|
|
|
- }
|
|
|
-
|
|
|
- constexpr iterator_type begin(void)
|
|
|
- {
|
|
|
- return root ? iterator_type(root->leftmost()) : end();
|
|
|
- }
|
|
|
- constexpr const_iterator_type begin(void) const
|
|
|
- {
|
|
|
- return root ? const_iterator_type(root->leftmost()) : end();
|
|
|
- }
|
|
|
- constexpr const_iterator_type cbegin(void) const
|
|
|
- {
|
|
|
- return root ? const_iterator_type(root->leftmost()) : end();
|
|
|
- }
|
|
|
-
|
|
|
- constexpr iterator_type find(const key_type& key)
|
|
|
- {
|
|
|
- return iterator_type(_find(key));
|
|
|
- }
|
|
|
- constexpr const_iterator_type find(const key_type& key) const
|
|
|
- {
|
|
|
- return const_iterator_type(_find(key));
|
|
|
- }
|
|
|
-
|
|
|
- constexpr iterator_type insert(pair_type val)
|
|
|
- {
|
|
|
- node* cur = root;
|
|
|
-
|
|
|
- while (likely(cur)) {
|
|
|
- if (val.first < cur->v.first) {
|
|
|
- if (!cur->left) {
|
|
|
- node* nd = newnode(cur, std::move(val));
|
|
|
- cur->left = nd;
|
|
|
- this->balance(nd);
|
|
|
- return iterator_type(nd);
|
|
|
- } else {
|
|
|
- cur = cur->left;
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (!cur->right) {
|
|
|
- node* nd = newnode(cur, std::move(val));
|
|
|
- cur->right = nd;
|
|
|
- this->balance(nd);
|
|
|
- return iterator_type(nd);
|
|
|
- } else {
|
|
|
- cur = cur->right;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- root = newnode(nullptr, std::move(val));
|
|
|
- root->toblack();
|
|
|
- return iterator_type(root);
|
|
|
- }
|
|
|
-
|
|
|
- constexpr iterator_type erase(const iterator_type& iter)
|
|
|
- {
|
|
|
- node* nd = iter.p;
|
|
|
- if (!nd)
|
|
|
- return end();
|
|
|
-
|
|
|
- if (nd->is_root() && nd->is_leaf()) {
|
|
|
- delnode(nd);
|
|
|
- root = nullptr;
|
|
|
- return end();
|
|
|
- }
|
|
|
-
|
|
|
- node* next = nd->next();
|
|
|
-
|
|
|
- while (!nd->is_leaf()) {
|
|
|
- node* alt = nd->right ? nd->right->leftmost() : nd->left;
|
|
|
- if (nd->is_root()) {
|
|
|
- this->root = alt;
|
|
|
- }
|
|
|
- node::swap(nd, alt);
|
|
|
- }
|
|
|
-
|
|
|
- this->_erase(nd);
|
|
|
-
|
|
|
- if (nd->is_left_child())
|
|
|
- nd->parent->left = nullptr;
|
|
|
- else
|
|
|
- nd->parent->right = nullptr;
|
|
|
-
|
|
|
- delnode(nd);
|
|
|
-
|
|
|
- return iterator_type(next);
|
|
|
- }
|
|
|
-
|
|
|
- constexpr void remove(const key_type& key)
|
|
|
- {
|
|
|
- auto iter = this->find(key);
|
|
|
- if (iter != this->end())
|
|
|
- this->erase(iter);
|
|
|
- }
|
|
|
-
|
|
|
- // destroy a subtree without adjusting nodes to maintain binary tree properties
|
|
|
- constexpr void destroy(node* nd)
|
|
|
- {
|
|
|
- if (nd) {
|
|
|
- this->destroy(nd->left);
|
|
|
- this->destroy(nd->right);
|
|
|
- delnode(nd);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- explicit constexpr map(void)
|
|
|
- {
|
|
|
- }
|
|
|
- constexpr map(const map& val)
|
|
|
- {
|
|
|
- for (const auto& item : val)
|
|
|
- this->insert(item);
|
|
|
- }
|
|
|
- constexpr map(map&& val)
|
|
|
- : root(val.root)
|
|
|
- {
|
|
|
- val.root = nullptr;
|
|
|
- }
|
|
|
- constexpr map& operator=(const map& val)
|
|
|
- {
|
|
|
- this->destroy(root);
|
|
|
- for (const auto& item : val)
|
|
|
- this->insert(item);
|
|
|
- }
|
|
|
- constexpr map& operator=(map&& val)
|
|
|
- {
|
|
|
- this->destroy(root);
|
|
|
- root = val.root;
|
|
|
- val.root = nullptr;
|
|
|
- }
|
|
|
- constexpr ~map()
|
|
|
- {
|
|
|
- this->destroy(root);
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-} // namespace types
|