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