123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699 |
- #pragma once
- #include <types/allocator.hpp>
- #include <types/cplusplus.hpp>
- #include <types/pair.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 = typename traits::add_const<Key>::type;
- using value_type = Value;
- using pair_type = 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(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)
- {
- node* p = first->parent;
- node* cl = first->left;
- node* cr = first->right;
- 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->is_root()) {
- if (first->is_left_child())
- p->left = second;
- else
- p->right = second;
- }
- if (cl)
- cl->parent = second;
- if (cr)
- cr->parent = second;
- first->parent = second->parent;
- first->left = second->left;
- first->right = second->right;
- if (!second->is_root()) {
- if (second->is_left_child())
- second->parent->left = first;
- else
- second->parent->right = first;
- }
- if (second->left)
- second->left->parent = first;
- if (second->right)
- second->right->parent = first;
- second->parent = p;
- second->left = cl;
- second->right = cr;
- }
- };
- using allocator_type = _Allocator<node>;
- template <bool Const>
- class iterator {
- private:
- static constexpr bool _is_const_iterator = Const;
- public:
- using node_pointer_type = typename traits::condition<_is_const_iterator, const node*, node*>::type;
- using value_type = typename traits::condition<_is_const_iterator, const pair_type, pair_type>::type;
- using pointer_type = typename traits::add_pointer<value_type>::type;
- using reference_type = typename traits::add_reference<value_type>::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;
- }
- constexpr iterator& operator=(iterator&& iter)
- {
- p = iter.p;
- iter.p = nullptr;
- }
- 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;
- }
- 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(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
- {
- node* cur = root;
- for (; cur;) {
- if (cur->v.key == key)
- return cur;
- if (key < cur->v.key)
- 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 (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();
- this->_erase(p);
- }
- }
- }
- 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.key < cur->v.key) {
- if (!cur->left) {
- node* nd = newnode(cur, move(val));
- cur->left = nd;
- this->balance(nd);
- return iterator_type(nd);
- } else {
- cur = cur->left;
- }
- } else {
- if (!cur->right) {
- node* nd = newnode(cur, move(val));
- cur->right = nd;
- this->balance(nd);
- return iterator_type(nd);
- } else {
- cur = cur->right;
- }
- }
- }
- root = newnode(nullptr, 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()) {
- if (nd->is_root())
- this->root = nd->right->leftmost();
- node::swap(nd, nd->right->leftmost());
- }
- 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
|