I'm working on a function to find the height of a binary search tree. I found a method that seems like it should work, but I keep getting this error, and I don't know whats wrong with it: Unhandled exception at 0x00903417 in PA5.exe: 0xC0000005: Access violation reading location 0x00000004.
Here are my height functions...
template <class T>
int BST<T>::height()
{
return displayHeight(mRootNode);
}
template <class T>
int BST<T>::displayHeight(BST<T> *node)
{
if (node = NULL)
{
return 0;
}
int left = displayHeight(node->mLeft);
int right = displayHeight(node->mRight);
if (left > right)
return 1 + left;
else
return 1 + right;
}
This is the implementation in the main function...
cout << endl << "height: " << tree.height();
If I should include anything else, let me know. Thanks!
if (node = NULL)
should be
if (node == NULL)
because in C++ = is an assignment operator and == is the relational operator for comparison.
Why the crash?
When you do if (node = NULL), you are assigning NULL to node and since NULL is 0 the if condition fails. So you go ahead and call the function recursively on the nodes's children. Now suppose node was actually NULL when the function was called for the first time, you'll be doing the recursive calls on NULL's left and right children!!! Leading to crash.
You are assigning null to your node parameter variable in your if statement.
if (node = NULL)
{
return 0;
}
should be
if(node == NULL) ...
Method to find the height while creating a tree(BST):For both left subtree and right subtree::
Put the elements you want to put in your binary tree in an array before you create the actual tree.
Calculate the number of elements which are greater than the root, which will be going to the left of the tree and similarly with the right side.
Then while you add the elements to your tree. Everytime set a flag bit to 1 or 0 depending on whether you are adding it to the left subtree or the right.
if(root->right && flagleft==1)
no_left--;
else if(root->right && flagright==1)
no_right--;
This is while you append a node to the left side.
if(root->left && flagl==1)
nl--;
else if(root->left && flagr==1)
nr--;
This is while you append a node to the right side.
This is because you've assigned the node to NULL i.e NULL value is 0 , so condition fails.
do if(node==NULL)
instead of
if(node=NULL)
Related
I need to implement this recursive function that will take a root of a BST and recursively count the number of nodes in it with two childrens, but i am not sure if my logic is correct?
My logic is:
If leaf or empty we return 0
You check if a node with two children we add one and call again on its left and right children
Else if a node doesnt have two children you call on its left and right subtrees without adding
Here is my function implementation
ps: assume everything in the BinarySearchTree class is implemented:
int count(BinarySearchTree *root )
{
if(root== nullptr)
{
return 0;
}
if(root->right != nullptr and root->left!= nullptr)
{
return 1+count(root->right)+count(root->left);
}
count(root->right);
count(root->left);
}
You need to sum up the counts even if your node doesn't have two children. Two count calls that you have after if are basically not used.
You can fix it like this:
int count(BinarySearchTree *root )
{
if (root== nullptr)
{
return 0;
}
int countForThisNode = root->right != nullptr and root->left!= nullptr;
return countForThisNode + count(root->right) + count(root->left);
}
In this case countForThisNode is 1 for the node that you want to count and 0 otherwise. All other nodes are added to the result no matter what.
I hope this is information you were asking for!
Your function has undefined behaviour because the control can be transfered to the closing brace without returning anything.
count(root->right);
count(root->left);
}
For starters as the list is not changed the parameter should have the qualifier const.
The function can be defined much simpler the following way
unsigned int count( const BinarySearchTree *root )
{
return root == nullptr ? 0
: ( root->left && root->right ) + count( root->left )
+ count( root->right );
}
An easy way to implement this function:
start from a standard enumeration of the nodes (can be prefix, infix, suffix, doesn't matter);
modify it so that at every node you increment the counter if there are two children.
Note that you need to look at the whole tree, as parts of it may be reached via single-childrened nodes.
visit(root):
if root.left != null:
visit(root.left)
if root.right != null:
visit(root.right)
becomes
visit(root):
count= root.left != null and root.right != null
if root.left != null:
count+= visit(root.left)
if root.right != null:
count+= visit(root.right)
return count
recently I passed a programming interview where I had to create a method that returns the address of a node (belonging to a tree). The method takes an integer value as an argument.
My code worked on a small tree, but when searching a large tree (300,000 nodes) I got an error stating "cannot access address '0x.....'".
What should I do to fix this?
'''
struct Node
{
int value;
Node* left = nullptr;
Node* right = nullptr;
Node* find_node(int);
};
Node* Node::find_node(int v)// The function is working on small trees only
{
if(this->value == v) //comparing the the value inside the root with the function's argument
return this;
else if(this->value > v) //if v is smaller than the node's value, search the next left node
{
if(this->left == nullptr) //checking if the next node on the left exists
return nullptr; //null returned if there is no more nodes
else
return (this->left)->find_node(v); //Call the find_node function recursively on the left node
}
else if(this->value < v) //if v is bigger than the node's value, search the next right node
{
if(this->right == nullptr) //checking if the next node on the left exists
return nullptr; //null returned if there is no more nodes
else
return (this->right)->find_node(v);// Call the find_node function recursively on the right node
}
return nullptr;// If the value is not found
}
'''
Your code needs lots of activation records on the call stack for repetitive calls to find_node(v). And it may lead to overflow of the call stack.
To avoid it, you can use non-recursive versions of binary search that uses a loop instead. For more information, check this link.
Hey guys, I encountered some problems about C++. Actually it's not the problem of language feature, otherwise it is related to kind of coding style.
OK, Let's get to the point!
I try to write the AVL Tree and want to calculate the balance factors,
and according the rule, the subtree without nodes(just a empty tree),
its height should be treated as -1. Yeah, everything thinks fine,
but when I write the code, use pointer to read Node class member,
I cannot read the nullptr BAD ACCESS, so I add lots of conditions, which makes my code look bad. Here is some parts of my code.
struct Node{
int key;
int height;
Node* left;
Node* right;
Node* parent;
Node(void);
Node(int key);
};
while((parent_node->left->height - parent_node->right->height) <= 1
||(parent_node->left->height - parent_node->right->height) >= (-1))
{
parent_node = parent_node->parent;
if(parent_node == nullptr) break;
}
The result I want is that when the parent_node's left subtree is empty,
its height will be treated as -1. And the fact is, though it's empty, its height should not exist.
So in the code I only list four cases
1. left subtree == nullptr && right subtree == nullptr
2. left subtree != nullptr && right subtree == nullptr
3. left subtree != nullptr && right subtree != nullptr
4. left subtree == nullptr && right subtree != nullptr
Then I replace the code of height part with the value -1 respectively.
It feels painful. And this condition happens in my coding time many times, I want to find the better solution.
My English is not that good, so my description maybe sort of misleading, I will appreciate it if you help me in any way.
Create a function that compute the height of a subtree including the special cases, and use that instead of accessing the ->height data member:
int heightOfSubtree(Node* tree) {
if (tree == nullptr) {
return -1;
}
else {
return tree-> height;
}
}
then your code becomes:
while((heightOfSubtree(parent_node->left) - heightOfSubtree(parent_node->right)) <= 1
||((heightOfSubtree(parent_node->left) - heightOfSubtree(parent_node->right)) >= (-1))
{
...
}
or better, you can define a member function in the Node structure such as this:
bool Node::isBalanced() {
int unb = heightOfSubtree(left) - heightOfSubtree(right);
return (unb <= 1) || (unb >=-1);
}
and your while condition becomes:
while(parent_node->isBalanced()) {
...
}
p.s.: I believe there is a logical error in your code: I am not sure the condition you are checking is correct, since it is always true (any number is either bigger than -1 or smaller than 1, for some both are true)
Unless I misunderstand, you could point to a sentinel node in stead of null as the terminator link. Set the height of the sentinel to -1 and it doesn't need to be handled differently for that part of the algorithm.
I am trying to write a remove from a binary tree function. I'm kinda lost so I'm trying to handle it case by case, starting with if the value I'm trying to remove is in the root of the BST. To test my function, I am first calling a printcontents() function that prints all the contents of the tree, then I'm calling remove(8) [8 being the value in my root at the moment), and then calling printcontents() again. The way I'm doing it is by trying to replace the root with the "right-most" value in the left side of the tree. When I call printcontents the second time, it prints the new root value correctly, but when it continues printing the contents and reaches the point where that value used to be, it has a random long number "-572......"(although i don't think the number matters) and then my program crashes. I see my root's value is being replaced, but what happens afterwards??
Here's my remove function:
void BinarySearchTree::remove(int value) {
Node* tmp = head;
Node* tmp2 = head;
if (head->data == value && head->left != NULL) {
tmp=tmp->left;
while (tmp->right != NULL) {
tmp=tmp->right;
}
while (tmp2->right->right != NULL) {
tmp2=tmp2->right;
}
if (tmp->left == NULL) {
head->data = tmp->data;
tmp2->right = NULL;
delete tmp;
}
if (tmp->left != NULL) {
head->data = tmp->data;
tmp2->right = tmp->left;
delete tmp;
}
}
It's obviously incomplete, but I'm testing it to only handle the case in which the root is removed and replaced by the right-most value in the left side of the tree (assuming there is a left side, which there is), and I feel like logically it should be working, so perhaps it is when I "delete tmp" that things go wrong. I don't know whether posting my whole program will be necessary, but if so, let me know!
May I suggest that instead of writing out for root, why don't you treat the case as it is dealt with in CLRS : That is two distinct cases.
1. When node to be deleted is a leaf
2. When node to be deleted is non-leaf(in that case replace it with inorder successor/predecessor).
The root deletion obviously falls under the second case. This is just a suggestion.
im working on an implimentation of an AVL tree, and im having problems with my recalculate height function. When i call it i pass in the root of the tree and a variable that has a value of 1. ive stepped through it, and found that once it gets to the while loop it preforms as expected but after that it returns to just ones. can you please look at it and see what i am doing wrong. I will post more code if neede, but i think just the function will provide you with enough information. Thanks
void BinaryTree::recalculate(Node *leaf, int count)
{
if(leaf == NULL)//if we are at the root
{
return;//exit the function
}
if((leaf->getLeft() != NULL))//if we are not at the end of the subtree
{
recalculate(leaf->getLeft(), count);//advance to the next node and re-enter the function
}
if(leaf->getRight() != NULL)//if we are not at the end of the right subtree
{
recalculate(leaf->getRight(), count);//advance to the next node and re-enter the program
}
else
{
while(leaf->getParent() != NULL)//calculate each subtree until we are at the root
{
leaf = leaf->getParent();//get the parent node
count++;//increment the height
if(leaf->getLeft() != NULL)//if there is an item in the left
{
leaf->getLeft()->setHeight(count-1);//sets the hight of the left child
}
if(leaf->getRight() != NULL)//if there is an item in the right
{
leaf->getRight()->setHeight(count -1);//sets the height of the right child
}
}
return;//exit the function
}
}
Your function is supposed to compute the height of each subtree of a binary tree, and save that value in the root node of that subtree. You chose to follow a recursive approach, which is the standard one. In this approach, the height of both left and right subtree must be computed first, and then the highest of both is taken for the current node.
In your implementation, you use a value named count passed in parameter to the recursive call. What is the purpose of that value, given that we need to retrieve a count from subnodes, not pass one to them?
If you:
remove that value from the recalculate parameters
have the recalculate method call itself first on both children if applicable
make the recalculate update the current node height from each subnode height
you should have it working. The following is a possible implementation based on this algorithm:
void BinaryTree::recalculate(Node *leaf) {
int count = 0;
if (leaf == NULL) {
return;
}
if (leaf->getLeft() == NULL && leaf->getRight() == NULL) {
// no child, the height is 0
setHeight(0);
return;
}
if (leaf->getLeft() != NULL) {
recalculate(leaf->getLeft());
count = leaf->getLeft()->getHeight();
}
if (leaf->getRight() != NULL){
recalculate(leaf->getRight());
count = max(count, leaf->getRight()->getHeight());
}
// include leaf in the height
setHeight(count+1);
}
If the getHeight method cannot be used, you may replace it by having recalculate return the height it computed.