Avl Stuff

This commit is contained in:
Samuel Oberhofer 2022-06-06 13:36:46 +02:00
parent 5627eac84b
commit 9c037c5aed
4 changed files with 300 additions and 0 deletions

51
Uebung 2/2.3/Makefile Normal file
View File

@ -0,0 +1,51 @@
# Name of the binary for Development
BINARY = main
# Name of the binary for Release
FINAL = prototyp
# Object files
OBJS = main.o avlNode.o
# Compiler flags
CFLAGS = -g #-std=c++17 #-fsanitize=address,undefined -Werror -Wall
# Linker flags
LFLAGS = #-fsanitize=address,undefined
#Which Compiler to use
COMPILER = c++
# all target: builds all important targets
all: binary
final : ${OBJS}
${COMPILER} ${LFLAGS} -o ${FINAL} ${OBJS}
binary : ${OBJS}
${COMPILER} ${LFLAGS} -o ${BINARY} ${OBJS}
# Links the binary
${BINARY} : ${OBJS}
${COMPILER} ${LFLAGS} -o ${BINARY} ${OBJS}
# Compiles a source-file (any file with file extension .c) into an object-file
#
# "%" is a wildcard which matches every file-name (similar to * in regular expressions)
# Such a rule is called a pattern rule (because it matches a pattern, see https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html),
# which are a form of so called implicit rules (see https://www.gnu.org/software/make/manual/html_node/Implicit-Rules.html)
# "$@" and "$<" are so called automatic variables (see https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html)
%.o : %.cpp
${COMPILER} -c ${CFLAGS} -o $@ $<
# Rules can not only be used for compiling a program but also for executing a program
run: ${BINARY}
./${BINARY}
# Delete all build artifacts
clean :
rm -rf ${BINARY} ${OBJS}
# all and clean are a "phony" targets, meaning they are no files
.PHONY : all clean

181
Uebung 2/2.3/avlNode.cpp Normal file
View File

@ -0,0 +1,181 @@
#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;
}

25
Uebung 2/2.3/avlNode.h Normal file
View File

@ -0,0 +1,25 @@
#include <iostream>
#include <sstream>
#include <string>
#pragma once
class AvlNode {
public:
int key;
AvlNode *left;
AvlNode *right;
int height;
AvlNode(int key);
int max(int n1, int n2);
int getHeightDifference();
int getHeight();
AvlNode *insert(int key);
AvlNode *leftRotation();
AvlNode *rightRotation();
AvlNode *deleteItem(int key);
std::string printPreorder();
};

43
Uebung 2/2.3/main.cpp Normal file
View File

@ -0,0 +1,43 @@
#include "avlNode.h"
#include <iostream>
#include <string>
int main() {
AvlNode *root = new AvlNode(10);
// always give the root, as it could be changed with any insertion (in
// comparison to BST!)
root = root->insert(15);
root = root->insert(5);
root = root->insert(8);
root = root->insert(3);
root = root->insert(9);
root = root->insert(16);
root = root->insert(17);
root = root->deleteItem(10);
for (int i = 20; i <= 50; i++) {
root = root->insert(i);
}
// root = root->deleteItem(5);
/* -- Scenarion 1 - rightRotation -- */
// root = root->insert(2);
/* -- Scenarion 2 - leftRotation -- */
// root = root->insert(17);
// root = root->insert(19);
/* -- Scenarion 3 - rightRotation, then leftRotation -- */
// root = root->insert(17);
// root = root->insert(16);
/* -- Scenarion 4 - leftRotation, then rightRotattion -- */
// root = root->insert(17);
// root = root->insert(6);
// root = root->insert(7);
std::cout << root->printPreorder();
std::cout << "Perfectly balanced! As all things should be!\n";
return 0;
}