AVL Tree Insertion - Implementation - c++

thank you for all the help you guys have offered me throughout the years. Here comes another concern, and as usual any explanations, suggestions, or corrections are welcomed and appreciated!
I'm working on an assignement in C++ for an AVL tree, currently I'm working on insertion, but also need to implement removal, so even though this post is going to be heavy on insertion code, any pointers as to how to implement removal the easiest way to understand with my code would be awesome!
Okay, so I have the following functions to assist me in balance/insertion:
int AVL :: returnBalance(Node* nodeme)
{
return (whatisHeight(nodeme->leftbaby) - whatisHeight(nodeme->rightbaby));
}
int AVL :: whatisHeight(Node* localroot)
{
if(localroot == NULL)
{
return 0;
}else
return localroot->getHeight();
}
void AVL :: adjustHeight(Node* localroot)
{
if(localroot != NULL)
{
localroot->height = 1 + max(whatisHeight(localroot->leftbaby), whatisHeight(localroot->rightbaby));
}
}
bool AVL :: contains(Node* nodeme ,int data)
{
if(!nodeme)
{
return false;
}else
if(data == nodeme->value)
{
return true;
}
if(data < nodeme->value)
{
return contains(nodeme->leftbaby,data);
}else
{
return contains(nodeme->rightbaby,data);
}
}
// Rotation
void AVL :: rotateLeft(Node* localroot)
{
Node * temp = localroot->rightbaby;
localroot->rightbaby = temp->leftbaby;
temp->leftbaby = localroot;
localroot = temp;
adjustHeight(localroot);
adjustHeight(localroot->rightbaby);
adjustHeight(temp);
}
void AVL :: rotateRight(Node* localroot)
{
Node * temp = localroot->leftbaby;
localroot->leftbaby = temp->rightbaby;
temp->rightbaby = localroot;
adjustHeight(localroot);
adjustHeight(localroot->leftbaby);
adjustHeight(temp);
localroot = temp;
}
And my insertion and insertionrecursive functions are written as follows
bool AVL :: add(int data)
{
if(!contains(root, data))
{
insertRecursive(root,data);
return true;
}else
{
return false;
}
}
Node * AVL :: insertRecursive(Node * nodeme, int data)
{
// getting a number ready to print
int num1 = data;
string out1;
ostringstream convert1;
convert1 << num1;
out1 = convert1.str();
cout << "running recursive insert -- value: " << out1 << endl;
if(root == NULL)
{
cout << "adding root node" << endl;
Node * temporary = new Node(data);
temporary->height = 0;
root = temporary;
return root;
}else
if(nodeme == NULL)
{
cout << "adding at local" << endl;
nodeme = new Node(data);
nodeme->height = 0;
return nodeme;
}else
if(data < nodeme->value)
{
nodeme->leftbaby = insertRecursive(nodeme->leftbaby,data);
// balancing and stuff
adjustHeight(nodeme);
if ((returnBalance(nodeme) == -2 )&& (returnBalance(nodeme->leftbaby) == -1))
{
cout << "rotating right" << endl;
rotateRight(nodeme);
}else
if((returnBalance(nodeme) == -2) && (returnBalance(nodeme->leftbaby) == 1))
{
cout << "rotating left ---- 1" << endl;
rotateLeft(nodeme->leftbaby);
cout << "rotating right" << endl;
rotateRight(nodeme);
}else
if((returnBalance(nodeme) == 2) && (returnBalance(nodeme->leftbaby) == 1))
{
cout << "rotating left" << endl;
rotateLeft(nodeme);
}
else
if((returnBalance(nodeme) == 2) && (returnBalance(nodeme->leftbaby) == -1))
{
cout << "rotating right --- 2" << endl;
rotateRight(nodeme->leftbaby);
cout << "rotating left" << endl;
rotateLeft(nodeme);
}
adjustHeight(nodeme);
//
return nodeme;
}
else
{
nodeme->rightbaby = insertRecursive(nodeme->rightbaby,data);
// balancing and stuff
adjustHeight(nodeme);
if ((returnBalance(nodeme) == -2 )&& (returnBalance(nodeme->leftbaby) == -1))
{
cout << "rotating right" << endl;
rotateRight(nodeme);
}else
if((returnBalance(nodeme) == -2) && (returnBalance(nodeme->leftbaby) == 1))
{
cout << "rotating left --- 3" << endl;
rotateLeft(nodeme->leftbaby);
cout << "rotating right" << endl;
rotateRight(nodeme);
}else
if((returnBalance(nodeme) == 2) && (returnBalance(nodeme->leftbaby) == 1))
{
cout << "rotating left" << endl;
rotateLeft(nodeme);
}
else
if((returnBalance(nodeme) == 2) && (returnBalance(nodeme- >leftbaby) == -1))
{
cout << "rotating right --- 4" << endl;
rotateRight(nodeme->leftbaby);
cout << "rotating left" << endl;
rotateLeft(nodeme);
}
cout << "adjust height" << endl;
adjustHeight(nodeme);
//
return nodeme;
}
}
the cout s are simply for testing, my classes uses a given test driver, and as it turns out my tree isn't matching what it should when adding 0,1,2,3 to 9. It fails when it adds the 2. Note repeated values are not allowed in this tree, hence the contains function.
Now, In my mind I'm adding to a tree, updating the height, checking the balance and then rotating before I continue, so in my mind I'm keeping my tree balanced as I go. Obviously this isn't implementing correctly, so I need some direction!
Expected tree is:
0 1
0 0
1 2
I'm returning
0 0
1 1
11 2
I apologize to through so much code out there, and I'm sure there aren't many that really want to read it all, but just glancing at it your probably wanting to vomit and can offer a great explanation.
Thank you much!
-MJ

in rotation:
localroot = temp;
You should pass parameter by reference. If not, the actual parameter can't be changed and you'll get memory leak.
And so does nodeme in AVL :: insertRecursive.

Related

Print Level Wise Binary Tree in C++

The output is giving - Runtime Error (SIGSEGV). What could be the problem?
QUestion:
Given a binary tree, print the tree in level wise order.
For printing a node with data N, you need to follow the exact format -
N:L:x,R:y
wherer, N is data of any node present in the binary tree. x and y are the values of left and right child of node N. Print -1. if any child is null.
There is no space in between.
You need to print all nodes in the level order form in different lines.
Input format :
Elements in level order form (separated by space)
(If any node does not have left or right child, take -1 in its place)
Sample Input :
8 3 10 1 6 -1 14 -1 -1 4 7 13 -1 -1 -1 -1 -1 -1 -1
Sample Output :
8:L:3,R:10 3:L:1,R:6 10:L:-1,R:14 1:L:-1,R:-1 6:L:4,R:7 14:L:13,R:-1
4:L:-1,R:-1 7:L:-1,R:-1 13:L:-1,R:-1
Here is the code:
// Following is the Binary Tree node structure
/**************
class BinaryTreeNode {
public :
T data;
BinaryTreeNode<T> *left;
BinaryTreeNode<T> *right;
BinaryTreeNode(T data) {
this -> data = data;
left = NULL;
right = NULL;
}
};
***************/
void printLevelWise(BinaryTreeNode<int> *root) {
if(root == NULL){
return;
}
cout << root->data << ":";
queue<BinaryTreeNode<int>*> pendingNodes;
pendingNodes.push(root);
while(pendingNodes.size() != NULL){
BinaryTreeNode<int>* front = pendingNodes.front();
pendingNodes.pop();
if(front->left->data != -1){
cout << "L:" << front->left->data << ",";
pendingNodes.push(front->left);
}
else if(front->left->data == -1){
cout << "L:" << "-1" << ",";
}
if(front->right->data != -1){
cout << "R:" << front->right->data;
pendingNodes.push(front->right);
}
else if(front->left->data == -1){
cout << "R:" << "-1";
}
cout << endl;
}
/* Don't write main().
* Don't read input, it is passed as function argument.
* Print output and don't return it.
* Taking input is handled automatically.
*/
}
if(front->left->data != -1)
when your subtree not contain left node and you are checking left->data!=-1
thats why you are getting Runtime Error (SIGSEGV)
Use this code
/**************
class BinaryTreeNode {
public :
T data;
BinaryTreeNode<T> *left;
BinaryTreeNode<T> *right;
BinaryTreeNode(T data) {
this -> data = data;
left = NULL;
right = NULL;
}
};
***************/
void printLevelWise(BinaryTreeNode<int> *root) {
if(root == NULL){
return;
}
queue<BinaryTreeNode<int>*> pendingNodes;
pendingNodes.push(root);
while(pendingNodes.size() != NULL){
BinaryTreeNode<int>* front = pendingNodes.front();
pendingNodes.pop();
cout << front->data << ":";
if(front->left){
if(front->left->data != -1){
cout << "L:" << front->left->data << ",";
pendingNodes.push(front->left);
}
else{
cout << "L:" << "-1" << ",";
}
}
if(front->right){
if(front->right->data != -1){
cout << "R:" << front->right->data;
pendingNodes.push(front->right);
}
else{
cout << "R:" << "-1";
}
}
}
/* Don't write main().
* Don't read input, it is passed as function argument.
* Print output and don't return it.
* Taking input is handled automatically.
*/
}
As the description says, you should print "-1" if a child is null.
It does not say that you should print "-1" if the child's data is -1.
This would be the same as printing the data, so it would not be described as a special case.
(It is very important to read problem descriptions thoroughly. I think you're confusing this with the program's input format, which has -1 to indicate the absence of a child node, but that's not the input to your function.)
You need
if(front->left != nullptr) {
cout << "L:" << front->left->data << ",";
pendingNodes.push(front->left);
}
else {
cout << "L:" << "-1" << ",";
}
(You're also going to need to adjust how you print commas, but that's a different problem.)
void printLevelWise(BinaryTreeNode<int> *root)
{
if (root == NULL)
{
return;
}
queue<BinaryTreeNode<int> *> pendingNodes;
pendingNodes.push(root);
while (pendingNodes.size() != NULL)
{
BinaryTreeNode<int> *front = pendingNodes.front();
pendingNodes.pop();
cout << front->data << ":";
if (front->left)
{
if (front->left->data != -1)
{
cout << "L:" << front->left->data << ",";
pendingNodes.push(front->left);
}
}
else
{
cout << "L:"<< "-1"<< ",";
}
if (front->right)
{
if (front->right->data != -1)
{
cout << "R:" << front->right->data;
pendingNodes.push(front->right);
}
}
else
{
cout << "R:"<< "-1";
}
cout<<endl;
}
}

AVL balancing finding when to balance

I am trying to create an AVL tree and I am having trouble with my function for finding where the tree is imbalanced. I get a segmentation fault in this function.
void AVL::findInbalance(Node* start) {
cout << "findInbalance " << start->data << endl;
int diff;
if(start->rightChild == nullptr && start->leftChild == nullptr) {
diff = 0;
}
else {
diff = start->rightChild->getHeight() - start->leftChild->getHeight();
}
if(diff > 1 && start->rightChild->rightChild->getHeight() >= start->rightChild->leftChild->getHeight()){
cout << "left rotation" << endl;
rotation(start, 0);
}
if(diff < -1 && start->leftChild->leftChild->getHeight() >= start->leftChild->rightChild->getHeight()){
cout << "right rotation" << endl;
rotation(start, 1);
}
if(diff < -1 && start->leftChild->leftChild->getHeight() < start->leftChild->rightChild->getHeight()) {
cout << "left right rotation" << endl;
rotation(start->leftChild, 0);
rotation(start, 1);
}
if(diff > 1 && start->rightChild->rightChild->getHeight() < start->rightChild->leftChild->getHeight()) {
cout << "right left rotation" << endl;
rotation(start->rightChild, 1);
rotation(start, 0);
}
if(start->parent != nullptr){
findInbalance(start->parent);
}
else {
cout << "balance complete" << endl;
return;
}
}

c++ (Compare all spaces with Pawns )

I have a board game that has spaces (has numeral values 1,2,3, etc.) starting from 1 and 16 pieces of pawns; four for each player.
I want to show the result of my board game at some point. I tried the method below but that will make my code extremely long.
i have 16 pieces and 100 spaces that i have to repeat that code with 100 space that would take forever. the code below is just for one space (the first space)
Any idea how to show my result in a short way? Thanks in advance!
Here is my old-fashioned way:
//space 1
if (bpiece1->value == 1)
{
cout << " bpiece1";
}
else if (bpiece2->value == 1)
{
cout << " bpiece2";
}
else if (bpiece3->value == 1)
{
cout << " bpiece3";
}
else if (bpiece4->value == 1)
{
cout << " bpiece4";
}
else if (gpiece1->value == 1)
{
cout << " gpiece1";
}
else if (gpiece2->value == 1)
{
cout << " gpiece2";
}
else if (gpiece3->value == 1)
{
cout << " gpiece3";
}
else if (gpiece4->value == 1)
{
cout << " gpiece4";
}
else if (ypiece1->value == 1)
{
cout << " ypiece1";
}
else if (ypiece2->value == 1)
{
cout << " ypiece2";
}
else if (ypiece3->value == 1)
{
cout << " ypiece3";
}
else if (y4->value == 1)
{
cout << " y4";
}
else if (rpiece1->value == 1)
{
cout << " rpiece1";
}
else if (rpiece2->value == 1)
{
cout << " rpiece2";
}
else if (rpiece3->value == 1)
{
cout << " rpiece3";
}
else if (rpiece4->value == 1)
{
cout << " rpiece4";
}
else
{
cout << " 01";
}
C++ is an object-oriented language. Therefore, we start by creating a class that stores your board and implements all functions on it. Like
//Board.h
#include <array>
using std::array;
enum class Figure { None, Pawn };
class Board {
private:
array<array<Figure, 8>, 8> fields; //8x8 if it was a chess board
public:
void print() const;
};
//Board.cpp
#include "Board.h"
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
inline string to_string(const Figure figure){
switch(figure){
case Figure::None:
return " ";
case Figure::Pawn:
return "p";
}
//throw error here
return "";
}
void Board::print() const {
for(size_t i = 0; i < fields.size(); i++){
for(size_t j = 0; j < fields[i].size(); j++){
cout << to_string(fields[i][j]);
}
cout << endl;
}
cout << endl;
}
If this is new to you, you should really read the basic tutorials first and make sure that you understand each line I wrote in the end.
Important here is: Representation, represenation, representation. Don't think in "1 is a pawn", think in "a pawn is a pawn". Everything that has a function which you can think of should probably be a class, a structure or an enum.

Bug in AVL tree code, data structures c++

I am really trying to figure out the bug in my code I wrote for AVL tree but there seems to be a bug in it.
It calls the rotation functions but when it finishes rotation there are several problem:
root doesn't change
only root value is displayed when in-order traversal is done, other values seem to disappear
I have been trying to fix this bug since 2-3 days but cant seem to solve it.
Would love some help from you guys. I will be attaching the code with this.
/*
insertion
rotations all DONE
level order DONE
deletion
*/
#include <iostream>
#include <queue>
using namespace std;
struct node
{
int data;
int height;
node *left;
node *right;
node()
{
height = 0;
left = right = NULL;
}
};
class AVL
{
public:
node *root;
AVL()
{
root = NULL;
}
// search function
bool search(int num)
{
node *nodePtr = root;
if (root->data == num)
{
cout << "FOUND " << endl;
return true;
}
else
{
while (nodePtr != NULL)
{
if (nodePtr->data < num)
{
nodePtr = nodePtr->right;
}
else if (nodePtr->data > num)
{
nodePtr = nodePtr->left;
}
else
{
cout << "FOUND " << endl;
return true;
}
}
cout << "NOT FOUND " << endl;
return false;
}
}
// inorder
void inorder()
{
inorder(root);
}
// postorder
void postorder()
{
postorder(root);
}
// preorder
void preorder()
{
preorder(root);
}
// inorder utility function
void inorder(node *&nodePtr)
{
if (nodePtr)
{
inorder(nodePtr->left);
cout << nodePtr->data << ", ";
inorder(nodePtr->right);
}
}
// preorder utility function
void preorder(node *&nodePtr)
{
if (nodePtr)
{
cout << nodePtr->data << ", ";
preorder(nodePtr->left);
preorder(nodePtr->right);
}
}
// postorder utility function
void postorder(node *&nodePtr)
{
if (nodePtr)
{
postorder(nodePtr->left);
postorder(nodePtr->right);
cout << nodePtr->data << ", ";
}
}
// returns the number of nodes in the tree
int size(node *&nodePtr)
{
if (!nodePtr)
{
return 0;
}
else
{
return (size(nodePtr->left) + size(nodePtr->right)) + 1;
}
}
// function to check if tree is empty or not
bool isempty()
{
if (root == NULL)
{
return true;
}
else
{
return false;
}
}
// max function to calculate height and also the balance factor
int maximum(int x, int y)
{
if (x>y)
{
return x;
}
else
{
return y;
}
}
// returns the level of the tree
int returnHeight(node *&nodePtr)
{
if (nodePtr == NULL)
{
return 0;
}
else
{
return nodePtr->height;
}
}
// assigning the height to the node
void assignHeightToNode(node *&nodePtr)
{
int left = returnHeight(nodePtr->left);
int right = returnHeight(nodePtr->right);
nodePtr->height = maximum(left, right) + 1;
}
// single left rotate
node *singleLeftRotate(node *&nodePtr)
{
// if (nodePtr==NULL)
// {
// return;
// }
node * b = nodePtr->right;
nodePtr->right = b->left;
b->left = nodePtr;
return b;
}
// single right rotate
node *singleRightRotate(node *&nodePtr)
{
// if (nodePtr==NULL)
// {
// return ;
// }
node * b = nodePtr->left;
nodePtr->left = b->right;
b->right = nodePtr;
assignHeightToNode(nodePtr);
assignHeightToNode(b);
return b;
}
// double left rotate
node *doubleLeft(node *&nodePtr)
{
nodePtr->right = singleRightRotate(nodePtr->right);
return singleLeftRotate(nodePtr);
}
// double right rotate
node *doubleRight(node *&nodePtr)
{
nodePtr->left = singleLeftRotate(nodePtr->left);
return singleRightRotate(nodePtr);
}
// insert function
void insert1(int x)
{
cout << "NOW INSERTING " << x << endl;
insert2(x, root);
}
// insert utility function
void insert2(int &x, node *&nodePtr)
{
if (nodePtr == NULL)
{
node *newNode = new node;
newNode->data = x;
newNode->height = 0;
nodePtr = newNode;
checkRotations(nodePtr, x);
return;
}
else
{
if (x < nodePtr->data)
{
cout << endl << "GOING LEFT " << endl;
insert2(x, nodePtr->left);
}
else if (x > nodePtr->data)
{
cout << endl << "GOING RIGHT " << endl;
insert2(x, nodePtr->right);
}
else if (nodePtr->data == x)
{
cout << "DUPLICATE VALUES NOT ALLOWED " << endl;
return;
}
}
checkRotations(nodePtr, x);
}
// checking if rotations needed
void checkRotations(node *&nodePtr, int &x)
{
assignHeightToNode(nodePtr);
cout << endl << endl << "HEIGHT OF " << nodePtr->data << " IS " << nodePtr->height << endl;
int bf = returnHeight(nodePtr->left) - returnHeight(nodePtr->right);
cout << endl << endl << "BALANCE FACTOR AT NODE " << nodePtr->data << " IS " << bf << endl;
if (bf < -1 || bf > 1)
{
cout << endl << endl << "ROTATION IS HAPPEENING " << endl << endl;
if (x > nodePtr->data)
{
singleLeftRotate(nodePtr);
cout << endl << "ROTATION DONE SINGLE LEFT " << endl;
return;
}
else if (x < nodePtr->data)
{
singleRightRotate(nodePtr);
cout << endl << "ROTATION DONE SINGLE RIGHT " << endl;
return;
}
else if (x < root->data && x > root->left->data)
{
doubleRight(nodePtr);
cout << endl << "ROTATION DONE DOUBLE LEFT " << endl;
return;
}
else if (x > root->data && x < root->right->data)
{
doubleLeft(nodePtr);
cout << endl << "ROTATION DONE DOUBLE LEFT " << endl;
return;
}
}
}
// level order display code
void levelOrderDisplay()
{
levelOrderDisplay2(root);
}
// level order display utility function
void levelOrderDisplay2(node *&nodePtr)
{
if (nodePtr == NULL)
{
cout << "THE TREE IS EMPTY" << endl;
return;
}
queue <node *> displayer;
displayer.push(nodePtr);
while (!displayer.empty())
{
node *currentNode = displayer.front();
cout << currentNode->data << ", ";
if (currentNode->left != NULL)
{
displayer.push(currentNode->left);
}
else if (currentNode->right != NULL)
{
displayer.push(currentNode->right);
}
displayer.pop();
}
}
void rootD()
{
cout << "root is " << root->data << endl;
}
};
int main()
{
AVL tree;
tree.insert1(3);
tree.insert1(2);
tree.insert1(1);
tree.insert1(4);
tree.insert1(5);
tree.insert1(6);
tree.insert1(7);
tree.inorder();
// tree.rootD();
// tree.levelOrderDisplay();
// tree.rootD();
return 0;
}
I suggest you that do not pass node pointer by reference where your code does not change pointer value such as print. Try this... I completed my avl tree code just 2 3 day before and i have similar problem, when i debug my program i came to know that somehow in print function my pointer value is changed because i passed it by reference..... So.. Try this and see if work or not.... Hope this might help you.
Really late answer, but this is what you had to do. You should set the node passed in the function equal to the temporary node made in the function. In coding language, nodePtr=b should have been the last line of the single rotate functions.
Hope this helps :)

AVL Tree Rotation Deletes Nodes

Working on AVL implementation. When I try to perform a rotation it deletes the children of the node being rotated. So far I've only started on right. I didn't implement a parent pointer in my nodes as I used my BST as a base.
Any guesses as to why this is fracking up? If any additional info is needed I can post it. I didn't want to upload my entire class for wall-of-code reasons.
Insert
template <typename T>
void AVL<T>::insert(T data)
{
insert(mRootNode, data);
}
template <typename T>
void AVL<T>::insert(Node<T>*& node, const T &data)
{
// If the tree is empty, make a new node and make it
// the root of the tree.
if (node == NULL)
{
node = new Node<T>(data);
return;
}
// If num is already in tree: return.
if (node->mData == data)
return;
// The tree is not empty: insert the new node into the
// left or right subtree.
if (data < node->mData)
{
insert(node->mLeft, data);
}
else
{
insert(node->mRight, data);
}
// Check for balance errors
int balance = getBalance(node);
bool
rotL = (balance > 1) && (getBalance(node->mRight) == 1),
rotR = (balance < -1) && (getBalance(node->mLeft) == -1),
rotRL = (balance > 1) && (getBalance(node->mRight) == -1),
rotLR = (balance < -1) && (getBalance(node->mLeft) == 1);
if (rotR)
{
rotateRight(node);
}
}
Right Rotation
template <class T>
void AVL<T>::rotateRight(Node<T>*& node)
{
showTree(); // Show tree before rotation
Node<T>* other = node->mLeft;
Node<T>* tmp = other->mRight;
other->mRight = node;
node->mLeft = tmp;
showTree(); // Show tree after rotation
}
Balance
template <class T>
int AVL<T>::getBalance(Node<T>* node)
{
return (node->mRight ? treeHeight(node->mRight) : 0) - (node->mLeft ? treeHeight(node->mLeft) : 0);
}
Stub
void StubAVL()
{
AVL<int> tree;
cout << "Inserting: 5\n";
tree.insert(5);
cout << "Inserting: 8\n";
tree.insert(8);
cout << "Inserting: 3\n";
tree.insert(3);
cout << "Inserting: 12\n";
tree.insert(12);
cout << "Inserting: 9\n";
tree.insert(9);
cout << "Inserting: 2\n";
tree.insert(2);
cout << "Inserting: 13\n";
tree.insert(13);
cout << "Inserting: 0\n";
tree.insert(0);
cout << "Inserting: -1\n";
tree.insert(-1);
cout << "Inorder: ";
tree.showInOrder();
cout << endl;
cout << "Preorder: ";
tree.showPreOrder();
cout << endl;
cout << "Postorder: ";
tree.showPostOrder();
cout << endl;
cout << "Node Count = " << tree.nodesCount() << endl;
cout << "Leaves Count = " << tree.leavesCount() << endl;
cout << "Height = " << tree.getHeight() << endl;
cout << "The tree looks like:\n";
tree.showTree();
cout
<< "\n\n"
<< "Heights\n";
tree.showHeight();
cout
<< "\n\n"
<< "Balances\n";
tree.showBalance();
cout << "\n\n";
system("pause");
}
Output
Right after it inserts 0 ↑ the children of 3 are deleted.