#ifndef AVLTREE_H #define AVLTREE_H #include #include "avlnode.h" template class AVLTree { private: AVLNode *root = nullptr; AVLNode *rotateLeft(AVLNode *node); AVLNode *rotateRight(AVLNode *node); int getHeight(AVLNode *node); void rebalance(AVLNode *node); public: AVLTree(); ~AVLTree(); bool insert(AVLNode *newNode); AVLNode *search(T searchData); bool remove(const T removeData); void printAsList(); void printNLR(); template friend ostream &operator << (ostream &os, AVLTree *tree); }; template AVLTree::AVLTree() { this->root = nullptr; } template AVLTree::~AVLTree() { delete this->root; this->root = nullptr; } template void AVLTree::rebalance(AVLNode *node) { if (node == nullptr) return; node->update(); if (node->balance > 1) { if (node->left->balance < -1) node->left = rotateLeft(node->left); node = rotateRight(node); } else if (node->balance < -1) { if (node->right->balance > 1) node->right = rotateRight(node->right); node = rotateLeft(node); } if (node->parent == nullptr) this->root = node; else rebalance(node->parent); } template AVLNode *AVLTree::rotateLeft(AVLNode *node) { AVLNode *temp = node->right; AVLNode *tmp = temp->left; AVLNode *parent = node->parent; temp->parent = parent; node->right = tmp; if (tmp != nullptr) { tmp->parent = node; } temp->left = node; node->parent = temp; if (parent != nullptr) { if (parent->left == node) parent->left = temp; else parent->right = temp; } node->update(); temp->update(); return temp; } template AVLNode *AVLTree::rotateRight(AVLNode *node) { AVLNode *temp = node->left; AVLNode *tmp = temp->right; AVLNode *parent = node->parent; temp->parent = parent; node->left = tmp; if (tmp != nullptr) { tmp->parent = node; } temp->right = node; node->parent = temp; if (parent != nullptr) { if (parent->left == node) parent->left = temp; else parent->right = temp; } node->update(); temp->update(); return temp; } template int AVLTree::getHeight(AVLNode *node) { if (node == nullptr) return 0; return node->height; } template bool AVLTree::insert(AVLNode *newNode) { if (newNode == nullptr) return false; if (this->root == nullptr) { this->root = newNode; return true; } AVLNode *temp = this->root; AVLNode *parent; while (true) { if (temp->data == newNode->data) return false; parent = temp; bool goLeft = (newNode->data < temp->data); temp = goLeft ? temp->left : temp->right; if (temp == nullptr) { if (goLeft) { parent->left = newNode; newNode->parent = parent; } else { parent->right = newNode; newNode->parent = parent; } rebalance(parent); return true; } } } template bool AVLTree::remove(const T removeData) { AVLNode *temp = this->root; while (temp != nullptr) { if (removeData < temp->data) temp = temp->left; else if (removeData > temp->data) temp = temp->right; else break; } if (temp == nullptr) return false; AVLNode *del = temp; if (temp->left != nullptr) { del = temp->left; while (del->right != nullptr) del = del->right; } AVLNode *parent = nullptr; if (del == this->root) { this->root = this->root->right; if (this->root != nullptr) this->root->parent = nullptr; } else if (del != temp) { temp->data = del->data; parent = del->parent; if (parent->left == del) parent->left = del->left; else parent->right = del->left; if (del->left != nullptr) del->left->parent = parent; } else { parent = del->parent; if (parent->left == del) parent->left = del->right; else parent->right = del->right; if (del->right != nullptr) del->right->parent = parent; } if (parent != nullptr) this->rebalance(parent); return true; } template void AVLTree::printNLR() { stack *> sAVLNode; stack sNodeLevel; sAVLNode.push(this->root); sNodeLevel.push(0); while (!sAVLNode.empty()) { AVLNode *tNode = sAVLNode.top(); sAVLNode.pop(); int tLevel = sNodeLevel.top(); sNodeLevel.pop(); for (int i = 0; i < tLevel; ++i) { cout << " "; } if (tNode == nullptr) { cout << "NULL" << endl; continue; } cout << tNode->data << "(" << tNode->balance << ")" << endl; sAVLNode.push(tNode->right); sNodeLevel.push(tLevel + 1); sAVLNode.push(tNode->left); sNodeLevel.push(tLevel + 1); } } template AVLNode *AVLTree::search(T searchData) { AVLNode *temp = this->root; while (temp != nullptr) { if (searchData < temp->data) temp = temp->left; else if (searchData > temp->data) temp = temp->right; else return temp; } return nullptr; } template void printLNR(AVLNode *subroot) { if (subroot == nullptr) return; printLNR(subroot->left); cout << subroot->data << endl; printLNR(subroot->right); } template void AVLTree::printAsList() { printLNR(this->root); } template ostream &operator << (ostream &os, AVLTree *tree) { os << tree->root; return os; } #endif // AVLTREE_H