From afec9113f70640dcc9121dbaf91952ac41f11868 Mon Sep 17 00:00:00 2001 From: Valentin Gehrke Date: Thu, 19 Jul 2018 14:48:32 +0200 Subject: [PATCH] Improve code of c++ avl tree --- bintree.h | 239 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 143 insertions(+), 96 deletions(-) diff --git a/bintree.h b/bintree.h index 521e594..1e6ba7d 100644 --- a/bintree.h +++ b/bintree.h @@ -14,6 +14,13 @@ class Bin_tree; template struct Bin_tree_node { +public: + typedef _Key Key; + +protected: + typedef Bin_tree_node Self; + typedef Bin_tree 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 Self; - typedef Bin_tree 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;