Find the parent node of a node in binary search tree - c++

So I want to find the parent node of a Node in a binary tree.
Suppose that I input 30,15,17,45,69,80,7 in the tree through a text file.
The tree should be
30
15 45
7 17 69
80
And here is my code :
Node* BST::searchforparentnode(Node* pRoot, int value)
{
if(pRoot->pleft == NULL && pRoot->pright == NULL)
return NULL;
if(pRoot->pleft->value == value || pRoot->pright->value == value)
return pRoot;
if(pRoot->value > value)
return searchforparentnode(pRoot->pleft,value);
if(pRoot->value < value)
return searchforparentnode(pRoot->pright,value);
}
In this case i'm not consider if the user input the value of the Root node.
Thing is, when I input 15,17,7, all the value in the left branch of Root node, it came out ok. But when i want to find parent Node of the values from the right branch (69,80) EXCEPT for 45, the program stop running.
Any idea about what caused this error guys? Thanks for reading.

It appears that 45 does not have a left node, it is NULL, so checking pRoot->pleft->value == value is undefined behavior.
30
/ \
15 45
/ \ \
7 17 69
\
80
So you need to do a check, something like:
Node* BST::searchforparentnode(Node* pRoot, int value)
{
if(pRoot->pleft == NULL && pRoot->pright == NULL)
return NULL;
if( (pRoot->pleft != NULL && pRoot->pleft->value == value)
|| (pRoot->pright != NULL && pRoot->pright->value == value))
return pRoot;
if(pRoot->value > value)
return searchforparentnode(pRoot->pleft,value);
if(pRoot->value < value)
return searchforparentnode(pRoot->pright,value);
}
However, another thing to check for is if pRoot itself is NULL:
Node* BST::searchforparentnode(Node* pRoot, int value)
{
if (pRoot == NULL)
return NULL;
if(pRoot->pleft == NULL && pRoot->pright == NULL)
return NULL;
if( (pRoot->pleft != NULL && pRoot->pleft->value == value)
|| (pRoot->pright != NULL && pRoot->pright->value == value))
return pRoot;
if(pRoot->value > value)
return searchforparentnode(pRoot->pleft,value);
if(pRoot->value < value)
return searchforparentnode(pRoot->pright,value);
}

Your Problem is:
if(pRoot->pleft->value == value || pRoot->pright->value == value)
because before you checked if left AND right is null. In the section mentioned above, one could be null
You maybe wanna Change your code to something like this:
Node* BST::searchforparentnode(Node* pRoot, int value)
{
if(pRoot->pleft == NULL && pRoot->pright == NULL)
return NULL;
//Added check
if(pRoot->pleft && pRoot->pleft->value == value)
return pRoot;
//Added check
if(pRoot->pright && pRoot->pright->value == value)
return pRoot;
//Check also needed here
if(pRoot->pleft && pRoot->value > value)
return searchforparentnode(pRoot->pleft,value);
//Check also needed here
if(pRoot->pright && pRoot->value < value)
return searchforparentnode(pRoot->pright,value);
}
IMHO: You could also create a pointer to the parent node in each node. This could Speed up certain things a lot!

public Node nodeParent(Node root, Node n){
if(root==null){
return null;
}
Node p=root;
if(p.left==null && p.right==null ){
return null;
}
if(p.left!=null && p.key>n.key){
p=p.left;
if(p.left.key==n.key){
return p;
}
}
if(p.right!=null && p.key<n.key){
p=p.right;
if(p.right.key==n.key){
return p;
}
}
if(p.left!=null && p.right!=null ){
if(p.key<n.key){
p=p.right;
}else{
p=p.left;
}
}
return p;
}

The following code snippet should do the trick:
public Node parent(Node root, int childValue){
if(root == null)
return null;
Node left = root.left;
Node right = root.right;
if(left != null && left.value == childValue)
return root;
else if(right != null && right.value == childValue)
return root;
else if(left != null && left.value > childValue)
return parent(left, childValue);
else if(right != null && right.value < childValue)
return parent(right, childValue);
else
return null;
}

You can also write simple iterative version of this subroutine as follows:
public Node parent(Node root, int childValue){
Node parent = NULL;
while(root != NULL && root.value != childValue) {
parent=root;
if(root.value > childValue)
root = root.left;
else
root=root.right;
}
return parent

Related

Deleting current Position in a BST

Hello I currently both the working and not working solutions below for the problem
Given the root of a BINARY TREE:
Collect all the leaf nodes.
Remove all the leaf nodes.
Repeat until the tree is empty.
HOWEVER it only works when I go set the current->left || current->right to null if they are leaves
In my second example if I try to set current = NULL when it's a leaf node it doesn't update. Please help I will respond to any questions this is based on LEETCODE336
//NEED HELP ON THIS ONE NOT WORKING
class Solution {
public:
vector<vector<int>> findLeaves(TreeNode* root) {
vector<vector<int>> result;
if(root == NULL) return result;
queue<TreeNode*> bfs;
vector<int> leaves;
while(root){
bfs.push(root);
while(!bfs.empty()){
TreeNode* current = bfs.front();
bfs.pop();
if(current->left != nullptr) bfs.push(current->left);
if(current->right != nullptr) bfs.push(current->right);
if(current->left == nullptr && current->right == nullptr){
leaves.push_back(current->val);
// NOT SETTING TO NULL WHEN IT'S A LEAF NODE
current = NULL;
}
}
result.push_back(leaves);
leaves.clear();
}
return result;
}
};
class Solution {
public:
bool isLeaf(TreeNode* current){
if(current->left == NULL && current->right == NULL) return true;
else
return false;
}
vector<vector<int>> findLeaves(TreeNode* root) {
vector<vector<int>> result;
if(root == NULL) return result;
queue<TreeNode*> bfs;
vector<int> leaves;
// bfs.push(root);
while(root != NULL){
if(isLeaf(root)){
leaves.push_back(root->val);
root = nullptr;
}
else {
bfs.push(root);
}
while(!bfs.empty()){
TreeNode* current = bfs.front();
bfs.pop();
if(current->left && isLeaf(current->left)){
leaves.push_back(current->left->val);
current->left = nullptr;
}
else if(current->left){
bfs.push(current->left);
}
if(current->right && isLeaf(current->right)){
leaves.push_back(current->right->val);
current->right = nullptr;
}
else if(current->right){
bfs.push(current->right);
}
}
result.push_back(leaves);
leaves.clear();
}
return result;
}
};

What are the problems in the following code?

I have tow code about the the question Binary Tree Pruning.
this is a wrong code
class Solution {
public:
TreeNode* pruneTree(TreeNode* root) {
if(root == NULL)
return NULL;
if((root->left = pruneTree(root->left)) == NULL &&
(root->right = pruneTree(root->right)) == NULL){
if(root->val == 0){
delete root;
return NULL;
}
}
return root;
}
};
this is my passed code
class Solution {
public:
TreeNode* pruneTree(TreeNode* root) {
if(root == NULL)
return NULL;
root->left = pruneTree(root->left);
root->right = pruneTree(root->right);
if(root->left == NULL && root->right == NULL){
if(root->val == 0){
delete root;
return NULL;
}
}
return root;
}
};
I want to know what cause the difference between the two programs
In the second code, it is guaranteed that both pruneTree(root->left) and pruneTree(root->right) are called, because those are two separate expressions.
root->left = pruneTree(root->left);
root->right = pruneTree(root->right);
In the first code you have:
(root->left = pruneTree(root->left)) == NULL &&
(root->right = pruneTree(root->right)) == NULL
The difference here is that pruneTree(root->left) and pruneTree(root->right) are in one expression, so they might (and this case the do) depend on each other.
If (root->left = pruneTree(root->left)) == NULL evaluates to false then the parte after the && does not need to be evaluated, because the complete expression can't become true anymore.

Is given binary tree is binary search tree or not

I have written a function that returns true if given binary tree is binary search tree else returns false.
bool IsBst(node* root)
{
if(root->left == NULL && root->right == NULL)
{
return true;
}
if(root->left->data <= root->data && root->right->data > root->data)
{
return (IsBst(root->left) && IsBst(root->right))
}
else
{
else false;
}
}
Is my function right?
Will this function return right answer?
I have doubt in case of if left child is null then what will this comparison root->left->data<=root->data return?(If there is NULL)
Help me to improve this!
Thanks in advance!
It should be something like
bool IsBst(const node* root, node* minNode = nullptr, node* maxNode = nullptr)
{
if (root == nullptr) {
return true;
}
if (minNode != nullptr && root->data < minNode->data)
{
return false;
}
if (maxNode != nullptr && maxNode->data < root->data)
{
return false;
}
return IsBst(root->left, minNode, root)
&& IsBst(root->right, root, maxNode);
}
If you're using C++ 17 and above, you can do it even more elegantly by using an optional class. Hence, you don't need to do nullptr checks for min and max:
bool checkBST0(const Node* root, const std::optional<int>& min, const std::optional<int>& max) {
if (root != nullptr) {
const auto data = root->data;
if ((min.has_value() && min >= data) ||
(max.has_value() && max <= data)) {
return false;
}
std::optional<int> opt(data);
return checkBST0(root->left, min, opt) && checkBST0(root->right, opt, max);
}
return true;
}
Initially, you should call this method with an optional without any value:
std::optional<int> emptyOptional;
return checkBST0(root, emptyOptional, emptyOptional);
Nope, it's not right. It would fail on this tree:
3
\
\
5
And it would give a wrong answer on this one:
4
/ \
/ \
/ \
2 6
/ \ / \
1 9 0 8
A BST is defined as a tree, whose each internal node stores a key greater than all the keys in the node’s left subtree and less than those in its right subtree (see the Wikipedia article).
So it's not enough for a 1-2-9 left subtree in my example to have a left node value less than it's root (1<2) and the right node greater than it (9>2). It should also satisfy the condition that all its nodes have values less than 4, the value in the whole tree's root.
Here is an example in C I gave in the answer to the question Pseudo code to check if binary tree is a binary search tree - not sure about the recursion:
// Test a node against its closest left-side and right-side ancestors
boolean isNodeBST(NODE *lt, NODE *node, NODE *rt)
{
if(node == NULL)
return true;
if(lt != NULL && node->key <= lt->key)
return false;
if(rt != NULL && node->key >= rt->key)
return false;
return
isNodeBST(lt, node->left, node) &&
isNodeBST(node, node->right, rt);
}
boolean isTreeBST(TREE *tree)
{
return isNodeBST( NULL, tree->root, NULL);
}

Why does this tree function give me "status_access_violation"?

I'm trying to make a function that tells if a Tree is "complete" or not, so basically if every subtree ends with two leaves and has no void subtrees. But when I run the code I get the following error:
[main] C:\Users\GIT\Desktop\dev\a.exe 1000 (0) handle_exceptions: Exception: STA
TUS_ACCESS_VIOLATION
[main] a 1000 (0) handle_exceptions: Dumping stack trace to a.exe.core
what should I do to solve this? Here's the code:
struct Tree {
int n;
Tree *left,*right;
Tree(): left(NULL),right(NULL) {}
};
bool isFoglia(Tree* root) {
return root->right == NULL && root->left == NULL;
}
bool isMinimum(Tree* root) {
return isFoglia(root->right) && isFoglia(root->left);
}
bool isCompleto(Tree* root) {
if(root == NULL || isFoglia(root) || isMinimum(root)) return 1;
if(isFoglia(root->right) && root->left == NULL) return 0;
if(isFoglia(root->left) && root->right == NULL) return 0;
return isCompleto(root->right) && isCompleto(root->left);
}
EDIT: I have the same error when I try to run this function that tells the maximum sum of a tree that you can get summing its elements from the top to the bottom, choosing each time which subtree to go:
int maxSum(Tree *root) {// max is an int function that returns the a if a>=b or b if b>a
if(isMinimum(root)) {
return max(root->n+root->right->n,root->n+root->left->n);
}
else {
return max(root->n+maxSum(root->right),root->n+maxSum(root->left));
}
}
Consider, for example, a tree that is severely unbalanced to the point that it is a linked list, i.e.
o
/ \
/ NULL
o
/ \
/ NULL
o
/ \
NULL NULL
And run this on the root node.
Then:
// root is not NULL, isFoglia(root) is not true, so we descend into
// isMinimum(root)
if(root == NULL || isFoglia(root) || isMinimum(root)) return 1;
whereupon in isMinimum(root),
return isFoglia(root->right) && isFoglia(root->left);
descends into isFoglia(root->right), which is isFoglia(nullptr), where finally
return root->right == NULL && root->left == NULL;
tries to take the left and right members of a null pointer.
In fact, this happens for any node that has a left child but not a right one, and further down,
if(isFoglia(root->left) && root->right == NULL) return 0;
exhibits the same problem for nodes that have a right child but not a left one. A simple fix would be to make isFoglia safely callable on null pointers, such as
bool isFoglia(Tree* root) {
return root != NULL && (root->right == NULL && root->left == NULL);
}

Binary Tree (not search) max function

I'm getting a segmentation fault with my code and I'm not sure why. I'm trying to find the max value in a regular binary tree that is not ordered.
tnode<int> *maxT(tnode<int> *t)
{
if (t == NULL) return NULL;
tnode<int> *left = maxT(t->left);
tnode<int> *right = maxT(t->right);
if (left->nodeValue > right->nodeValue)
{
return maxT(left);
}
if (left->nodeValue < right->nodeValue)
{
return maxT(right);
}
}
The fundamentals of the algorithm are fairly straight forward. Because the tree is unordered, all nodes must be visited, with the following preconditions:
A null node pointer results in null as an answer.
Else a node with no children results in the current node
Else result is the max of the node compared to the max of its children.
Given that, I'm pretty sure this is what you're trying to do:
template<typename T>
tnode<T>* maxT(const tnode<T>* t)
{
if (!t)
return nullptr;
tnode<T>* lmax = maxT(t->left);
tnode<T>* rmax = maxT(t->right);
tnode<T>* cmax = (lmax && rmax)
? ((rmax->nodeValue < lmax->nodeValue ? lmax : rmax))
: (lmax ? lmax : rmax);
return (!cmax || (cmax->nodeValue < t->nodeValue) ? t : cmax);
}
tnode<int> *maxT(tnode<int> *t)
{
if (t->right == NULL && t->left == NULL) //leaf node
return t->nodeValue;
else if (t->right == NULL) //no right subtree
return MAX(t->nodeValue, maxT(t->left))
else if (t->left == NULL) //no left subtree
return MAX(t->nodeValue, maxT(t->right))
else
return MAX(maxT(t->right), maxT(t->left));
}
In your case, what happens if a node doesn't have a right or left child. Then either node->right == NULL or node->left == NULL. Yet you are trying to access left->nodeValue or right->nodeValue.