Added Key_trait to C++ avl tree

This commit is contained in:
madmaurice 2018-07-19 16:12:03 +02:00
parent afec9113f7
commit 381bcd1de9

159
bintree.h
View file

@ -12,17 +12,9 @@ typedef int Mword;
template <typename Key> template <typename Key>
class Bin_tree; class Bin_tree;
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>; template <typename E> friend class Bin_tree;
void recalc() void recalc()
{ {
@ -35,7 +27,7 @@ private:
height = (leftHeight < rightHeight ? rightHeight : leftHeight); height = (leftHeight < rightHeight ? rightHeight : leftHeight);
} }
void replaceChild(Self* child, Self* replace) void replaceChild(Bin_tree_node* child, Bin_tree_node* replace)
{ {
assert(child == left || child == right); assert(child == left || child == right);
@ -52,38 +44,61 @@ private:
recalc(); recalc();
} }
public: protected:
constexpr Bin_tree_node(Key key) constexpr Bin_tree_node()
: key(key), parent(nullptr), left(nullptr), : parent(nullptr), left(nullptr),
right(nullptr), tree(nullptr), right(nullptr), tree(nullptr),
balance(0), height(0) balance(0), height(0)
{} {}
constexpr Bin_tree_node() private:
: Bin_tree_node(0) Bin_tree_node* parent;
{} Bin_tree_node* left;
Bin_tree_node* right;
Self* parent; void* tree;
Self* left;
Self* right;
Tree* tree;
// AVL Tree // AVL Tree
Mword balance; Mword balance;
Umword height; Umword height;
public:
Key key;
}; };
template <typename Key = Umword> template<typename Key>
class Bin_tree_node_t : public Bin_tree_node {
public:
class Key_trait {
public:
typedef Key Key_type;
static inline
Key_type get_key(Bin_tree_node* node)
{ return static_cast<Bin_tree_node_t<Key>* >(node)->key(); }
static inline
bool compare(Key_type a, Key_type b)
{ return (a < b); }
};
Bin_tree_node_t(Key k) : Bin_tree_node(), _key(k)
{}
inline
Key& key()
{ return _key; }
private:
Key _key;
};
template <typename Key_trait>
class Bin_tree { class Bin_tree {
protected: protected:
typedef Bin_tree_node<Key> Node; typedef Bin_tree_node Node;
typedef typename Key_trait::Key_type Key_type;
private: private:
Node* root; Node* root;
Node* findByKey(Key key) const Node* findByKey(Key_type key) const
{ {
Node* iterparent = nullptr; Node* iterparent = nullptr;
Node* iter = root; Node* iter = root;
@ -92,13 +107,12 @@ private:
{ {
iterparent = iter; iterparent = iter;
if(key < iter->key) { if(Key_trait::compare(key, Key_trait::get_key(iter)))
iter = iter->left; iter = iter->left;
} else if(key > iter->key) { else if(Key_trait::compare(Key_trait::get_key(iter), key))
iter = iter->right; iter = iter->right;
} else { else
break; break;
}
} }
return iterparent; return iterparent;
@ -116,25 +130,6 @@ private:
return iter; return iter;
} }
// void replaceInParent(Node* node, Node* replace) {
// assert(node->parent);
// assert(node->parent->left == node
// || node->parent->right == node);
// assert(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) void leafRemove(Node* leaf)
{ {
assert(leaf); assert(leaf);
@ -164,43 +159,6 @@ private:
child->parent = nullptr; 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;
@ -270,7 +228,6 @@ private:
else else
node->parent->replaceChild(node, partner); node->parent->replaceChild(node, partner);
// partner->parent = node->parent;
node->parent = partner; node->parent = partner;
partner->left = node; partner->left = node;
@ -318,7 +275,6 @@ private:
else else
node->parent->replaceChild(node,partner); node->parent->replaceChild(node,partner);
// partner->parent = node->parent;
node->parent = partner; node->parent = partner;
partner->right = node; partner->right = node;
@ -359,7 +315,7 @@ private:
dump(node->left, indent+1); dump(node->left, indent+1);
for(int i = 0; i < indent; i++) for(int i = 0; i < indent; i++)
cout << " "; cout << " ";
cout << node->key << endl; cout << Key_trait::get_key(node) << endl;
assert(node->right == nullptr assert(node->right == nullptr
|| node->right->parent == node); || node->right->parent == node);
@ -383,12 +339,14 @@ public:
else else
{ {
// else, find a suitable parent // else, find a suitable parent
parent = findByKey(node->key); parent = findByKey(Key_trait::get_key(node));
assert(parent); assert(parent);
if(node->key < parent->key) if(Key_trait::compare(Key_trait::get_key(node),
Key_trait::get_key(parent)))
parent->left = node; parent->left = node;
else if(node->key > parent->key) else if(Key_trait::compare(Key_trait::get_key(parent),
Key_trait::get_key(node)))
parent->right = node; parent->right = node;
else // Node with same key exists else // Node with same key exists
return false; return false;
@ -451,7 +409,7 @@ public:
node->recalc(); node->recalc();
} }
Node* lookup(Key key) const Node* lookup(Key_type key) const
{ {
if(root == nullptr) if(root == nullptr)
return nullptr; return nullptr;
@ -461,7 +419,8 @@ public:
if(node == nullptr) if(node == nullptr)
__builtin_unreachable(); __builtin_unreachable();
if(node->key != key) if(Key_trait::compare(Key_trait::get_key(node),key)
|| Key_trait::compare(key, Key_trait::get_key(node)))
return nullptr; return nullptr;
return node; return node;
@ -477,10 +436,12 @@ public:
#endif #endif
}; };
template<typename T, typename Key = typename T::Key> template<typename T, typename Key_trait = typename T::Key_trait>
class Bin_tree_t : Bin_tree<Key> { class Bin_tree_t : Bin_tree<Key_trait> {
private: private:
typedef Bin_tree<Key> Base; typedef Bin_tree<Key_trait> Base;
typedef typename Key_trait::Key_type Key_type;
public: public:
inline inline
bool insert(T* node) bool insert(T* node)
@ -491,7 +452,7 @@ public:
{ Base::remove(static_cast<typename Base::Node*>(node)); } { Base::remove(static_cast<typename Base::Node*>(node)); }
inline inline
T* lookup(Key key) T* find(Key_type key)
{ return static_cast<T*>(Base::lookup(key)); } { return static_cast<T*>(Base::lookup(key)); }
#ifdef DUMP #ifdef DUMP