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;
}
}
Related
I have this program that is supposed to simulate fish and sharks moving around on a grid of any given size, but I'm running into an infinite loop in my fish's move function.
the program isn't consistent on when the looping occurs because when I run it sometimes it gets stuck on turn 0, but it could also happen on turn 3; this is possible because of my randomness attached to it
here's my fish_class.cpp where the problem occurs, I've marked where the infinite loop happens. hope anyone could help.
#include "fish_class.h"
#include "world.h"
#include <vector>
#include <stdlib.h>
#include <time.h>
using namespace std;
void FishT::SetFishBreed(int fishBreedRate)
{
fishBreed = fishBreedRate;
//return fishBreed;
}
int FishT::GetFishBreed()
{
return fishBreed;
}
int FishT::IncreaseMoves()
{
if (moveCount == fishBreed) //just incase for unlimited breeding
{
moveCount = 0;
}
moveCount++;
return moveCount;
}
void FishT::Move(WorldT& world)
{
bool HasMoved = false;
srand (time (NULL)); //initialize random seed
//generate a number from 1 to 4 (north, south, east, west) to move to on the world grid
int PlaceToMove = static_cast<int>(rand() % 4 + 1);
while (HasMoved == false)
{
if (PlaceToMove == 1 and world.IsInBoundry(x, y - 1) and world.IsEmpty(x, y - 1)) //checking if north is empty and in bounds
{
//cout << "moving fish north" << endl;
//update fish's position
world.SetEmpty(x, y);
world.SetFishPlacement(x, y - 1);
y = y - 1;
HasMoved = true;
Turn(world); //increase our move tracker
}
else if (PlaceToMove == 2 and world.IsInBoundry(x, y + 1) and world.IsEmpty(x, y + 1)) //checking if south is empty and in bounds
{
//cout << "moving fish south" << endl;
//update fish's position
world.SetEmpty(x, y);
world.SetFishPlacement(x, y + 1);
y = y + 1;
HasMoved = true;
Turn(world);
}
else if (PlaceToMove == 3 and world.IsInBoundry(x + 1, y) and world.IsEmpty(x + 1, y)) //checking if east is empty
{
//cout << "moving fish east" << endl;
//update fish's position
world.SetEmpty(x, y);
world.SetFishPlacement(x + 1, y);
x = x + 1;
HasMoved = true;
Turn(world);
}
else if (PlaceToMove == 4 and world.IsInBoundry(x - 1, y) and world.IsEmpty(x - 1, y)) //checking if west is empty
{
//cout << "moving fish west" << endl;
//update fish's position
world.SetEmpty(x, y);
world.SetFishPlacement(x - 1, y);
x = x - 1;
HasMoved = true;
Turn(world);
}
else
{
// *** this is where the loop problem occurs ***
//cout << "updating fish's placetomove" << endl;
PlaceToMove = PlaceToMove % 4 + 1;
}
}
if (PlaceToMove == 1 and moveCount == fishBreed)
{
//cout << "in reproduce north" << endl;
//cout << "fish breed is: " << GetFishBreed() << endl;
//cout << "move count is: " << moveCount << endl;
Reproduce(x, y + 1, world);
}
else if (PlaceToMove == 2 and moveCount == fishBreed)
{
//cout << "in reproduce south" << endl;
//cout << "fish breed is: " << GetFishBreed() << endl;
//cout << "move count is: " << moveCount << endl;
Reproduce(x, y - 1, world);
}
else if (PlaceToMove == 3 and moveCount == fishBreed)
{
//cout << "in reproduce east" << endl;
//cout << "fish breed is: " << GetFishBreed() << endl;
//cout << "move count is: " << moveCount << endl;
Reproduce(x - 1, y, world);
}
else if (PlaceToMove == 4 and moveCount == fishBreed)
{
//cout << "in reproduce west" << endl;
//cout << "fish breed is: " << GetFishBreed() << endl;
//cout << "move count is: " << moveCount << endl;
Reproduce(x + 1, y, world);
}
}
void FishT::Reproduce(int x, int y, WorldT& world)
{
//cout << "in reproduce function" << endl;
world.SetFishPlacement(x, y);
world.AddNewFish(x, y);
}
void FishT::Turn(WorldT& world)
{
IncreaseMoves(); //keep track of move turns
}
void FishT::Die(WorldT& world)
{
world.FishDie(x, y);
}
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.
So the problem I'm having is this: When a win condition is met the program should stop the while loop and just display the win/lose/draw message, but instead it allows the X and O of the game to take one more turn and I'm rather at a loss as to why. Any help would be greatly appreciated.
#include <iostream>
#include <cmath>
#include <string>
#include <cstdlib>
#include <ctime>
const int yCoordMax = 6;
const int xCoordMax = 2;
int xCoord;
int yCoord;
int square = 0;
const char PLAYER1 = 'X';
const char COMPUTER = 'O';
const int MAXTURN = 9;
char playerChar ; //the current turn's player's symbol
const std::string WIN = "You won! How nice.\n";
const std::string LOSE = "You lost.\n";
const std::string DRAW = "It's a draw.\n";
const std::string PLAY = "You will be the X's against the computer O's\n\n";
const std::string INSTRUCTIONS = "Enter the number of the square you wish to mark\nwith 1 being top left and 9 being bottom right.\n\n";
const std::string INVALIDSQUARE = "Please enter a correct square number between 1 and 9.\n";
const std::string SQUAREISFULL = "That square is already marked. Choose another.\n";
bool gameOver = false;
bool isGameDraw = false;
char boardChoices[3][3] = {{'1', '2', '3'},{'4', '5', '6'},{'7', '8', '9'}};
void drawBoard(void);
void playGame(void);
bool checkForWinner(void);
void isMoveValid(void);
int main()
{
std::srand(time(0)); //sets the seed for computer only once
std::cout << PLAY;
std::cout << INSTRUCTIONS;
playerChar = PLAYER1;
while(!gameOver)
{
drawBoard();
playGame();
isMoveValid();
gameOver = checkForWinner();
}
if (playerChar == 'O' && !isGameDraw)
{
drawBoard();
std::cout << std::endl << std::endl << "Player 1 [X] Wins! Game Over!\n";
}
else if (playerChar == 'X' && !isGameDraw)
{
drawBoard();
std::cout << std::endl << std::endl << "Player 2 [O] Wins! Game Over!\n";
}
else
{
drawBoard();
std::cout << std::endl << std::endl << "It's a draw! Game Over!\n";
}
return 0;
}
void drawBoard()
{
std::cout << std::endl << std::endl << "gameover says " << gameOver << std::endl;
std::cout << "+----" << "+----+" << "----+" << std::endl; // 0
std::cout << "| " << boardChoices[0][0] << " " << "| " << boardChoices[0][1] << " |" << " " << boardChoices[0][2] << " |" << std::endl; // 1 input here only [1][0], [1][1], [1][2]
std::cout << "+----" << "+----+" << "----+" << std::endl; // 2
std::cout << "| " << boardChoices[1][0] << " " << "| " << boardChoices[1][1] << " |" << " " << boardChoices[1][2] << " |" << std::endl; // 3 input here only [3][0], [3][1], [3][2]
std::cout << "+----" << "+----+" << "----+" << std::endl; // 4
std::cout << "| " << boardChoices[2][0] << " " << "| " << boardChoices[2][1] << " |" << " " << boardChoices[2][2] << " |" << std::endl; // 5 input here only [5][0], [5][1], [5][2]
std::cout << "+----" << "+----+" << "----+" << std::endl;
}
void playGame()
{
std::cout << std::endl;
if(playerChar == PLAYER1)
{
std::cout << "X's turn :: ";
std::cin >> square;
}
else if(playerChar == COMPUTER)
{
square = rand() % 9 + 1;
std::cout << "O's turn:: " << square << std::endl << std::endl;
}
if (square == 1)
{yCoord = 0;
xCoord = 0;}
if (square == 2)
{yCoord = 0;
xCoord = 1;}
if (square == 3)
{yCoord = 0;
xCoord = 2;}
if (square == 4)
{yCoord = 1;
xCoord = 0;}
if (square == 5)
{yCoord = 1;
xCoord = 1;}
if (square == 6)
{yCoord = 1;
xCoord = 2;}
if (square == 7)
{yCoord = 2;
xCoord = 0;}
if (square == 8)
{yCoord = 2;
xCoord = 1;}
if (square == 9)
{yCoord = 2;
xCoord = 2;}
}
void isMoveValid()
{
if(playerChar == PLAYER1 && boardChoices[yCoord][xCoord] != PLAYER1 && boardChoices[yCoord][xCoord] != COMPUTER)
{
boardChoices[yCoord][xCoord] = playerChar;
playerChar = COMPUTER;
}
else if(playerChar == COMPUTER && boardChoices[yCoord][xCoord] != PLAYER1 && boardChoices[yCoord][xCoord] != COMPUTER)
{
boardChoices[yCoord][xCoord] = COMPUTER;
playerChar = PLAYER1;
}
else
{
if(playerChar == PLAYER1)
std::cout << SQUAREISFULL;
}
}
bool checkForWinner()
{
std::string victoryOrDefeat;
if(playerChar == COMPUTER)
{
victoryOrDefeat = LOSE;
}
else if(playerChar == PLAYER1)
{
victoryOrDefeat = WIN;
}
if(boardChoices[0][0] == playerChar && boardChoices[0][1] == playerChar && boardChoices[0][2] == playerChar) // Horizontal
{std::cout << victoryOrDefeat;
return true;}
if(boardChoices[1][0] == playerChar && boardChoices[1][1] == playerChar && boardChoices[1][2] == playerChar) // Horizontal
{std::cout << victoryOrDefeat;
return true;}
if(boardChoices[2][0] == playerChar && boardChoices[2][1] == playerChar && boardChoices[2][2] == playerChar) // Horizontal
{std::cout << victoryOrDefeat;
return true;}
if(boardChoices[0][0] == playerChar && boardChoices[1][0] == playerChar && boardChoices[2][0] == playerChar) // Vertical
{std::cout << victoryOrDefeat;
return true;}
if(boardChoices[0][1] == playerChar && boardChoices[1][1] == playerChar && boardChoices[2][1] == playerChar) // Vertical
{std::cout << victoryOrDefeat;
return true;}
if(boardChoices[0][2] == playerChar && boardChoices[1][2] == playerChar && boardChoices[2][2] == playerChar) // Vertical
{std::cout << victoryOrDefeat;
return true;}
if(boardChoices[0][0] == playerChar && boardChoices[1][1] == playerChar && boardChoices[2][2] == playerChar) // Diagonal
{std::cout << victoryOrDefeat;
return true;}
if(boardChoices[0][2] == playerChar && boardChoices[1][1] == playerChar && boardChoices[2][0] == playerChar) // Diagonal
{std::cout << victoryOrDefeat;
return true;}
for (int i = 0; i < 3; i++)//Check for draw
{
for (int j = 0; j < 3; j++)
{
if (boardChoices[i][j] != 'X' && boardChoices[i][j] != 'O')
{
return false;
}
}
}
isGameDraw = true;
return true;
}
I have got it..You are changing playerChar after each isMoveValid() check as a result when you should be checking with X you are checking with O..simple do this change after checking the winner..that will give correct result.
Initially when player1 gives X position you are checking the win move for giving O and in later cases too this happens.. That's why it's getting the error.
I used the code from this post, How to display binary search tree in console properly?. It complies fine on my IDE, but it doesnt print out anything so it basically shows nothing. I want it to print out in the tree structure like the post mentioned I posted here. I think I have the code typed wrong for 3rd argument for the printLevel function in int main(). Would char* x = " " work fine? It does give warning message, but I'm not sure if I do it right.
string printLevel(Node *pRoot, int level, string gap)
{
if (level == 1)
{
if (pRoot == 0)
{
cout << ".. printLevel - " << pRoot << ": " << gap << "-" << gap << "\n";
return gap + "-" + gap;
}
stringstream out;
out << pRoot->data;
//cout << ".. printLevel - " << pRoot << ": " << gap << pRoot->data << gap << "\n";
return gap + out.str() + gap;
}
else if(level > 1)
{
string left = printLevel(pRoot ? pRoot->pLeft : 0, level - 1, gap);
string right = printLevel(pRoot ? pRoot->pRight : 0, level - 1, gap);
//cout << ".. printLevel - " << pRoot << ": '" << left << "', '" << right << "'\n";
return left + " " + right;
}
else return
"";
}
void printLevelOrder(Node* pRoot, int depth)
{
for (int i = 1; i <= depth; i++)
{
string gap = "";
for (int j = 0; j < pow(2, depth - i) - 1; j++)
{
gap += " ";
}
string levelNodes = printLevel(pRoot, i, gap);
cout << levelNodes <<endl;
}
}
in the main
Node *pRoot = NULL;
int inputValue = 0;
char* gap = " ";
// Loop to read in input values
cout << "To build a BST enter positive integer values, followed by -1 \n";
while (inputValue != -1)
{
cin >> inputValue;
if( inputValue != -1)
{
insertIntoTree( pRoot, inputValue);
}
}
cout << endl;
// Display the tree
printLevel(pRoot, inputValue, gap);
printLevelOrder(pRoot, inputValue);
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.