|
|
@@ -1,5 +1,7 @@
|
|
|
// balance and height functions based on code from
|
|
|
// http://www.sanfoundry.com/cpp-program-implement-avl-trees/
|
|
|
+// Finding elements based on code from
|
|
|
+// http://www.cplusplus.com/forum/beginner/54835/
|
|
|
|
|
|
#include <cassert>
|
|
|
#include <iostream>
|
|
|
@@ -14,14 +16,16 @@ BSTNode::BSTNode(int key) :
|
|
|
parent_(std::weak_ptr<BSTNode>()),
|
|
|
left_(nullptr),
|
|
|
right_(nullptr),
|
|
|
- height_(1) {} // add a height_
|
|
|
+ height_(0),
|
|
|
+ balance_(0) {} // add a height_
|
|
|
|
|
|
BSTNode::BSTNode(int key, std::weak_ptr<BSTNode> parent) :
|
|
|
key_(key),
|
|
|
parent_(parent),
|
|
|
left_(nullptr),
|
|
|
right_(nullptr),
|
|
|
- height_(1) {}
|
|
|
+ height_(0),
|
|
|
+ balance_(0) {}
|
|
|
|
|
|
bool BSTNode::IsLeaf() const {
|
|
|
return left_ == nullptr && right_ == nullptr;
|
|
|
@@ -78,17 +82,19 @@ int AVLCommands::height(std::shared_ptr<BSTNode> currentNode) {
|
|
|
if (currentNode->left_ != nullptr) {
|
|
|
leftHeight = height(currentNode->left_);
|
|
|
} else {
|
|
|
- leftHeight = 0;
|
|
|
+ leftHeight = -1;
|
|
|
}
|
|
|
|
|
|
if (currentNode->right_ != nullptr) {
|
|
|
rightHeight = height(currentNode->right_);
|
|
|
} else {
|
|
|
- rightHeight = 0;
|
|
|
+ rightHeight = -1;
|
|
|
}
|
|
|
|
|
|
heightMax = 1 + max(leftHeight, rightHeight);
|
|
|
currentNode->height_ = heightMax;
|
|
|
+ // update balance for each node
|
|
|
+ currentNode->balance_ = leftHeight - rightHeight;
|
|
|
}
|
|
|
return currentNode->height_;
|
|
|
}
|
|
|
@@ -97,56 +103,46 @@ int AVLCommands::getBalance(std::shared_ptr<BSTNode> currentNode) {
|
|
|
if (root_ == nullptr) {
|
|
|
return 0;
|
|
|
}
|
|
|
- int leftHeight = 0;
|
|
|
- int rightHeight = 0;
|
|
|
- int balanceFactor = 0;
|
|
|
- if (currentNode->left_ != nullptr) {
|
|
|
- leftHeight = currentNode->left_->height_;
|
|
|
- }
|
|
|
- if (currentNode->right_ != nullptr) {
|
|
|
- rightHeight = currentNode->right_->height_;
|
|
|
- }
|
|
|
- balanceFactor = leftHeight - rightHeight);
|
|
|
|
|
|
- // Left Left Case
|
|
|
- if (lastNodeBalance > 1 && key < lastNode->left_->key_)
|
|
|
- rightRotate(lastNode);
|
|
|
-
|
|
|
- // Right Right Case
|
|
|
- if (lastNodeBalance < -1 && key > lastNode->right_->key_)
|
|
|
- leftRotate(lastNode);
|
|
|
+ int leftHeight, rightHeight, balanceFactor;
|
|
|
+ if (currentNode != nullptr) {
|
|
|
+ if (currentNode->left_ != nullptr) {
|
|
|
+ leftHeight = height(currentNode->left_);
|
|
|
+ } else {
|
|
|
+ leftHeight = -1;
|
|
|
+ }
|
|
|
|
|
|
- // Left Right Case
|
|
|
- if (lastNodeBalance > 1 && key > lastNode->left_->key_) {
|
|
|
- lastNode->left_ = leftRotate(lastNode->left_);
|
|
|
- rightRotate(lastNode);
|
|
|
- }
|
|
|
+ if (currentNode->right_ != nullptr) {
|
|
|
+ rightHeight = height(currentNode->right_);
|
|
|
+ } else {
|
|
|
+ rightHeight = -1;
|
|
|
+ }
|
|
|
|
|
|
- // Right Left Case
|
|
|
- if (lastNodeBalance < -1 && key < lastNode->right_->key_) {
|
|
|
- lastNode->right_ = rightRotate(lastNode->right_);
|
|
|
- leftRotate(lastNode);
|
|
|
- }
|
|
|
- return 0;
|
|
|
+ balanceFactor = leftHeight - rightHeight;
|
|
|
+ }
|
|
|
+ return balanceFactor;
|
|
|
}
|
|
|
|
|
|
std::shared_ptr<BSTNode> AVLCommands::rightRotate(std::shared_ptr<BSTNode> currentNode){
|
|
|
+ std::cout << "Right Rotate!" << std::endl;
|
|
|
std::shared_ptr<BSTNode> x = currentNode->left_;
|
|
|
- std::shared_ptr<BSTNode> T2 = x->right_;
|
|
|
+ std::shared_ptr<BSTNode> T2 = x->right_;
|
|
|
+ // Perform rotation
|
|
|
+ x->right_ = currentNode;
|
|
|
+ currentNode->left_ = T2;
|
|
|
|
|
|
- // Perform rotation
|
|
|
- x->right_ = currentNode;
|
|
|
- currentNode->left_ = T2;
|
|
|
+ // Update heights
|
|
|
+ currentNode->height_ = max(height(currentNode->left_), height(currentNode->right_))+1;
|
|
|
+ x->height_ = max(height(x->left_), height(x->right_))+1;
|
|
|
|
|
|
- // Update heights
|
|
|
- currentNode->height_ = max(height(currentNode->left_), height(currentNode->right_))+1;
|
|
|
- x->height_ = max(height(x->left_), height(x->right_))+1;
|
|
|
+ // Return new root
|
|
|
+ return x;
|
|
|
|
|
|
- // Return new root
|
|
|
- return x;
|
|
|
+ return currentNode;
|
|
|
}
|
|
|
|
|
|
std::shared_ptr<BSTNode> AVLCommands::leftRotate(std::shared_ptr<BSTNode> currentNode){
|
|
|
+ std::cout << "Left Rotate!" << std::endl;
|
|
|
std::shared_ptr<BSTNode> y = currentNode->right_;
|
|
|
std::shared_ptr<BSTNode> T2 = y->left_;
|
|
|
|
|
|
@@ -173,6 +169,7 @@ void AVLCommands::printTree(std::shared_ptr<BSTNode> currentNode){
|
|
|
} else {
|
|
|
std::cout << "key: " << currentNode->key_ << std::endl;
|
|
|
std::cout << "height: " << currentNode->height_ << std::endl;
|
|
|
+ std::cout << "balance: " << currentNode->balance_ << std::endl;
|
|
|
if (currentNode->left_ != nullptr) {
|
|
|
std::cout << "left" << std::endl;
|
|
|
printTree(currentNode->left_);
|
|
|
@@ -205,54 +202,36 @@ void AVLCommands::Insert(int key) {
|
|
|
}
|
|
|
size_++;
|
|
|
|
|
|
- // update height of the tree
|
|
|
+ // update height and balance of the tree
|
|
|
height(root_);
|
|
|
|
|
|
- std::cout << "insert height update attempt..." << std::endl;
|
|
|
- int leftHeight, rightHeight;
|
|
|
-
|
|
|
- if (lastNode->left_ != nullptr) {
|
|
|
- leftHeight = lastNode->left_->height_;
|
|
|
- } else {
|
|
|
- leftHeight = 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (lastNode->right_ != nullptr) {
|
|
|
- rightHeight = lastNode->right_->height_;
|
|
|
- } else {
|
|
|
- rightHeight = 0;
|
|
|
- }
|
|
|
-
|
|
|
- lastNode->height_ = 1 + max(leftHeight, rightHeight);
|
|
|
-
|
|
|
- std::cout << "New height: " << lastNode->height_ << std::endl;
|
|
|
- std::cout << "insert height update attempt success!" << std::endl;
|
|
|
-
|
|
|
- // Update balance factor of this ancestor's node
|
|
|
- std::cout << "insert balance update attempt..." << std::endl;
|
|
|
- int lastNodeBalance = getBalance(lastNode);
|
|
|
- std::cout << "New balance: " << lastNodeBalance << std::endl;
|
|
|
- std::cout << "insert balance update attempt success!" << std::endl;
|
|
|
+ std::cout << "Rotation to be preformed:" << std::endl;
|
|
|
|
|
|
// Check if unbalanced
|
|
|
// Left Left Case
|
|
|
- if (lastNodeBalance > 1 && key < lastNode->left_->key_)
|
|
|
- rightRotate(lastNode);
|
|
|
+ if (lastNode->balance_ > 1 && key < lastNode->left_->key_) {
|
|
|
+ std::cout << "Left-Left" << std::endl;
|
|
|
+ rightRotate(lastNode);
|
|
|
+ }
|
|
|
|
|
|
// Right Right Case
|
|
|
- if (lastNodeBalance < -1 && key > lastNode->right_->key_)
|
|
|
- leftRotate(lastNode);
|
|
|
+ if (lastNode->balance_ < -1 && key > lastNode->right_->key_) {
|
|
|
+ std::cout << "Right-Right" << std::endl;
|
|
|
+ leftRotate(lastNode);
|
|
|
+ }
|
|
|
|
|
|
// Left Right Case
|
|
|
- if (lastNodeBalance > 1 && key > lastNode->left_->key_) {
|
|
|
- lastNode->left_ = leftRotate(lastNode->left_);
|
|
|
- rightRotate(lastNode);
|
|
|
+ if (lastNode->balance_ > 1 && key > lastNode->left_->key_) {
|
|
|
+ std::cout << "Left-Right" << std::endl;
|
|
|
+ lastNode->left_ = leftRotate(lastNode->left_);
|
|
|
+ rightRotate(lastNode);
|
|
|
}
|
|
|
|
|
|
// Right Left Case
|
|
|
- if (lastNodeBalance < -1 && key < lastNode->right_->key_) {
|
|
|
- lastNode->right_ = rightRotate(lastNode->right_);
|
|
|
- leftRotate(lastNode);
|
|
|
+ if (lastNode->balance_ < -1 && key < lastNode->right_->key_) {
|
|
|
+ std::cout << "Right-Left" << std::endl;
|
|
|
+ lastNode->right_ = rightRotate(lastNode->right_);
|
|
|
+ leftRotate(lastNode);
|
|
|
}
|
|
|
|
|
|
}
|