|
@@ -25,6 +25,15 @@ public: |
|
|
{ |
|
|
{ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
~avl_tree() |
|
|
|
|
|
{ |
|
|
|
|
|
if (this->m_root) |
|
|
|
|
|
{ |
|
|
|
|
|
this->m_root->cascade_delete(); |
|
|
|
|
|
delete this->m_root; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
bool insert(K const & key, V const & value) |
|
|
bool insert(K const & key, V const & value) |
|
|
{ |
|
|
{ |
|
|
if (!m_root) |
|
|
if (!m_root) |
|
@@ -52,7 +61,7 @@ public: |
|
|
return this->m_root->exists(key); |
|
|
return this->m_root->exists(key); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool try_get_value(K const & key, V * & value_ptr) |
|
|
|
|
|
|
|
|
bool try_get_value(K const & key, V * & value_ptr) const |
|
|
{ |
|
|
{ |
|
|
if (this->m_root) |
|
|
if (this->m_root) |
|
|
return this->m_root->try_get_value(key, value_ptr); |
|
|
return this->m_root->try_get_value(key, value_ptr); |
|
@@ -60,13 +69,35 @@ public: |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
virtual ~avl_tree() |
|
|
|
|
|
|
|
|
bool try_get_min(K const * & key_ptr, V * & value_ptr) const |
|
|
{ |
|
|
{ |
|
|
|
|
|
tree_node * min_node = nullptr; |
|
|
|
|
|
|
|
|
if (this->m_root) |
|
|
if (this->m_root) |
|
|
{ |
|
|
{ |
|
|
this->m_root->cascade_delete(); |
|
|
|
|
|
delete this->m_root; |
|
|
|
|
|
|
|
|
this->m_root->get_min(min_node); |
|
|
|
|
|
key_ptr = &min_node->m_key; |
|
|
|
|
|
value_ptr = &min_node->m_value; |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool try_get_max(K const * & key, V * & value_ptr) const |
|
|
|
|
|
{ |
|
|
|
|
|
tree_node * max_node = nullptr; |
|
|
|
|
|
|
|
|
|
|
|
if (this->m_root) |
|
|
|
|
|
{ |
|
|
|
|
|
this->m_root->get_max(max_node); |
|
|
|
|
|
value_ptr = &max_node->value; |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
protected: |
|
|
protected: |
|
@@ -84,6 +115,16 @@ protected: |
|
|
m_chain[0] = m_chain[1] = nullptr; |
|
|
m_chain[0] = m_chain[1] = nullptr; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
K const & get_key() |
|
|
|
|
|
{ |
|
|
|
|
|
return this->m_key; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
V & get_value() |
|
|
|
|
|
{ |
|
|
|
|
|
return this->m_value; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/* Insert a value in tree and return true or update an existing value for |
|
|
/* Insert a value in tree and return true or update an existing value for |
|
|
* the existing key and return false */ |
|
|
* the existing key and return false */ |
|
|
bool insert(K const & key, V const & value) |
|
|
bool insert(K const & key, V const & value) |
|
@@ -169,6 +210,22 @@ protected: |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void get_min(tree_node * & min_node) const |
|
|
|
|
|
{ |
|
|
|
|
|
min_node = this; |
|
|
|
|
|
|
|
|
|
|
|
while (this->m_child[0]) |
|
|
|
|
|
min_node = this->m_child[0]; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void get_max(tree_node * & max_node) const |
|
|
|
|
|
{ |
|
|
|
|
|
max_node = this; |
|
|
|
|
|
|
|
|
|
|
|
while (this->m_child[1]) |
|
|
|
|
|
max_node = this->m_child[1]; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void cascade_delete() |
|
|
void cascade_delete() |
|
|
{ |
|
|
{ |
|
|
if (this->m_child[0]) |
|
|
if (this->m_child[0]) |
|
@@ -184,14 +241,19 @@ protected: |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int get_balance() |
|
|
|
|
|
|
|
|
int get_balance() const |
|
|
{ |
|
|
{ |
|
|
return this->m_stairs[1] - this->m_stairs[0]; |
|
|
return this->m_stairs[1] - this->m_stairs[0]; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
K get_key() |
|
|
|
|
|
|
|
|
tree_node * get_previous() const |
|
|
{ |
|
|
{ |
|
|
return this->m_key; |
|
|
|
|
|
|
|
|
return this->m_chain[0]; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
tree_node * get_next() const |
|
|
|
|
|
{ |
|
|
|
|
|
return this->m_chain[1]; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
protected: |
|
|
protected: |
|
@@ -292,6 +354,160 @@ protected: |
|
|
tree_node * m_chain[2]; // Linked list used to keep order between nodes |
|
|
tree_node * m_chain[2]; // Linked list used to keep order between nodes |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
|
|
|
|
/* Iterators related */ |
|
|
|
|
|
|
|
|
|
|
|
struct OutputValue |
|
|
|
|
|
{ |
|
|
|
|
|
OutputValue(K const & key, V & value) : |
|
|
|
|
|
m_key(key), |
|
|
|
|
|
m_value(value) |
|
|
|
|
|
{ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
K const & m_key; |
|
|
|
|
|
V & m_value; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class Iterator |
|
|
|
|
|
{ |
|
|
|
|
|
public: |
|
|
|
|
|
|
|
|
|
|
|
Iterator(tree_node * node) : |
|
|
|
|
|
m_node(node) |
|
|
|
|
|
{ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Iterator & operator++(int) |
|
|
|
|
|
{ |
|
|
|
|
|
ASSERT(this->m_node); |
|
|
|
|
|
|
|
|
|
|
|
this->m_node = this->m_node->get_next(); |
|
|
|
|
|
|
|
|
|
|
|
return *this; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Iterator & operator--(int) |
|
|
|
|
|
{ |
|
|
|
|
|
ASSERT(this->m_node); |
|
|
|
|
|
|
|
|
|
|
|
this->m_node = this->m_node->get_previous(); |
|
|
|
|
|
|
|
|
|
|
|
return *this; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Iterator operator++() |
|
|
|
|
|
{ |
|
|
|
|
|
ASSERT(this->m_node); |
|
|
|
|
|
|
|
|
|
|
|
tree_node * ret = this->m_node; |
|
|
|
|
|
this->m_node = this->m_node->get_next(); |
|
|
|
|
|
|
|
|
|
|
|
return Iterator(ret); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Iterator operator--() |
|
|
|
|
|
{ |
|
|
|
|
|
ASSERT(this->m_node); |
|
|
|
|
|
|
|
|
|
|
|
tree_node * ret = this->m_node; |
|
|
|
|
|
this->m_node = this->m_node->get_previous(); |
|
|
|
|
|
|
|
|
|
|
|
return Iterator(ret); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
OutputValue operator*() |
|
|
|
|
|
{ |
|
|
|
|
|
return OutputValue(this->m_node->get_key(), this->m_node->get_value()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool operator==(Iterator const & that) const |
|
|
|
|
|
{ |
|
|
|
|
|
return this->m_node = that->m_node; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
|
|
|
|
|
|
tree_node * m_node; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
struct ConstOutputValue |
|
|
|
|
|
{ |
|
|
|
|
|
ConstOutputValue(K const & key, V const & value) : |
|
|
|
|
|
m_key(key), |
|
|
|
|
|
m_value(value) |
|
|
|
|
|
{ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
K const & m_key; |
|
|
|
|
|
V const & m_value; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class ConstIterator |
|
|
|
|
|
{ |
|
|
|
|
|
public: |
|
|
|
|
|
|
|
|
|
|
|
ConstIterator(tree_node * node) : |
|
|
|
|
|
m_node(node) |
|
|
|
|
|
{ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ConstIterator & operator++(int) |
|
|
|
|
|
{ |
|
|
|
|
|
ASSERT(this->m_node); |
|
|
|
|
|
|
|
|
|
|
|
this->m_node = this->m_node->get_next(); |
|
|
|
|
|
|
|
|
|
|
|
return *this; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ConstIterator & operator--(int) |
|
|
|
|
|
{ |
|
|
|
|
|
ASSERT(this->m_node); |
|
|
|
|
|
|
|
|
|
|
|
this->m_node = this->m_node->get_previous(); |
|
|
|
|
|
|
|
|
|
|
|
return *this; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ConstIterator operator++() |
|
|
|
|
|
{ |
|
|
|
|
|
ASSERT(this->m_node); |
|
|
|
|
|
|
|
|
|
|
|
tree_node * ret = this->m_node; |
|
|
|
|
|
this->m_node = this->m_node->get_next(); |
|
|
|
|
|
|
|
|
|
|
|
return ConstIterator(ret); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ConstIterator operator--() |
|
|
|
|
|
{ |
|
|
|
|
|
ASSERT(this->m_node); |
|
|
|
|
|
|
|
|
|
|
|
tree_node * ret = this->m_node; |
|
|
|
|
|
this->m_node = this->m_node->get_previous(); |
|
|
|
|
|
|
|
|
|
|
|
return ConstIterator(ret); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ConstOutputValue operator*() |
|
|
|
|
|
{ |
|
|
|
|
|
return ConstOutputValue(this->m_node->get_key(), this->m_node->get_value()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool operator==(ConstIterator const & that) const |
|
|
|
|
|
{ |
|
|
|
|
|
return this->m_node = that->m_node; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
|
|
|
|
|
|
tree_node * m_node; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
|
|
|
tree_node * m_root; |
|
|
tree_node * m_root; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|