Formatting code
This commit is contained in:
parent
6dc64ce76b
commit
13a8f07e32
37 changed files with 2242 additions and 2281 deletions
|
|
@ -9,88 +9,88 @@ namespace tp {
|
|||
|
||||
NumericType val;
|
||||
|
||||
AvlNumericKey() = default;
|
||||
AvlNumericKey(NumericType val) : val(val) {}
|
||||
AvlNumericKey() = default;
|
||||
AvlNumericKey(NumericType val) : val(val) {}
|
||||
|
||||
inline bool descentRight(AvlNumericKey in) const { return in.val > val; }
|
||||
inline bool descentLeft(AvlNumericKey in) const { return in.val < val; }
|
||||
inline bool exactNode(AvlNumericKey in) const { return in.val == val; }
|
||||
inline bool descentLeft(AvlNumericKey in) const { return in.val < val; }
|
||||
inline bool exactNode(AvlNumericKey in) const { return in.val == val; }
|
||||
|
||||
inline AvlNumericKey getFindKey(/**/) const { return *this; }
|
||||
inline AvlNumericKey keyInRightSubtree(AvlNumericKey in) const { return in; }
|
||||
inline AvlNumericKey keyInLeftSubtree(AvlNumericKey in) const { return in; }
|
||||
inline AvlNumericKey getFindKey(/**/) const { return *this; }
|
||||
inline AvlNumericKey keyInRightSubtree(AvlNumericKey in) const { return in; }
|
||||
inline AvlNumericKey keyInLeftSubtree(AvlNumericKey in) const { return in; }
|
||||
|
||||
inline void updateTreeCacheCallBack() {}
|
||||
inline void updateTreeCacheCallBack() {}
|
||||
};
|
||||
|
||||
template <typename Key, typename Data, class Allocator = DefaultAllocator>
|
||||
class AvlTree {
|
||||
typedef SelCopyArg<Key> KeyArg;
|
||||
typedef SelCopyArg<Data> DataArg;
|
||||
typedef SelCopyArg<Key> KeyArg;
|
||||
typedef SelCopyArg<Data> DataArg;
|
||||
|
||||
public:
|
||||
class Node {
|
||||
friend AvlTree;
|
||||
public:
|
||||
class Node {
|
||||
friend AvlTree;
|
||||
|
||||
private:
|
||||
Node(KeyArg aKey, DataArg aData) : key(aKey), data(aData) {}
|
||||
private:
|
||||
Node(KeyArg aKey, DataArg aData) : key(aKey), data(aData) {}
|
||||
|
||||
public:
|
||||
Data data;
|
||||
Key key;
|
||||
public:
|
||||
Data data;
|
||||
Key key;
|
||||
|
||||
private:
|
||||
Node* mLeft = nullptr;
|
||||
Node* mRight = nullptr;
|
||||
Node* mParent = nullptr;
|
||||
ualni mHeight = 0;
|
||||
private:
|
||||
Node* mLeft = nullptr;
|
||||
Node* mRight = nullptr;
|
||||
Node* mParent = nullptr;
|
||||
ualni mHeight = 0;
|
||||
|
||||
private:
|
||||
inline bool descentRight(KeyArg aKey) const { return key.descentRight(aKey); }
|
||||
inline bool descentLeft(KeyArg aKey) const { return key.descentLeft(aKey); }
|
||||
inline bool exactNode(KeyArg aKey) const { return key.exactNode(aKey); }
|
||||
private:
|
||||
inline bool descentRight(KeyArg aKey) const { return key.descentRight(aKey); }
|
||||
inline bool descentLeft(KeyArg aKey) const { return key.descentLeft(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 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(); }
|
||||
};
|
||||
inline void updateTreeCacheCallBack() { key.updateTreeCacheCallBack(); }
|
||||
};
|
||||
|
||||
private:
|
||||
Node* mRoot = nullptr;
|
||||
ualni mSize = 0;
|
||||
private:
|
||||
Node* mRoot = nullptr;
|
||||
ualni mSize = 0;
|
||||
Allocator mAlloc;
|
||||
|
||||
private:
|
||||
|
||||
inline void deleteNode(Node* node) {
|
||||
node->~Node();
|
||||
mAlloc.deallocate(node);
|
||||
}
|
||||
private:
|
||||
|
||||
inline void deleteNode(Node* node) {
|
||||
node->~Node();
|
||||
mAlloc.deallocate(node);
|
||||
}
|
||||
|
||||
inline Node* newNode(KeyArg key, DataArg data) {
|
||||
return new (mAlloc.allocate(sizeof(Node))) Node(key, data);
|
||||
}
|
||||
inline Node* newNode(KeyArg key, DataArg data) {
|
||||
return new (mAlloc.allocate(sizeof(Node))) Node(key, data);
|
||||
}
|
||||
|
||||
inline void injectNodeInstead(Node* place, Node* inject) {
|
||||
// TODO : swap instead of copy
|
||||
place->data = inject->data;
|
||||
place->key = inject->key;
|
||||
}
|
||||
inline void injectNodeInstead(Node* place, Node* inject) {
|
||||
// TODO : swap instead of copy
|
||||
place->data = inject->data;
|
||||
place->key = inject->key;
|
||||
}
|
||||
|
||||
inline alni getNodeHeight(const Node* node) const {
|
||||
return node ? node->mHeight : -1;
|
||||
}
|
||||
|
||||
// returns new head
|
||||
Node* rotateLeft(Node* pivot) {
|
||||
DEBUG_ASSERT(pivot);
|
||||
Node* rotateLeft(Node* pivot) {
|
||||
DEBUG_ASSERT(pivot);
|
||||
|
||||
Node* const head = pivot;
|
||||
Node* const right = pivot->mRight;
|
||||
Node* const right_left = right->mLeft;
|
||||
Node* const parent = pivot->mParent;
|
||||
Node* const head = pivot;
|
||||
Node* const right = pivot->mRight;
|
||||
Node* const right_left = right->mLeft;
|
||||
Node* const parent = pivot->mParent;
|
||||
|
||||
// parents
|
||||
if (right_left) right_left->mParent = head;
|
||||
|
|
@ -112,13 +112,13 @@ namespace tp {
|
|||
return right;
|
||||
}
|
||||
|
||||
Node* rotateRight(Node* pivot) {
|
||||
DEBUG_ASSERT(pivot);
|
||||
Node* rotateRight(Node* pivot) {
|
||||
DEBUG_ASSERT(pivot);
|
||||
|
||||
Node* const head = pivot;
|
||||
Node* const left = pivot->mLeft;
|
||||
Node* const left_right = left->mRight;
|
||||
Node* const parent = pivot->mParent;
|
||||
Node* const head = pivot;
|
||||
Node* const left = pivot->mLeft;
|
||||
Node* const left_right = left->mRight;
|
||||
Node* const parent = pivot->mParent;
|
||||
|
||||
// parents
|
||||
if (left_right) left_right->mParent = head;
|
||||
|
|
@ -141,12 +141,12 @@ namespace tp {
|
|||
}
|
||||
|
||||
// recursively returns valid left or right child or root
|
||||
Node* insertUtil(Node* head, KeyArg key, DataArg data) {
|
||||
Node* insertUtil(Node* head, KeyArg key, DataArg data) {
|
||||
|
||||
Node* insertedNode;
|
||||
Node* insertedNode;
|
||||
|
||||
if (head == nullptr) {
|
||||
mSize++;
|
||||
mSize++;
|
||||
Node* out = newNode(key, data);
|
||||
out->updateTreeCacheCallBack();
|
||||
return out;
|
||||
|
|
@ -155,14 +155,14 @@ namespace tp {
|
|||
return head;
|
||||
}
|
||||
else if (head->descentRight(key)) {
|
||||
insertedNode = insertUtil(head->mRight, head->keyInRightSubtree(key), data);
|
||||
insertedNode = insertUtil(head->mRight, head->keyInRightSubtree(key), data);
|
||||
head->mRight = insertedNode;
|
||||
insertedNode->mParent = head;
|
||||
insertedNode->mParent = head;
|
||||
}
|
||||
else {
|
||||
insertedNode = insertUtil(head->mLeft, head->keyInLeftSubtree(key), data);
|
||||
insertedNode = insertUtil(head->mLeft, head->keyInLeftSubtree(key), data);
|
||||
head->mLeft = insertedNode;
|
||||
insertedNode->mParent = head;
|
||||
insertedNode->mParent = head;
|
||||
}
|
||||
|
||||
// update height
|
||||
|
|
@ -194,31 +194,31 @@ namespace tp {
|
|||
return head;
|
||||
}
|
||||
|
||||
Node* removeUtil(Node* head, KeyArg key) {
|
||||
Node* removeUtil(Node* head, KeyArg key) {
|
||||
if (head == nullptr) return head;
|
||||
|
||||
if (head->exactNode(key)) {
|
||||
if (head->mRight && head->mLeft) {
|
||||
Node* min = minNode(head->mRight);
|
||||
auto const& newKey = min->getFindKey(head->mRight);
|
||||
injectNodeInstead(head, min);
|
||||
Node* min = minNode(head->mRight);
|
||||
auto const& newKey = min->getFindKey(head->mRight);
|
||||
injectNodeInstead(head, min);
|
||||
head->mRight = removeUtil(head->mRight, newKey);
|
||||
}
|
||||
else if (head->mRight) {
|
||||
injectNodeInstead(head, head->mRight);
|
||||
injectNodeInstead(head, head->mRight);
|
||||
deleteNode(head->mRight);
|
||||
head->mRight = nullptr;
|
||||
mSize--;
|
||||
mSize--;
|
||||
}
|
||||
else if (head->mLeft) {
|
||||
injectNodeInstead(head, head->mLeft);
|
||||
deleteNode(head->mLeft);
|
||||
injectNodeInstead(head, head->mLeft);
|
||||
deleteNode(head->mLeft);
|
||||
head->mLeft = nullptr;
|
||||
mSize--;
|
||||
mSize--;
|
||||
}
|
||||
else {
|
||||
deleteNode(head);
|
||||
mSize--;
|
||||
deleteNode(head);
|
||||
mSize--;
|
||||
head = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
@ -229,7 +229,7 @@ namespace tp {
|
|||
head->mLeft = removeUtil(head->mLeft, head->keyInLeftSubtree(key));
|
||||
}
|
||||
|
||||
if (head == nullptr) return head;
|
||||
if (head == nullptr) return head;
|
||||
|
||||
head->mHeight = 1 + max(getNodeHeight(head->mRight), getNodeHeight(head->mLeft));
|
||||
alni balance = getNodeHeight(head->mRight) - getNodeHeight(head->mLeft);
|
||||
|
|
@ -268,7 +268,7 @@ namespace tp {
|
|||
return mSize;
|
||||
}
|
||||
|
||||
Node* head() const {
|
||||
Node* head() const {
|
||||
return this->mRoot;
|
||||
}
|
||||
|
||||
|
|
@ -282,24 +282,24 @@ namespace tp {
|
|||
if (mRoot) mRoot->mParent = nullptr;
|
||||
}
|
||||
|
||||
Node* maxNode(Node* head) const {
|
||||
if (!head) return nullptr;
|
||||
while (head->mRight != nullptr) {
|
||||
head = head->mRight;
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
Node* minNode(Node* head) const {
|
||||
Node* maxNode(Node* head) const {
|
||||
if (!head) return nullptr;
|
||||
while (head->mLeft != nullptr) {
|
||||
head = head->mLeft;
|
||||
}
|
||||
while (head->mRight != nullptr) {
|
||||
head = head->mRight;
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
Node* find(KeyArg key) const {
|
||||
Node* iter = mRoot;
|
||||
Node* minNode(Node* head) const {
|
||||
if (!head) return nullptr;
|
||||
while (head->mLeft != nullptr) {
|
||||
head = head->mLeft;
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
Node* find(KeyArg key) const {
|
||||
Node* iter = mRoot;
|
||||
while (true) {
|
||||
if (!iter) return nullptr;
|
||||
if (iter->exactNode(key)) return iter;
|
||||
|
|
@ -313,61 +313,61 @@ namespace tp {
|
|||
}
|
||||
}
|
||||
|
||||
Node* findLessOrEq(KeyArg key) const {
|
||||
Node* iter = mRoot;
|
||||
while (true) {
|
||||
if (!iter) return nullptr;
|
||||
if (iter->exactNode(key)) return iter;
|
||||
if (iter->descentLeft(key)) {
|
||||
if (iter->mLeft) {
|
||||
key = iter->keyInLeftSubtree(key);
|
||||
iter = iter->mLeft;
|
||||
} else {
|
||||
return iter;
|
||||
}
|
||||
} else {
|
||||
if (iter->mRight) {
|
||||
key = iter->keyInRightSubtree(key);
|
||||
iter = iter->mRight;
|
||||
} else {
|
||||
return iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Node* findLessOrEq(KeyArg key) const {
|
||||
Node* iter = mRoot;
|
||||
while (true) {
|
||||
if (!iter) return nullptr;
|
||||
if (iter->exactNode(key)) return iter;
|
||||
if (iter->descentLeft(key)) {
|
||||
if (iter->mLeft) {
|
||||
key = iter->keyInLeftSubtree(key);
|
||||
iter = iter->mLeft;
|
||||
} else {
|
||||
return iter;
|
||||
}
|
||||
} else {
|
||||
if (iter->mRight) {
|
||||
key = iter->keyInRightSubtree(key);
|
||||
iter = iter->mRight;
|
||||
} else {
|
||||
return iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// returns first invalid node
|
||||
const Node* findInvalidNode(const Node* head) const {
|
||||
const Node* findInvalidNode(const Node* head) const {
|
||||
if (head == nullptr) return nullptr;
|
||||
|
||||
if (head->mLeft) {
|
||||
// TODO: incomplete test
|
||||
if (!head->descentLeft(head->mLeft->getFindKey(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->descentRight(head->mRight->getFindKey(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;
|
||||
}
|
||||
|
||||
if (head->mLeft && head->mRight) {
|
||||
if (max(head->mLeft->mHeight, head->mRight->mHeight) != head->mHeight - 1) return head;
|
||||
}
|
||||
if (head->mLeft && head->mRight) {
|
||||
if (max(head->mLeft->mHeight, head->mRight->mHeight) != head->mHeight - 1) return head;
|
||||
}
|
||||
|
||||
int balance = getNodeHeight(head->mRight) - getNodeHeight(head->mLeft);
|
||||
|
||||
if (balance > 1 || balance < -1) return head;
|
||||
|
||||
const Node* ret = findInvalidNode(head->mRight);
|
||||
const Node* ret = findInvalidNode(head->mRight);
|
||||
|
||||
if (ret) return ret;
|
||||
|
||||
return findInvalidNode(head->mLeft);
|
||||
}
|
||||
|
||||
bool isValid() { return findInvalidNode(head()) == nullptr; }
|
||||
bool isValid() { return findInvalidNode(head()) == nullptr; }
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue