Improve code of c++ avl tree

This commit is contained in:
madmaurice 2018-07-19 14:48:32 +02:00
parent 283d926b27
commit afec9113f7

225
bintree.h
View file

@ -14,6 +14,13 @@ class Bin_tree;
template <typename _Key = Umword>
struct Bin_tree_node {
public:
typedef _Key Key;
protected:
typedef Bin_tree_node<Key> Self;
typedef Bin_tree<Key> Tree;
private:
friend class Bin_tree<_Key>;
@ -28,13 +35,24 @@ private:
height = (leftHeight < rightHeight ? rightHeight : leftHeight);
}
void replaceChild(Self* child, Self* replace)
{
assert(child == left || child == right);
if(child == left)
left = replace;
else if(child == right)
right = replace;
if(replace)
replace->parent = this;
child->parent = nullptr;
recalc();
}
public:
typedef _Key Key;
protected:
typedef Bin_tree_node<Key> Self;
typedef Bin_tree<Key> Tree;
constexpr Bin_tree_node(Key key)
: key(key), parent(nullptr), left(nullptr),
right(nullptr), tree(nullptr),
@ -88,7 +106,8 @@ private:
Node* findLeft(Node* start) const
{
assert(start != nullptr);
assert(start);
Node* iter = start;
while(iter->left != nullptr)
{
@ -97,71 +116,91 @@ private:
return iter;
}
void replaceInParent(Node* node, Node* replace) {
assert(node->parent);
assert(node->parent->left == node
|| node->parent->right == node);
// void replaceInParent(Node* node, Node* replace) {
// assert(node->parent);
// assert(node->parent->left == node
// || node->parent->right == node);
assert(node->parent);
// assert(node->parent);
if(node->parent->left == node)
{
node->parent->left = replace;
if(replace) replace->parent = node->parent;
}
else if(node->parent->right == node)
{
node->parent->right = replace;
if(replace) replace->parent = node->parent;
}
}
// if(node->parent->left == node)
// node->parent->left = replace;
// else if(node->parent->right == node)
// node->parent->right = replace;
// if(replace)
// {
// replace->parent = node->parent;
// replace->recalc();
// }
// }
void leafRemove(Node* leaf)
{
assert(leaf);
assert(leaf->left == nullptr
|| leaf->right == nullptr);
Node* child;
if(leaf->left == nullptr && leaf->right == nullptr)
{
if(leaf->parent != nullptr)
{
assert(leaf->parent->left == leaf
|| leaf->parent->right == leaf);
replaceInParent(leaf, nullptr);
rebalance(leaf->parent, 1, 2);
}
else
root = nullptr;
}
child = nullptr;
else if(leaf->left == nullptr)
{
if(leaf->parent != nullptr)
{
assert(leaf->parent->left == leaf
|| leaf->parent->right == leaf);
replaceInParent(leaf, leaf->right);
rebalance(leaf->parent, 1, 2);
}
else
{
root = leaf->right;
leaf->right->parent = nullptr;
}
}
child = leaf->right;
else if(leaf->right == nullptr)
child = leaf->left;
else
assert(false);
if(leaf->parent)
{
if(leaf->parent != nullptr)
{
replaceInParent(leaf, leaf->left);
rebalance(leaf->parent, 1, 2);
leaf->parent->replaceChild(leaf, child);
rebalance(leaf->parent, 1);
}
else
{
root = leaf->left;
leaf->left->parent = nullptr;
}
root = child;
if(child)
child->parent = nullptr;
}
// if(leaf->left == nullptr && leaf->right == nullptr)
// {
// if(leaf->parent != nullptr)
// {
// replaceInParent(leaf, nullptr);
// rebalance(leaf->parent, 1, 2);
// }
// else
// root = nullptr;
// }
// else if(leaf->left == nullptr)
// {
// if(leaf->parent != nullptr)
// {
// replaceInParent(leaf, leaf->right);
// rebalance(leaf->parent, 1, 2);
// }
// else
// {
// root = leaf->right;
// leaf->right->parent = nullptr;
// }
// }
// else if(leaf->right == nullptr)
// {
// if(leaf->parent != nullptr)
// {
// replaceInParent(leaf, leaf->left);
// rebalance(leaf->parent, 1, 2);
// }
// else
// {
// root = leaf->left;
// leaf->left->parent = nullptr;
// }
// }
leaf->parent = nullptr;
leaf->left = nullptr;
leaf->right = nullptr;
@ -171,7 +210,7 @@ private:
}
void
rebalance(Node* start, Mword abortCond, Mword rebalanceCond)
rebalance(Node* start, Mword abortCond)
{
for(Node* iter = start; iter != nullptr; iter = iter->parent)
{
@ -180,11 +219,7 @@ private:
Mword absBalance =
(iter->balance < 0) ? -(iter->balance) : iter->balance;
if(absBalance == abortCond)
{
break;
}
else if(absBalance == rebalanceCond)
if(absBalance == 2) // needs rotation
{
// Left side is taller
if(iter->balance > 0)
@ -210,6 +245,8 @@ private:
// then abort
break;
}
else if(absBalance == abortCond) // can abort
break;
}
}
@ -226,13 +263,15 @@ private:
// No parent, partner is the new root
if(node->parent == nullptr)
{
root = partner;
partner->parent = nullptr;
}
else
replaceInParent(node, partner);
node->parent->replaceChild(node, partner);
partner->parent = node->parent;
// partner->parent = node->parent;
node->parent = partner;
partner->left = node;
assert(node->parent == nullptr
@ -272,11 +311,14 @@ private:
// No parent, partner is the new root
if(node->parent == nullptr)
{
root = partner;
partner->parent = nullptr;
}
else
replaceInParent(node,partner);
node->parent->replaceChild(node,partner);
partner->parent = node->parent;
// partner->parent = node->parent;
node->parent = partner;
partner->right = node;
@ -333,31 +375,26 @@ public:
{
assert(node->tree == nullptr);
Node* parent = nullptr;
if(root == nullptr)
{
// Tree is empty, add node as root
root = node;
root->parent = nullptr;
root->left = nullptr;
root->right = nullptr;
root->tree = this;
return true;
}
Node* parent = findByKey(node->key);
if(node->key < parent->key)
{
parent->left = node;
}
else if(node->key > parent->key)
{
parent->right = node;
}
else
{
// else, find a suitable parent
parent = findByKey(node->key);
assert(parent);
if(node->key < parent->key)
parent->left = node;
else if(node->key > parent->key)
parent->right = node;
else // Node with same key exists
return false;
}
// setup node
node->parent = parent;
node->left = nullptr;
node->right = nullptr;
@ -365,7 +402,9 @@ public:
node->height = 0;
node->balance = 0;
rebalance(parent,0,2);
// rebalance tree
if(parent)
rebalance(parent,0);
return true;
}
@ -385,13 +424,13 @@ public:
leafRemove(replacement);
if(node == root)
if(node->parent == nullptr)
{
root = replacement;
replacement->parent = nullptr;
}
else
replaceInParent(node, replacement);
node->parent->replaceChild(node, replacement);
replacement->left = node->left;
replacement->right = node->right;
@ -409,12 +448,20 @@ public:
node->right = nullptr;
node->parent = nullptr;
node->tree = nullptr;
node->recalc();
}
Node* lookup(Key key) const {
Node* lookup(Key key) const
{
if(root == nullptr)
return nullptr;
Node* node = findByKey(key);
if(node == nullptr || node->key != key)
if(node == nullptr)
__builtin_unreachable();
if(node->key != key)
return nullptr;
return node;