| @@ -29,11 +29,11 @@ public: | |||
| { | |||
| if (!m_root) | |||
| { | |||
| this->m_root = new tree_node(key, value); | |||
| this->m_root = new tree_node(key, value, &this->m_root); | |||
| return true; | |||
| } | |||
| return this->m_root->insert(key, value, this->m_root); | |||
| return this->m_root->insert(key, value); | |||
| } | |||
| bool erase(K const & key) | |||
| @@ -41,7 +41,7 @@ public: | |||
| if (!m_root) | |||
| return false; | |||
| return this->m_root->erase(key, this->m_root); | |||
| return this->m_root->erase(key); | |||
| } | |||
| bool exists(K const & key) | |||
| @@ -74,9 +74,10 @@ protected: | |||
| class tree_node | |||
| { | |||
| public: | |||
| tree_node(K key, V value) : | |||
| tree_node(K key, V value, tree_node ** parent_slot) : | |||
| m_key(key), | |||
| m_value(value) | |||
| m_value(value), | |||
| m_parent_slot(parent_slot) | |||
| { | |||
| m_child[0] = m_child[1] = nullptr; | |||
| m_stairs[0] = m_stairs[1] = 0; | |||
| @@ -84,7 +85,7 @@ protected: | |||
| /* Insert a value in tree and return true or update an existing value for | |||
| * the existing key and return false */ | |||
| bool insert(K const & key, V const & value, tree_node * & parent_slot) | |||
| bool insert(K const & key, V const & value) | |||
| { | |||
| int i = -1 + (key < this->m_key) + 2 * (this->m_key < key); | |||
| @@ -97,33 +98,33 @@ protected: | |||
| bool created = false; | |||
| if (this->m_child[i]) | |||
| created = this->m_child[i]->insert(key, value, this->m_child[i]); | |||
| created = this->m_child[i]->insert(key, value); | |||
| else | |||
| { | |||
| this->m_child[i] = new tree_node(key, value); | |||
| this->m_child[i] = new tree_node(key, value, &this->m_child[i]); | |||
| created = true; | |||
| } | |||
| if (created) | |||
| this->rebalance_if_needed(parent_slot); | |||
| this->rebalance_if_needed(); | |||
| return created; | |||
| } | |||
| /* Erase a value in tree and return true or return false */ | |||
| bool erase(K const & key, tree_node * & parent_slot) | |||
| bool erase(K const & key) | |||
| { | |||
| int i = -1 + (key < this->m_key) + 2 * (this->m_key < key); | |||
| if (i < 0) | |||
| { | |||
| this->erase_self(parent_slot); | |||
| this->erase_self(); | |||
| delete this; | |||
| return true; | |||
| } | |||
| else if(this->m_child[i]->erase(key, this->m_child[i])) | |||
| else if(this->m_child[i]->erase(key)) | |||
| { | |||
| this->rebalance_if_needed(parent_slot); | |||
| this->rebalance_if_needed(); | |||
| return true; | |||
| } | |||
| @@ -146,31 +147,13 @@ protected: | |||
| return false; | |||
| } | |||
| tree_node * detach_deepest(int i, tree_node * & parent_slot) | |||
| { | |||
| tree_node * ret = nullptr; | |||
| if (this->m_child[i]) | |||
| ret = this->m_child[i]->detach_deepest(i, this->m_child[i]); | |||
| else | |||
| { | |||
| parent_slot = this->m_child[(i ? 0 : 1)]; | |||
| this->m_child[(i ? 0 : 1)] = nullptr; | |||
| ret = this; | |||
| } | |||
| this->rebalance_if_needed(parent_slot); | |||
| return ret; | |||
| } | |||
| void update_balance() | |||
| { | |||
| this->m_stairs[0] = this->m_child[0] ? lol::max(this->m_child[0]->m_stairs[0], this->m_child[0]->m_stairs[1]) + 1 : 0; | |||
| this->m_stairs[1] = this->m_child[1] ? lol::max(this->m_child[1]->m_stairs[0], this->m_child[1]->m_stairs[1]) + 1 : 0; | |||
| } | |||
| void rebalance_if_needed(tree_node * & parent_slot) | |||
| void rebalance_if_needed() | |||
| { | |||
| this->update_balance(); | |||
| @@ -179,16 +162,27 @@ protected: | |||
| if (i || j) | |||
| { | |||
| tree_node * swap = this->m_child[i]; | |||
| this->m_child[i] = swap->m_child[j]; | |||
| swap->m_child[j] = this; | |||
| parent_slot = swap; | |||
| tree_node * save = this->m_child[i]; | |||
| tree_node ** save_parent = this->m_parent_slot; | |||
| this->set_child(i, save->m_child[j]); | |||
| save->set_child(j, this); | |||
| save->m_parent_slot = save_parent; | |||
| *save_parent = save; | |||
| this->update_balance(); | |||
| swap->update_balance(); | |||
| save->update_balance(); | |||
| } | |||
| } | |||
| void set_child(int i, tree_node * node) | |||
| { | |||
| this->m_child[i] = node; | |||
| if (node) | |||
| node->m_parent_slot = &this->m_child[i]; | |||
| } | |||
| bool exists(K const & key) | |||
| { | |||
| int i = -1 + (key < this->m_key) + 2 * (this->m_key < key); | |||
| @@ -229,22 +223,35 @@ protected: | |||
| protected: | |||
| void erase_self(tree_node * & parent_slot) | |||
| void erase_self() | |||
| { | |||
| int i = (this->get_balance() == -1); | |||
| tree_node * replacement = nullptr; | |||
| if (i || this->m_child[1]) | |||
| replacement = this->m_child[1 - i]->detach_deepest(i, this->m_child[1 - i]); | |||
| tree_node * replacement = this->m_child[1 - i]; | |||
| if (replacement) | |||
| { | |||
| while (replacement->m_child[i]) | |||
| replacement = replacement->m_child[i]; | |||
| } | |||
| if (replacement) | |||
| { | |||
| *replacement->m_parent_slot = replacement->m_child[1 - i]; | |||
| if (*replacement->m_parent_slot) | |||
| (*replacement->m_parent_slot)->rebalance_if_needed(); | |||
| replacement->m_parent_slot = this->m_parent_slot; | |||
| *replacement->m_parent_slot = replacement; | |||
| replacement->m_child[0] = this->m_child[0]; | |||
| replacement->m_child[1] = this->m_child[1]; | |||
| } | |||
| else | |||
| *this->m_parent_slot = nullptr; | |||
| parent_slot = replacement; | |||
| this->m_parent_slot = nullptr; | |||
| this->m_child[0] = nullptr; | |||
| this->m_child[1] = nullptr; | |||
| } | |||
| K m_key; | |||
| @@ -252,6 +259,8 @@ protected: | |||
| tree_node *m_child[2]; | |||
| int m_stairs[2]; | |||
| tree_node ** m_parent_slot; | |||
| }; | |||
| tree_node * m_root; | |||