Algorithmen_Datenstrukturen/Uebung 2/Uebung2_3/avlNode.cpp

181 lines
5.0 KiB
C++

#include "avlNode.h"
AvlNode::AvlNode(int key) {
this->left = nullptr;
this->right = nullptr;
this->key = key;
this->height = 1;
}
// helper function which returns the max of the two inputs
int AvlNode::max(int n1, int n2) { return (n1 > n2) ? n1 : n2; }
// caluclate height difference of a given Node by calculating difference of
// heights of left and right subtree
int AvlNode::getHeightDifference() {
int diff;
if (this == nullptr) {
diff = 0;
} else {
diff = this->left->getHeight() - this->right->getHeight();
}
return diff;
}
// returns height of a given AVL Node
int AvlNode::getHeight() {
if (this == nullptr) {
return 0;
} else {
return this->height;
}
}
// insert a new node by recursively going to the sorted position which yields
// nullptr
AvlNode *AvlNode::insert(int key) {
if (this == nullptr) {
AvlNode *newNode = new AvlNode(key);
return newNode;
} else if (key > this->key) {
this->right = this->right->insert(key);
} else if (key < this->key) {
this->left = this->left->insert(key);
} else {
return this;
}
// update heights of all other nodes
this->height =
1 + this->max(this->left->getHeight(), this->right->getHeight());
int diff = this->getHeightDifference();
// check if rebalancing is necessary
if (diff > 1) { // check which kind of rebalancing is necessary
if (key > this->left->key) {
this->left = this->left->leftRotation();
return this->rightRotation();
} else if (key < this->left->key) {
return this->rightRotation();
}
} else if (diff < -1) { // check which kind of rebalancing is necessary
if (key > this->right->key) {
return this->leftRotation();
} else if (key < this->right->key) {
this->right = this->right->rightRotation();
return this->leftRotation();
}
}
return this;
}
// perform a left rotation (see lecture)
AvlNode *AvlNode::leftRotation() {
std::cout << "Do a left rotation on node " << this->key << "\n";
AvlNode *rightNode = this->right;
AvlNode *leftOfRightNode = rightNode->left;
rightNode->left = this;
this->right = leftOfRightNode;
// update heights
this->height =
this->max(this->left->getHeight(), this->right->getHeight()) + 1;
rightNode->height =
this->max((rightNode->left->getHeight()), rightNode->right->getHeight()) +
1;
return rightNode;
}
// perform a right rotation (see lecture)
AvlNode *AvlNode::rightRotation() {
std::cout << "Do a right rotation on node " << this->key << "\n";
AvlNode *leftNode = this->left;
AvlNode *rightOfLeftNode = leftNode->right;
leftNode->right = this;
this->left = rightOfLeftNode;
// update heights
this->height =
this->max(this->left->getHeight(), this->right->getHeight()) + 1;
leftNode->height =
this->max(leftNode->left->getHeight(), leftNode->right->getHeight()) + 1;
return leftNode;
}
// function to print an AVL tree in pre-order: (sub)root, left (sub)tree, right
// (sub)tree
std::string AvlNode::printPreorder() {
std::stringstream output;
output << "node:\t" << this->key << ",\t";
output << "height:\t" << this->getHeight() << ",\t";
output << "Diff:\t" << this->getHeightDifference() << "\n";
if (this->left != nullptr) {
output << this->left->printPreorder();
}
if (this->right != nullptr) {
output << this->right->printPreorder();
}
return output.str();
}
AvlNode *AvlNode::deleteItem(int key) {
AvlNode *node = this;
if (node == nullptr) {
return this;
} else if (key < node->key) {
node->left = node->left->deleteItem(key);
} else if (key > node->key) {
node->right = node->right->deleteItem(key);
} else {
// AvlNode *deleteNode = node;
if (node->left == nullptr && node->right == nullptr) {
delete node;
node = nullptr;
return nullptr;
} else if (node->left == nullptr) { // only children in right subtree
AvlNode *temp = node;
node = node->right;
delete temp;
} else if (this->right == nullptr) { // only children in left subtree
AvlNode *temp = node;
node = node->left;
delete temp;
} else { // we have to keep the BST structure, here, we look for the minimum
// in the right subtree (see lecture)
AvlNode *temp = node->right;
while (temp->left != nullptr) {
temp = temp->left;
}
node->key = temp->key;
node->right = node->right->deleteItem(temp->key);
}
}
this->height = 1 + max(this->left->getHeight(), this->right->getHeight());
int diff = this->getHeightDifference();
if (diff > 1) {
if (this->left->getHeightDifference() >= 0) {
// Left Left Case
return this->rightRotation();
} else {
// Left Right Case
this->left = this->left->leftRotation();
return this->rightRotation();
}
}
if (diff < -1) {
if (this->right->getHeightDifference() <= 0) {
// Right Right Case
return this->leftRotation();
} else {
// Right Left Case
this->right = this->right->rightRotation();
return this->leftRotation();
}
}
return node;
}