Improve code of c++ avl tree
This commit is contained in:
parent
283d926b27
commit
afec9113f7
1 changed files with 143 additions and 96 deletions
239
bintree.h
239
bintree.h
|
@ -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,70 +116,90 @@ 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
root = leaf->left;
|
||||
leaf->left->parent = nullptr;
|
||||
}
|
||||
leaf->parent->replaceChild(leaf, child);
|
||||
rebalance(leaf->parent, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
|
@ -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;
|
||||
{
|
||||
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;
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
// Tree is empty, add node as root
|
||||
root = node;
|
||||
else
|
||||
{
|
||||
return false;
|
||||
// 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;
|
||||
|
|
Loading…
Reference in a new issue