Check if 2 nodes are adjacent in binary tree using linkedlish C++ - c++

Sorry for the bad English.
I'm creating a binary tree project by using a linked list in C++. And Im trying to make a boolean method to check if 2 nodes are adjacent or not?
And I'm trying to use the recursion method as I'm using the linked list to do this, but it seems I did it wrong.
Here is how I declare the Node
Struct Node{
string name;
int data;
Node *right, *left;
}
And here is how I declare the checking function:
bool checkadjacent(node* Node, string& u, string& v) {
if(!Node){
return false;
}
if (Node && Node->right) {
string current = Node->name;
string right = Node->right->name;
if (current == u && right == v)
return true;
else if (current == v && right == u)
return true;
}
if (Node && Node->left) {
string current = Node->name;
string left = Node->left->name;
if (current == u && left == v)
return true;
else if (current == v && left == u)
return true;
}
if (Node->left){
if(checkadjacent(Node->left, u, v)){
return true;
}
}
if (Node->right){
if(checkadjacent(Node->right, u, v)){
return true;
}
}
}

Note: "it seems I did it wrong" is not an explanation of how your code fials. Always describe what your code is SUPPOSED to do and what it is ACTUALLY doing.
Having said that, I'm assuming your code does not compile. I put together a (possibly non-comprehensive) list of errors and other problems with your code, aswell as a corrected version of your code. However, I would advise you to watch some tutorials about C++ (or C if you want, since your code is basically C code), because your code shows some serious misunderstandings and neglection. Apart from that, your basic idea seems correct except for the last bullet point in the following list.
List of problems:
It's struct not Struct (capitalization matters in C++). (This is necessary for correctness/syntax)
In the declaration of Node you capitalize the name of the Node. Later, you call it node and instead capitalize the name of the object which instantiates Node (to be consistent, I called the struct Node and it's instantiation node). (This is necessary for correctness/syntax)
First you check whether Node is actually pointing to a struct: if(!Node). This is good, but there is no need to check the same thing again later: if (Node && Node->right) and if (Node && Node->left) just leave out the first part in both conditions: if (node->right) and if (node->left). (This is for style)
Then you can also leave out the 3rd and 4th if statements and put their block into the 1st and 2nd if blocks respectively. (This is for style)
Do not declare the variables current, right and left inside the if blocks, instead declare them at the beginning of the function. (This is for style)
For the algorithm to work you have to return false if none of the if none of the if statements are executed (this is a guess; I did not test this and you WILL have to try that yourself). (This is necessary for correctness/semantics)
Here's the full code (note that I did NOT test this code, as your problem was clearly faulty syntax and not algorithm design.
bool checkadjacent(Node* node, string& u, string& v) {
string current, left, right;
if (!node) {
return false;
}
if (node->right) {
current = node->name;
right = node->right->name;
if (current == u && right == v)
return true;
else if (current == v && right == u)
return true;
// recursion
if (checkadjacent(node->right, u, v)) {
return true;
}
}
if (node->left) {
current = node->name;
left = node->left->name;
if (current == u && left == v)
return true;
else if (current == v && left == u)
return true;
// recursion
if (checkadjacent(node->left, u, v)) {
return true;
}
}
return false;
}
Also note:
I did not change the definition of Node.
Apart from string your code is just C code. In C++ you have the possibility to create a class for the binary tree which would be a lot more readable.
There are no linked lists in any parts of the code above (neither in the code you posted). The fact that the node have left and right child nodes, does not make it a linked list (in particular it's not a list because it is not 1-dimensional).
Again, I did NOT test this code; you can do that yourself.

Related

Finding a node in a cloned tree using DFS

I am trying the LeetCode problem1379. Find a Corresponding Node of a Binary Tree in a Clone of That Tree:
Given two binary trees original and cloned and given a reference to a node target in the original tree.
The cloned tree is a copy of the original tree.
Return a reference to the same node in the cloned tree.
Note that you are not allowed to change any of the two trees or the target node and the answer must be a reference to a node in the cloned tree.
This is my code:
class Solution {
public:
TreeNode* ans = NULL ;
TreeNode* getTargetCopy(TreeNode* original, TreeNode* cloned, TreeNode* target) {
// if(cloned == NULL){return cloned ;}
if(cloned == NULL){return cloned ;}
// if(cloned->val == target->val){
// return cloned ;
// }
if(cloned->val == target->val){
ans = cloned ;
}
// return getTargetCopy(original,cloned->left ,target) ;
// return getTargetCopy(original,cloned->right,target) ;
getTargetCopy(original,cloned->left ,target) ;
getTargetCopy(original,cloned->right,target) ;
return ans ;
}
};
The commented out part was my initial code but it returned wrong answer
Your input
[7,4,3,null,null,6,19]
3
Output
null
Expected
3
Help me understand the problem in my code
Some issues:
With these (now commented) lines:
return getTargetCopy(original,cloned->left ,target) ;
return getTargetCopy(original,cloned->right,target) ;
...execution would never get to that second line, as the first line would end the function.
These (now commented) lines:
if(cloned->val == target->val){
return cloned ;
}
...are fine: once you have found the target value, there is no need to do anything else in this function, and so it is fine to return the node. This is better than setting ans to that node and still make some (unnecessary) recursive call(s).
What is missing here is getting the value from the first recursive call, and deciding whether that call successfully found the target value or not. In case it found it, there is no more need for a second recursive call. In case it didn't find it, then the second recursive call is needed. Finally, the return value you get from either recursive call, should be returned back as the current function's return value.
So:
class Solution {
public:
TreeNode* getTargetCopy(TreeNode* original, TreeNode* cloned, TreeNode* target) {
if (cloned == nullptr || cloned->val == target->val) {
return cloned;
}
TreeNode *ans = getTargetCopy(original,cloned->left ,target) ;
if (ans != nullptr) {
return ans;
}
return getTargetCopy(original,cloned->right,target) ;
}
};

Recursive function to return last node of a heap

I am trying to return the last node of a binary heap (implemented with pointers, not an array). Here, 'last' means the bottom-most node starting from the left in this case without two children, actually the node where I am supposed to append the new node to. The insert function will bind data to a new node for insertion, then call this function to return the last node, so I can add the new node either left of right depending on the child nodes present, or not.
The problem is that the right side of the tree is always empty, and never gets past the height after root's. Seems to stick on the leftmost side, because it reaches first the exit condition from every recursion call starting from left.
The recursive function checks first the node, returns 0 if no child, returns 1 if only left child and returns 2 in case of a node having two children. Here is the function :
template<typename T>
node<T> * heap<T>::find_insert_pos (node<T> *x, int &res) {
if(find_insert_poshelper(x, res) == 0) return x;
else if(find_insert_poshelper(x, res) == 1) return x;
else {
node<T> *a = find_insert_pos(x->left, res);
if(find_insert_poshelper(a, res) != 2) return a;
else return find_insert_pos(a, res);
node<T> *b = find_insert_pos(x->right, res);
if(find_insert_poshelper(b, res) != 2) return b;
else return find_insert_pos(b, res);
}
}
I've tried to figure it out, but insertion still goes wrong. The other functions used into insertion are more than triple checked.
(By the way, 'res' is passed by reference always in the chunk of code)
I have changed the logic behind the function. Instead of only validating for children per node, I validate now if the node evaluated had children, if it does then I validate one step further each of those children, left and right, to see if any of those grand-children have children themselves.
If they don't, I will loop this for the next level following the root level 0, jumping to level 1 and so on, until one of the children nodes does not contain two children, and returning x.left or x.right, depending the case.
-- Final edit --
Hard to think about a MRE since it was more about logic. The question was posted by someone in need of practice with recursion, and it happened. All the logic changed, even for sub-functions.
But it will be required to manually assign and narrow down until three levels are full (full meaning having two children) before calling this operation, which is checking three levels down. Having this done nicely I get a beautiful heap.
I can show an attempt to a MRE of how I implemented it to be able to find the bottom node to append a new node to, but not pure since I don't put the code from the 'insert' function, which is part iterative (first three levels) and part recursive (that was the original question, to find the parent node for the new node to insert). How the insert operation goes, I create a new node dynamically and then I search for the parent node where I need to append new data to (the iterative part starts here until the 8th node of the tree is reached, path similar to BFS), then when the position is retrieved (that is, the pointer itself), I test whether for left or right insertion, as by the rules of the heap. Starting at the 8th node, the value of the parent node is set recursively as follows :
First the recursive function itself :
node * function_a (node *x, int &res) {
node *temp = function_b (x, res);
if(temp != ptr_null) return temp;
else {
if(x->L != ptr_null) function_a (x->L, res);
if(x->R != ptr_null) function_a (x->R, res);
return temp;
}
}
A sub-function :
node * function_b (node *x, int &res) {
node *a = x->L;
node *b = x->R;
int aL = function_c (a->L, res);
int aR = function_c (a->R, res);
int bL = function_c (b->L, res);
int bL = function_c (b->R, res);
if(aL != 2) return a->L;
else if(aR != 2) return a->R;
else if(bL != 2) return b->L;
else if(bR != 2) return b->R;
else return ptr_null;
}
And another :
int & function_c (node *x, int &res) {
if(x->L == ptr_null && x.R == ptr_null) return res = 0;
else if(x->L != ptr_null && x->R == ptr_null) return res = 1;
else return res = 2;
}
Since this is checking 3 levels down from x defined (in this case from the root) in function_a, I can't make it 100% recursive that way or I will get a segmentation fault. How can I improve my algorithm ?

how to extract a tree iteration in C++

I've been repeating a chunk of similar code for several times. This how it's like in pseudo code:
stack.push(root)
while stack size > 0
node = stack.pop()
if condition_1
if node is leaf
if condition_2
// do something,
// for example, push node into a vector and return the vector
else
stack.push(children of node)
or like this:
stack.push(root)
while stack size > 0
node = stack.pop()
if condition_1
if node is leaf
if condition_2 // or no condition_2 and return true directly
return true
else
stack.push(children of node)
return false
The difference between this two snippets is that the first one iterates all leaf nodes, while the second one has a break logic. And usually the main work I do is condition_2 and what's in its scope. Other lines are just repeating themselves.
So is there a way to extract this kind of tree iterating loop, in C++ or any other language?
As I understood correctly, you want to have a generic version of this algorithm.
I don't know which parts you do want to make generic, so here is a very simple solution where everything is generic.
template <class NodeType, class TraversalPredicate, class LeafPredicate,
class TerminalPredicate, class ChildrenGetter>
bool findIf(NodeType *root, TraversalPredicate shouldTraverse,
LeafPredicate isLeaf, TerminalPredicate shouldFinish,
ChildrenGetter getChildren) {
std::stack<NodeType *> stack;
stack.push(root);
while (not stack.empty()) {
auto *node = stack.top();
stack.pop();
if (not shouldTraverse(node))
continue;
if (isLeaf(node)) {
if (shouldFinish(node)) {
return true;
}
} else {
for (auto *child : getChildren(node)) {
stack.push(child);
}
}
}
return false;
}
I hope that is what you were looking for!

Equality operator for linked lists C++

I am trying to create a linked list class and I'm having trouble determining how to check the equality of two lists using the operator== (equality operator). How would I go about going through each node and checking if elements within them are equal in their respective positions?
bool List::operator==(const List& list2) const {
if(mySize != list2.mySize){
return false;
}
if(myFirst == list2.myFirst){
if(myFirst == NULL){
return true;
}
Node * nPtr1 = myFirst;
Node * nPtr2 = list2.myFirst;
while(nPtr1 != NULL){
//what can I do here to check the equality of each element in both lists?
}
}
}
According to your code, myFirst is a pointer, so the following is wrong:
if(myFirst == list2.myFirst)
Unless a node is equal to another node ONLY if it is the same node (pointer wise).
You have a special case when the lists are empty which you kind of captured:
if(myFirst == nullptr && list2.myFirst == nullptr)
{
return true;
}
That would be the empty case.
Otherwise, you got the while properly, and if your items (Node) can simple be compared you would do:
p = myFirst;
q = list2.myFirst;
while(p != nullptr)
{
if(*p != *q) // this is what you're asking about, right?
{
return false;
}
p = p->next; // not too sure how you have a Node separated from the List
q = q->next; // and check next/previous items...
}
return true;
Note that if nodes can only be equal if they have the same pointer then the compare becomes:
if(p != q) // this is a test of pointers instead of objects
P.S. Someone mentioned using a recursive algorithm. That's an idea and conceptually it's great. When using such in the real world, though, you notice that it can be (much) slower. It has to very heavily use the stack and with very large lists, it could break your software.
while(nPtr1 != NULL){
if(nPtr1 != nPtr2){
return false;
}
nPtr1=nPtr1->next;
nPtr2=nPtr2->next;
}
return true;
But this is the way to check if the two lists are identical (nPtr1 and nPtr2 are pointing to the same list). If you really want to compare lists by content you have to compare content like:
if(nPtr1->content != nPtr2->content)
and also change your first pointer check:
if(myFirst->content == list.myFirst->content)

How to add children to BST

I'm trying to make/create a BST, but it doesn't seem to work properly. I've literally been sitting here for hours trying to figure out what's going on. It's gotten to the point where I've drawn a million diagrams to figure this out, yet my code fails me. I need to pass in a root node into a function. Then I need to traverse through the tree until I find that the parent string parameter of the function coincides with the tree parent node's string. If I do find it, I must insert the string into the parent, and create two new children from that parent. If I can't find the parent string, then I return false.
bool insertNode(BSTNode *n, char* parentQ, char* leftQ, char* rightQ)
{
if(n->Q == parentQ)
{
n->left = new BSTNode(leftQ);
n->right = new BSTNode(rightQ);
return true;
}
else if(n->Q != parent)
{
insertNode(n->left,parentQ,leftQ,rightQ);
insertNode(n->right,parentQ,leftQ,rightQ);
}
else
return false;
}
Also I need to make another method that takes the tree that I have established, and corrects the strings. So the method modifies the parent string, if found, and looks at its children, if found, and replaces those strings with those found in the method parameters. It's sort of like adding a subtree without screwing the entire tree up. Thanks in advance!
bool changeNode(BSTNode *n,char* parentQ, char* leftQ, char* rightQ)
{
if(n->Q == leftQ)
{
n->Q = parentQ;
n->left = new BSTNode(leftQ);
n->right = new BSTNode(rightQ);
return true;
}
else if(n->Q == rightQ)
{
n->Q = parentQ;
n->left = new BSTNode(leftQ);
n->right = new BSTNode(rightQ);
return true;
}
else if(n->Q != leftQ)
{
changeNode(n->left,parentQ,leftQ, rightQ);
}
else if(n->Q != rightQ)
{
changeNode(n->right,parentQ,leftQ,rightQ);
}
return false;
}
You didn't even mention what the error was, example input / expected output, but shouldn't you be checking whether the current node actually has a left and right child, before calling the function with those children?
else if(n->Q != parentQ) // <--- you have a typo in this line, "parent"
{ // (and you don't even need the 'if')
insertNode(n->left,parentQ,leftQ,rightQ);
insertNode(n->right,parentQ,leftQ,rightQ);
// in this case you return nothing! corrupted return value
}
^ this seems very error-prone, especially null-pointer. You should turn it into something like:
else
{
if(n->left != NULL) // take a look at nullptr if you have C++11
if(insertNode(n->left,parentQ,leftQ,rightQ)) return true;
if(n->right != NULL)
if(insertNode(n->right,parentQ,leftQ,rightQ)) return true;
return false;
}
Otherwise your true return never gets propagated back beyond the first return, so then you're always returning false unless in the only case where the root of the tree is actually the node you were searching for.
Also, do not compare two char arrays using ==, unless n->Q is actually an std::string. You should use if(strcmp(n->Q, parentQ) == 0) otherwise.
Your second piece of code, however, is just a mess. You need to take a better look at what exactly will be happening on your else if's and see if it is actually doing what you want (hint: it isn't), as you currently only execute at most 1 of the code blocks, even if more than one condition is true.