Loading docs/ds/llrbt.md +109 −119 Original line number Diff line number Diff line Loading @@ -203,10 +203,7 @@ template <class Key, class Compare = std::less<Key>> class Set { private: enum NodeColor { kBlack = 0, kRed = 1 }; enum NodeColor { kBlack = 0, kRed = 1 }; struct Node { Key key; Loading @@ -214,7 +211,8 @@ size_t size{0}; NodeColor color; // the color of the parent link Node(Key key, NodeColor color, size_t size) : key(key), color(color), size(size) {} Node(Key key, NodeColor color, size_t size) : key(key), color(color), size(size) {} Node() = default; }; Loading @@ -232,9 +230,7 @@ return nd == nullptr ? false : nd->color; // kRed == 1, kBlack == 0 } size_t size(const Node *nd) const { return nd == nullptr ? 0 : nd->size; } size_t size(const Node *nd) const { return nd == nullptr ? 0 : nd->size; } Node *rotate_left(Node *node) const { // left rotate a red link Loading Loading @@ -291,7 +287,6 @@ Node *root_{nullptr}; public: typedef Key KeyType; typedef Key ValueType; typedef std::size_t SizeType; Loading @@ -307,9 +302,7 @@ Set(Set &&) noexcept = default; ~Set() { destroyTree(root_); } ~Set() { destroyTree(root_); } SizeType size() const; Loading @@ -329,12 +322,11 @@ }; template <class Key, class Compare> typename Set<Key, Compare>::SizeType Set<Key, Compare>::count(ConstReference key) const { typename Set<Key, Compare>::SizeType Set<Key, Compare>::count( ConstReference key) const { Node *x = root_; while (x != nullptr) { if (key == x->key) return 1; if (key == x->key) return 1; if (cmp_(key, x->key)) // if (key < x->key) x = x->lc; else Loading @@ -344,14 +336,12 @@ } template <class Key, class Compare> typename Set<Key, Compare>::SizeType Set<Key, Compare>::erase(const KeyType &key) { typename Set<Key, Compare>::SizeType Set<Key, Compare>::erase( const KeyType &key) { if (count(key) > 0) { if (!is_red(root_->lc) && !(is_red(root_->rc))) root_->color = kRed; if (!is_red(root_->lc) && !(is_red(root_->rc))) root_->color = kRed; root_ = delete_arbitrary(root_, key); if (root_ != nullptr) root_->color = kBlack; if (root_ != nullptr) root_->color = kBlack; return 1; } else { return 0; Loading @@ -376,11 +366,11 @@ } template <class Key, class Compare> typename Set<Key, Compare>::Node * Set<Key, Compare>::insert(Set::Node *root, const Key &key) const { if (root == nullptr) return new Node(key, kRed, 1); if (root->key == key); typename Set<Key, Compare>::Node *Set<Key, Compare>::insert( Set::Node *root, const Key &key) const { if (root == nullptr) return new Node(key, kRed, 1); if (root->key == key) ; else if (cmp_(key, root->key)) // if (key < root->key) root->lc = insert(root->lc, key); else Loading @@ -389,8 +379,8 @@ } template <class Key, class Compare> typename Set<Key, Compare>::Node * Set<Key, Compare>::delete_min(Set::Node *root) const { typename Set<Key, Compare>::Node *Set<Key, Compare>::delete_min( Set::Node *root) const { if (root->lc == nullptr) { delete root; return nullptr; Loading @@ -405,10 +395,11 @@ } template <class Key, class Compare> typename Set<Key, Compare>::Node * Set<Key, Compare>::move_red_right(Set::Node *root) const { typename Set<Key, Compare>::Node *Set<Key, Compare>::move_red_right( Set::Node *root) const { color_flip(root); if (is_red(root->lc->lc)) { // assume that root->lc != nullptr when calling this function if (is_red(root->lc->lc)) { // assume that root->lc != nullptr when calling // this function root = rotate_right(root); color_flip(root); } Loading @@ -416,8 +407,8 @@ } template <class Key, class Compare> typename Set<Key, Compare>::Node * Set<Key, Compare>::move_red_left(Set::Node *root) const { typename Set<Key, Compare>::Node *Set<Key, Compare>::move_red_left( Set::Node *root) const { color_flip(root); if (is_red(root->rc->lc)) { // assume that root->rc != nullptr when calling this function Loading @@ -429,11 +420,12 @@ } template <class Key, class Compare> typename Set<Key, Compare>::Node * Set<Key, Compare>::fix_up(Set::Node *root) const { typename Set<Key, Compare>::Node *Set<Key, Compare>::fix_up( Set::Node *root) const { if (is_red(root->rc) && !is_red(root->lc)) // fix right leaned red link root = rotate_left(root); if (is_red(root->lc) && is_red(root->lc->lc)) // fix doubly linked left leaned red link if (is_red(root->lc) && is_red(root->lc->lc)) // fix doubly linked left leaned red link // if (root->lc == nullptr), then the second expr won't be evaluated root = rotate_right(root); if (is_red(root->lc) && is_red(root->rc)) Loading @@ -447,36 +439,36 @@ const Key &Set<Key, Compare>::get_min(Set::Node *root) const { Node *x = root; // will crash as intended when root == nullptr for (; x->lc != nullptr; x = x->lc); for (; x->lc != nullptr; x = x->lc) ; return x->key; } template <class Key, class Compare> typename Set<Key, Compare>::SizeType Set<Key, Compare>::size() const { typename Set<Key, Compare>::SizeType Set<Key, Compare>::size() const { return size(root_); } template <class Key, class Compare> typename Set<Key, Compare>::Node * Set<Key, Compare>::delete_arbitrary(Set::Node *root, Key key) const { typename Set<Key, Compare>::Node *Set<Key, Compare>::delete_arbitrary( Set::Node *root, Key key) const { if (cmp_(key, root->key)) { // key < root->key if (!is_red(root->lc) && !(is_red(root->lc->lc))) root = move_red_left(root); // ensure the invariant: either root->lc or root->lc->lc (or root and root->lc after dive into the function) is red, // to ensure we will eventually delete a red node. therefore we will not break the black height balance // ensure the invariant: either root->lc or root->lc->lc (or root and // root->lc after dive into the function) is red, to ensure we will // eventually delete a red node. therefore we will not break the black // height balance root->lc = delete_arbitrary(root->lc, key); } else { // key >= root->key if (is_red(root->lc)) root = rotate_right(root); if (is_red(root->lc)) root = rotate_right(root); if (key == root->key && root->rc == nullptr) { delete root; return nullptr; } if (!is_red(root->rc) && !is_red(root->rc->lc)) root = move_red_right(root); if (!is_red(root->rc) && !is_red(root->rc->lc)) root = move_red_right(root); if (key == root->key) { root->key = get_min(root->rc); root->rc = delete_min(root->rc); Loading @@ -485,7 +477,6 @@ } } return fix_up(root); } template <class Key, class Compare> Loading @@ -496,9 +487,9 @@ } template <class Key, class Compare> void Set<Key, Compare>::serialize(Set::Node *root, std::vector<Key> *res) const { if (root == nullptr) return; void Set<Key, Compare>::serialize(Set::Node *root, std::vector<Key> *res) const { if (root == nullptr) return; serialize(root->lc, res); res->push_back(root->key); serialize(root->rc, res); Loading @@ -506,8 +497,7 @@ template <class Key, class Compare> void Set<Key, Compare>::print_tree(Set::Node *root, int indent) const { if (root == nullptr) return; if (root == nullptr) return; print_tree(root->lc, indent + 4); std::cout << std::string(indent, '-') << root->key << std::endl; print_tree(root->rc, indent + 4); Loading Loading
docs/ds/llrbt.md +109 −119 Original line number Diff line number Diff line Loading @@ -203,10 +203,7 @@ template <class Key, class Compare = std::less<Key>> class Set { private: enum NodeColor { kBlack = 0, kRed = 1 }; enum NodeColor { kBlack = 0, kRed = 1 }; struct Node { Key key; Loading @@ -214,7 +211,8 @@ size_t size{0}; NodeColor color; // the color of the parent link Node(Key key, NodeColor color, size_t size) : key(key), color(color), size(size) {} Node(Key key, NodeColor color, size_t size) : key(key), color(color), size(size) {} Node() = default; }; Loading @@ -232,9 +230,7 @@ return nd == nullptr ? false : nd->color; // kRed == 1, kBlack == 0 } size_t size(const Node *nd) const { return nd == nullptr ? 0 : nd->size; } size_t size(const Node *nd) const { return nd == nullptr ? 0 : nd->size; } Node *rotate_left(Node *node) const { // left rotate a red link Loading Loading @@ -291,7 +287,6 @@ Node *root_{nullptr}; public: typedef Key KeyType; typedef Key ValueType; typedef std::size_t SizeType; Loading @@ -307,9 +302,7 @@ Set(Set &&) noexcept = default; ~Set() { destroyTree(root_); } ~Set() { destroyTree(root_); } SizeType size() const; Loading @@ -329,12 +322,11 @@ }; template <class Key, class Compare> typename Set<Key, Compare>::SizeType Set<Key, Compare>::count(ConstReference key) const { typename Set<Key, Compare>::SizeType Set<Key, Compare>::count( ConstReference key) const { Node *x = root_; while (x != nullptr) { if (key == x->key) return 1; if (key == x->key) return 1; if (cmp_(key, x->key)) // if (key < x->key) x = x->lc; else Loading @@ -344,14 +336,12 @@ } template <class Key, class Compare> typename Set<Key, Compare>::SizeType Set<Key, Compare>::erase(const KeyType &key) { typename Set<Key, Compare>::SizeType Set<Key, Compare>::erase( const KeyType &key) { if (count(key) > 0) { if (!is_red(root_->lc) && !(is_red(root_->rc))) root_->color = kRed; if (!is_red(root_->lc) && !(is_red(root_->rc))) root_->color = kRed; root_ = delete_arbitrary(root_, key); if (root_ != nullptr) root_->color = kBlack; if (root_ != nullptr) root_->color = kBlack; return 1; } else { return 0; Loading @@ -376,11 +366,11 @@ } template <class Key, class Compare> typename Set<Key, Compare>::Node * Set<Key, Compare>::insert(Set::Node *root, const Key &key) const { if (root == nullptr) return new Node(key, kRed, 1); if (root->key == key); typename Set<Key, Compare>::Node *Set<Key, Compare>::insert( Set::Node *root, const Key &key) const { if (root == nullptr) return new Node(key, kRed, 1); if (root->key == key) ; else if (cmp_(key, root->key)) // if (key < root->key) root->lc = insert(root->lc, key); else Loading @@ -389,8 +379,8 @@ } template <class Key, class Compare> typename Set<Key, Compare>::Node * Set<Key, Compare>::delete_min(Set::Node *root) const { typename Set<Key, Compare>::Node *Set<Key, Compare>::delete_min( Set::Node *root) const { if (root->lc == nullptr) { delete root; return nullptr; Loading @@ -405,10 +395,11 @@ } template <class Key, class Compare> typename Set<Key, Compare>::Node * Set<Key, Compare>::move_red_right(Set::Node *root) const { typename Set<Key, Compare>::Node *Set<Key, Compare>::move_red_right( Set::Node *root) const { color_flip(root); if (is_red(root->lc->lc)) { // assume that root->lc != nullptr when calling this function if (is_red(root->lc->lc)) { // assume that root->lc != nullptr when calling // this function root = rotate_right(root); color_flip(root); } Loading @@ -416,8 +407,8 @@ } template <class Key, class Compare> typename Set<Key, Compare>::Node * Set<Key, Compare>::move_red_left(Set::Node *root) const { typename Set<Key, Compare>::Node *Set<Key, Compare>::move_red_left( Set::Node *root) const { color_flip(root); if (is_red(root->rc->lc)) { // assume that root->rc != nullptr when calling this function Loading @@ -429,11 +420,12 @@ } template <class Key, class Compare> typename Set<Key, Compare>::Node * Set<Key, Compare>::fix_up(Set::Node *root) const { typename Set<Key, Compare>::Node *Set<Key, Compare>::fix_up( Set::Node *root) const { if (is_red(root->rc) && !is_red(root->lc)) // fix right leaned red link root = rotate_left(root); if (is_red(root->lc) && is_red(root->lc->lc)) // fix doubly linked left leaned red link if (is_red(root->lc) && is_red(root->lc->lc)) // fix doubly linked left leaned red link // if (root->lc == nullptr), then the second expr won't be evaluated root = rotate_right(root); if (is_red(root->lc) && is_red(root->rc)) Loading @@ -447,36 +439,36 @@ const Key &Set<Key, Compare>::get_min(Set::Node *root) const { Node *x = root; // will crash as intended when root == nullptr for (; x->lc != nullptr; x = x->lc); for (; x->lc != nullptr; x = x->lc) ; return x->key; } template <class Key, class Compare> typename Set<Key, Compare>::SizeType Set<Key, Compare>::size() const { typename Set<Key, Compare>::SizeType Set<Key, Compare>::size() const { return size(root_); } template <class Key, class Compare> typename Set<Key, Compare>::Node * Set<Key, Compare>::delete_arbitrary(Set::Node *root, Key key) const { typename Set<Key, Compare>::Node *Set<Key, Compare>::delete_arbitrary( Set::Node *root, Key key) const { if (cmp_(key, root->key)) { // key < root->key if (!is_red(root->lc) && !(is_red(root->lc->lc))) root = move_red_left(root); // ensure the invariant: either root->lc or root->lc->lc (or root and root->lc after dive into the function) is red, // to ensure we will eventually delete a red node. therefore we will not break the black height balance // ensure the invariant: either root->lc or root->lc->lc (or root and // root->lc after dive into the function) is red, to ensure we will // eventually delete a red node. therefore we will not break the black // height balance root->lc = delete_arbitrary(root->lc, key); } else { // key >= root->key if (is_red(root->lc)) root = rotate_right(root); if (is_red(root->lc)) root = rotate_right(root); if (key == root->key && root->rc == nullptr) { delete root; return nullptr; } if (!is_red(root->rc) && !is_red(root->rc->lc)) root = move_red_right(root); if (!is_red(root->rc) && !is_red(root->rc->lc)) root = move_red_right(root); if (key == root->key) { root->key = get_min(root->rc); root->rc = delete_min(root->rc); Loading @@ -485,7 +477,6 @@ } } return fix_up(root); } template <class Key, class Compare> Loading @@ -496,9 +487,9 @@ } template <class Key, class Compare> void Set<Key, Compare>::serialize(Set::Node *root, std::vector<Key> *res) const { if (root == nullptr) return; void Set<Key, Compare>::serialize(Set::Node *root, std::vector<Key> *res) const { if (root == nullptr) return; serialize(root->lc, res); res->push_back(root->key); serialize(root->rc, res); Loading @@ -506,8 +497,7 @@ template <class Key, class Compare> void Set<Key, Compare>::print_tree(Set::Node *root, int indent) const { if (root == nullptr) return; if (root == nullptr) return; print_tree(root->lc, indent + 4); std::cout << std::string(indent, '-') << root->key << std::endl; print_tree(root->rc, indent + 4); Loading