remove extra layer of redirection in avl tree
This commit is contained in:
parent
86f81fb534
commit
7c7171f470
2 changed files with 42 additions and 45 deletions
|
|
@ -21,15 +21,19 @@ namespace tp {
|
||||||
|
|
||||||
inline bool exactNode(const IntervalKey& in) const { return in.mStart == mStart && in.mEnd == mEnd; }
|
inline bool exactNode(const IntervalKey& in) const { return in.mStart == mStart && in.mEnd == mEnd; }
|
||||||
|
|
||||||
inline const IntervalKey& getFindKey() const { return *this; }
|
template <typename tTreeNodeType>
|
||||||
|
inline const IntervalKey& getFindKey(const tTreeNodeType* node) const {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
inline const IntervalKey& keyInRightSubtree(const IntervalKey& in) const { return in; }
|
inline const IntervalKey& keyInRightSubtree(const IntervalKey& in) const { return in; }
|
||||||
inline const IntervalKey& keyInLeftSubtree(const IntervalKey& in) const { return in; }
|
inline const IntervalKey& keyInLeftSubtree(const IntervalKey& in) const { return in; }
|
||||||
|
|
||||||
template <typename tTreeNodeType>
|
template <typename tTreeNodeType>
|
||||||
inline void updateTreeCacheCallBack(const tTreeNodeType& node) {
|
inline void updateTreeCacheCallBack(const tTreeNodeType* node) {
|
||||||
mMax = 0;
|
mMax = 0;
|
||||||
if (node.mRight && node.mRight->key.mMax > mMax) mMax = node.mRight->key.mMax;
|
if (node->mRight && node->mRight->key.mMax > mMax) mMax = node->mRight->key.mMax;
|
||||||
if (node.mLeft && node.mLeft->key.mMax > mMax) mMax = node.mLeft->key.mMax;
|
if (node->mLeft && node->mLeft->key.mMax > mMax) mMax = node->mLeft->key.mMax;
|
||||||
if (mMax < mEnd) mMax = mEnd;
|
if (mMax < mEnd) mMax = mEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,16 @@ namespace tp {
|
||||||
inline bool descentRight(AvlNumericKey in) const { return in.val > val; }
|
inline bool descentRight(AvlNumericKey in) const { return in.val > val; }
|
||||||
inline bool exactNode(AvlNumericKey in) const { return in.val == val; }
|
inline bool exactNode(AvlNumericKey in) const { return in.val == val; }
|
||||||
|
|
||||||
inline AvlNumericKey getFindKey(/**/) const { return *this; }
|
template <typename NodeType>
|
||||||
|
inline AvlNumericKey getFindKey(const NodeType*) const {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
inline AvlNumericKey keyInRightSubtree(AvlNumericKey in) const { return in; }
|
inline AvlNumericKey keyInRightSubtree(AvlNumericKey in) const { return in; }
|
||||||
inline AvlNumericKey keyInLeftSubtree(AvlNumericKey in) const { return in; }
|
inline AvlNumericKey keyInLeftSubtree(AvlNumericKey in) const { return in; }
|
||||||
|
|
||||||
template <typename NodeType>
|
template <typename NodeType>
|
||||||
inline void updateTreeCacheCallBack(const NodeType&) {}
|
inline void updateTreeCacheCallBack(const NodeType*) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Key, typename Data, class Allocator = DefaultAllocator>
|
template <typename Key, typename Data, class Allocator = DefaultAllocator>
|
||||||
|
|
@ -42,21 +46,10 @@ namespace tp {
|
||||||
Data data;
|
Data data;
|
||||||
Key key;
|
Key key;
|
||||||
|
|
||||||
public:
|
|
||||||
Node* mLeft = nullptr;
|
Node* mLeft = nullptr;
|
||||||
Node* mRight = nullptr;
|
Node* mRight = nullptr;
|
||||||
Node* mParent = nullptr;
|
Node* mParent = nullptr;
|
||||||
ualni mHeight = 0;
|
ualni mHeight = 0;
|
||||||
|
|
||||||
private:
|
|
||||||
inline bool descentRight(KeyArg aKey) const { return key.descentRight(aKey); }
|
|
||||||
inline bool exactNode(KeyArg aKey) const { return key.exactNode(aKey); }
|
|
||||||
|
|
||||||
inline KeyArg getFindKey(const Node* node = nullptr) const { return key.getFindKey(/*node*/); }
|
|
||||||
inline KeyArg keyInRightSubtree(KeyArg aKey) const { return key.keyInRightSubtree(aKey); }
|
|
||||||
inline KeyArg keyInLeftSubtree(KeyArg aKey) const { return key.keyInLeftSubtree(aKey); }
|
|
||||||
|
|
||||||
inline void updateTreeCacheCallBack() { key.updateTreeCacheCallBack(*this); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -97,12 +90,12 @@ namespace tp {
|
||||||
Node* iter = mRoot;
|
Node* iter = mRoot;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (!iter) return nullptr;
|
if (!iter) return nullptr;
|
||||||
if (iter->exactNode(key)) return iter;
|
if (iter->key.exactNode(key)) return iter;
|
||||||
if (iter->descentRight(key)) {
|
if (iter->key.descentRight(key)) {
|
||||||
key = iter->keyInRightSubtree(key);
|
key = iter->key.keyInRightSubtree(key);
|
||||||
iter = iter->mRight;
|
iter = iter->mRight;
|
||||||
} else {
|
} else {
|
||||||
key = iter->keyInLeftSubtree(key);
|
key = iter->key.keyInLeftSubtree(key);
|
||||||
iter = iter->mLeft;
|
iter = iter->mLeft;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -112,17 +105,17 @@ namespace tp {
|
||||||
Node* iter = mRoot;
|
Node* iter = mRoot;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (!iter) return nullptr;
|
if (!iter) return nullptr;
|
||||||
if (iter->exactNode(key)) return iter;
|
if (iter->key.exactNode(key)) return iter;
|
||||||
if (iter->descentRight(key)) {
|
if (iter->key.descentRight(key)) {
|
||||||
if (iter->mRight) {
|
if (iter->mRight) {
|
||||||
key = iter->keyInRightSubtree(key);
|
key = iter->key.keyInRightSubtree(key);
|
||||||
iter = iter->mRight;
|
iter = iter->mRight;
|
||||||
} else {
|
} else {
|
||||||
return iter;
|
return iter;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (iter->mLeft) {
|
if (iter->mLeft) {
|
||||||
key = iter->keyInLeftSubtree(key);
|
key = iter->key.keyInLeftSubtree(key);
|
||||||
iter = iter->mLeft;
|
iter = iter->mLeft;
|
||||||
} else {
|
} else {
|
||||||
return iter;
|
return iter;
|
||||||
|
|
@ -137,13 +130,13 @@ namespace tp {
|
||||||
|
|
||||||
if (head->mLeft) {
|
if (head->mLeft) {
|
||||||
// TODO: incomplete test
|
// TODO: incomplete test
|
||||||
if (head->descentRight(head->mLeft->getFindKey(head))) return head;
|
if (head->key.descentRight(head->mLeft->key.getFindKey(head))) return head;
|
||||||
if (head->mLeft->mParent != head) return head;
|
if (head->mLeft->mParent != head) return head;
|
||||||
if (!head->mRight && head->mLeft->mHeight != head->mHeight - 1) return head;
|
if (!head->mRight && head->mLeft->mHeight != head->mHeight - 1) return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (head->mRight) {
|
if (head->mRight) {
|
||||||
if (!head->descentRight(head->mRight->getFindKey(head))) return head;
|
if (!head->key.descentRight(head->mRight->key.getFindKey(head))) return head;
|
||||||
if (head->mRight->mParent != head) return head;
|
if (head->mRight->mParent != head) return head;
|
||||||
if (!head->mLeft && head->mRight->mHeight != head->mHeight - 1) return head;
|
if (!head->mLeft && head->mRight->mHeight != head->mHeight - 1) return head;
|
||||||
}
|
}
|
||||||
|
|
@ -236,8 +229,8 @@ namespace tp {
|
||||||
right->mHeight = 1 + max(getNodeHeight(right->mLeft), getNodeHeight(right->mRight));
|
right->mHeight = 1 + max(getNodeHeight(right->mLeft), getNodeHeight(right->mRight));
|
||||||
|
|
||||||
// cache
|
// cache
|
||||||
head->updateTreeCacheCallBack();
|
head->key.updateTreeCacheCallBack(head);
|
||||||
right->updateTreeCacheCallBack();
|
right->key.updateTreeCacheCallBack(right);
|
||||||
|
|
||||||
return right;
|
return right;
|
||||||
}
|
}
|
||||||
|
|
@ -264,8 +257,8 @@ namespace tp {
|
||||||
left->mHeight = 1 + max(getNodeHeight(left->mLeft), getNodeHeight(left->mRight));
|
left->mHeight = 1 + max(getNodeHeight(left->mLeft), getNodeHeight(left->mRight));
|
||||||
|
|
||||||
// cache
|
// cache
|
||||||
head->updateTreeCacheCallBack();
|
head->key.updateTreeCacheCallBack(head);
|
||||||
left->updateTreeCacheCallBack();
|
left->key.updateTreeCacheCallBack(left);
|
||||||
|
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
@ -278,16 +271,16 @@ namespace tp {
|
||||||
if (head == nullptr) {
|
if (head == nullptr) {
|
||||||
mSize++;
|
mSize++;
|
||||||
Node* out = newNode(key, data);
|
Node* out = newNode(key, data);
|
||||||
out->updateTreeCacheCallBack();
|
out->key.updateTreeCacheCallBack(out);
|
||||||
return out;
|
return out;
|
||||||
} else if (head->exactNode(key)) {
|
} else if (head->key.exactNode(key)) {
|
||||||
return head;
|
return head;
|
||||||
} else if (head->descentRight(key)) {
|
} else if (head->key.descentRight(key)) {
|
||||||
insertedNode = insertUtil(head->mRight, head->keyInRightSubtree(key), data);
|
insertedNode = insertUtil(head->mRight, head->key.keyInRightSubtree(key), data);
|
||||||
head->mRight = insertedNode;
|
head->mRight = insertedNode;
|
||||||
insertedNode->mParent = head;
|
insertedNode->mParent = head;
|
||||||
} else {
|
} else {
|
||||||
insertedNode = insertUtil(head->mLeft, head->keyInLeftSubtree(key), data);
|
insertedNode = insertUtil(head->mLeft, head->key.keyInLeftSubtree(key), data);
|
||||||
head->mLeft = insertedNode;
|
head->mLeft = insertedNode;
|
||||||
insertedNode->mParent = head;
|
insertedNode->mParent = head;
|
||||||
}
|
}
|
||||||
|
|
@ -298,14 +291,14 @@ namespace tp {
|
||||||
alni balance = alni(getNodeHeight(head->mRight) - getNodeHeight(head->mLeft));
|
alni balance = alni(getNodeHeight(head->mRight) - getNodeHeight(head->mLeft));
|
||||||
|
|
||||||
if (balance > 1) {
|
if (balance > 1) {
|
||||||
if (head->mRight->descentRight(head->keyInRightSubtree(key))) {
|
if (head->mRight->key.descentRight(head->key.keyInRightSubtree(key))) {
|
||||||
return rotateLeft(head);
|
return rotateLeft(head);
|
||||||
} else {
|
} else {
|
||||||
head->mRight = rotateRight(head->mRight);
|
head->mRight = rotateRight(head->mRight);
|
||||||
return rotateLeft(head);
|
return rotateLeft(head);
|
||||||
}
|
}
|
||||||
} else if (balance < -1) {
|
} else if (balance < -1) {
|
||||||
if (!head->mLeft->descentRight(head->keyInLeftSubtree(key))) {
|
if (!head->mLeft->key.descentRight(head->key.keyInLeftSubtree(key))) {
|
||||||
return rotateRight(head);
|
return rotateRight(head);
|
||||||
} else {
|
} else {
|
||||||
head->mLeft = rotateLeft(head->mLeft);
|
head->mLeft = rotateLeft(head->mLeft);
|
||||||
|
|
@ -313,7 +306,7 @@ namespace tp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
head->updateTreeCacheCallBack();
|
head->key.updateTreeCacheCallBack(head);
|
||||||
|
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
@ -321,10 +314,10 @@ namespace tp {
|
||||||
Node* removeUtil(Node* head, KeyArg key) {
|
Node* removeUtil(Node* head, KeyArg key) {
|
||||||
if (head == nullptr) return head;
|
if (head == nullptr) return head;
|
||||||
|
|
||||||
if (head->exactNode(key)) {
|
if (head->key.exactNode(key)) {
|
||||||
if (head->mRight && head->mLeft) {
|
if (head->mRight && head->mLeft) {
|
||||||
Node* min = minNode(head->mRight);
|
Node* min = minNode(head->mRight);
|
||||||
auto const& newKey = min->getFindKey(head->mRight);
|
auto const& newKey = min->key.getFindKey(head->mRight);
|
||||||
injectNodeInstead(head, min);
|
injectNodeInstead(head, min);
|
||||||
head->mRight = removeUtil(head->mRight, newKey);
|
head->mRight = removeUtil(head->mRight, newKey);
|
||||||
} else if (head->mRight) {
|
} else if (head->mRight) {
|
||||||
|
|
@ -342,10 +335,10 @@ namespace tp {
|
||||||
mSize--;
|
mSize--;
|
||||||
head = nullptr;
|
head = nullptr;
|
||||||
}
|
}
|
||||||
} else if (head->descentRight(key)) {
|
} else if (head->key.descentRight(key)) {
|
||||||
head->mRight = removeUtil(head->mRight, head->keyInRightSubtree(key));
|
head->mRight = removeUtil(head->mRight, head->key.keyInRightSubtree(key));
|
||||||
} else {
|
} else {
|
||||||
head->mLeft = removeUtil(head->mLeft, head->keyInLeftSubtree(key));
|
head->mLeft = removeUtil(head->mLeft, head->key.keyInLeftSubtree(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (head == nullptr) return head;
|
if (head == nullptr) return head;
|
||||||
|
|
@ -369,7 +362,7 @@ namespace tp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
head->updateTreeCacheCallBack();
|
head->key.updateTreeCacheCallBack(head);
|
||||||
|
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue