From 8e550876b5ffb8054acd9598f86da5fe2dc23621 Mon Sep 17 00:00:00 2001 From: Stoycho Kyosev Date: Mon, 19 Dec 2022 19:17:32 +0200 Subject: add AVLTree --- Seminar10/AVLTree.hpp | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 Seminar10/AVLTree.hpp diff --git a/Seminar10/AVLTree.hpp b/Seminar10/AVLTree.hpp new file mode 100644 index 0000000..2b4fba7 --- /dev/null +++ b/Seminar10/AVLTree.hpp @@ -0,0 +1,203 @@ +#ifndef AVL_TREE_IMPL +#define AVL_TREE_IMPL + +#include +#include +#include + +template +class AVLTree { +private: + + struct Node { + T data; + Node* left; + Node* right; + int height; + + static int getHeight(const Node* r) { + if (r == nullptr) + return 0; + + return r->height; + } + + static void rotateLeft(Node*& r) { + assert(r->right != nullptr); + + Node* originalRight = r->right; + r->right = originalRight->left; + originalRight->left = r; + r = originalRight; + } + + static void rotateRight(Node*& r) { + assert(r->left != nullptr); + + Node* originalLeft = r->left; + r->left = originalLeft->right; + originalLeft->right = r; + r = originalLeft; + } + + static void balanceLeft(Node*& r) { + assert(r); + + int rootBalance = getBalanceFactor(r); + int leftBalance = getBalanceFactor(r->left); + + if (rootBalance == -2) { + if (leftBalance == 1) { + rotateRight(r->left); + updateHeight(r->left->left); + updateHeight(r->left); + } + + rotateLeft(r); + updateHeight(r->left); + updateHeight(r); + } + } + + static void balanceRight(Node*& r) { + assert(r); + + int rootBalance = getBalanceFactor(r); + int rightBalance = getBalanceFactor(r->right); + + if (rootBalance == 2) { + if (rightBalance == -1) { + rotateRight(r->right); + updateHeight(r->right->right); + updateHeight(r->right); + } + + rotateLeft(r); + updateHeight(r->left); + updateHeight(r); + } + } + + static void updateHeight(Node* r) { + if (r == nullptr) + return; + r->height = std::max(getHeight(r->left), getHeight(r->right)) + 1; + } + + static int getBalanceFactor(const Node* r) { + if (r == nullptr) + return 0; + + return getHeight(r->right) - getHeight(r->left); + } + + Node(const T& d, Node* l, Node* r, int h) : data{ d }, left{ l }, right{ r }, height{ h } {} + }; + + Node* findMinNode(Node* r) { + if (r->left == nullptr) + return r; + + return findMinNode(r->left); + } + + void insertRec(Node*& r, const T& elem) { + if (r == nullptr) { + r = new Node(elem, nullptr, nullptr, 1); + size++; + return; + } + + if (r->data < elem) { + insertRec(r->right, elem); + + Node::updateHeight(r->right); + Node::balanceRight(r); + } + else if (r->data > elem) { + insertRec(r->left, elem); + + Node::updateHeight(r->left); + Node::balanceLeft(r); + } + } + + bool removeRec(Node*& r, const T& elem) { + if (r == nullptr) { + return false; + } + + if (r->data < elem) { + removeRec(r->right, elem); + + Node::updateHeight(r); + Node::balanceLeft(r); + } + else if (r->data > elem) { + removeRec(r->left, elem); + + Node::updateHeight(r); + Node::balanceRight(r); + } + else { + if (!r->left && !r->right) { + delete r; + r = nullptr; + return true; + } + else if (r->left && !r->right) { + Node* toDelete = r; + r = r->left; + delete toDelete; + } + else if (!r->left && r->right) { + Node* toDelete = r; + r = r->right; + delete toDelete; + } + else { + root->data = findMinNode(root->right)->data; + removeRec(r->right, r->data); + Node::updateHeight(r); + Node::balanceRight(r); + } + } + return true; + } + + void freeRec(Node* r) { + if (r == nullptr) + return; + + freeRec(r->left); + freeRec(r->right); + delete r; + } + +public: + AVLTree() : root{ nullptr }, size{ 0 } {} + + // TBI + AVLTree(const AVLTree& other) = delete; + AVLTree& operator=(const AVLTree& other) = delete; + bool contains(const T& elem); + + void insert(const T& elem) { + insertRec(root, elem); + } + + bool remove(const T& elem) { + return removeRec(root, elem); + } + + ~AVLTree() { + freeRec(root); + } + +private: + + Node* root; + size_t size; +}; + +#endif \ No newline at end of file -- cgit v1.3.1-23-gd82d