Recursive tree, printing ancestor nodes - c++

this is study material, not homework:
I have the following tree, I need to write an algorithm that finds a given number and returns an integer indicating how many nodes it visited before finding it. It should also print the values of all "ancestor" nodes relative to the node in which the value was found (in no particular order, and it is assumed that the given value is always present)
10
/ \
20 60
/ \
50 30
\
40
If the given value is 40 it should return 4 and print 30, 20, 10 (in any order)
I've written the following solution, and I think it works, but I'm concerned about the print.
void foobar (ty_tree *tree, int value, int & count){
if (tree !=null) {
if (tree->value != value) {
count++;
foobar (tree->left, value, count);
foobar (tree->right, value, count);
cout << tree->value;
}
}
}

Good approach ! But to print the ancestors (i.e.parent nodes) you need to know in your recursive function if the value was found in one of the child:
bool foobar (ty_tree *tree, int value, int & count) {
if (tree !=nullptr) { // oops: NULL or nullptr, the latter is better
if (tree->value != value) {
count++;
if (foobar (tree->left, value, count) ||
foobar (tree->right, value, count) ) // if found below
cout << tree->value<<endl; // print the node, because it's on the path
}
else {
cout << "Found: "<<tree->value<<endl; // print the value found
return true; // and inform caller that he can print as well.
}
}
else return false; // reached a leaf without finding
}
As some doubts were expressed in the comments, here an online demo

Related

Binary Search Tree using the most frequent node to print out certain statements

I have a binary search tree that I want to use to be able to give a certain output for the most common node but i'm having a hard time doing that. I already have code that prints out how many times the node is entered into the tree and which one is the most frequent but I don't know how to write the if statement that would compare the values and be able to output certain things if one was greater than the other. I have been working on this for hours and just can't get the right output please help.
So if i have more a's i want that to have a certain output or if i have more b's that should have a different output etc.
For starters, change the node definition to look more like the one below. This definition initializes all the struct's fields to their zero values. For me, this change prevented an access violation at the line if (p->data == q->data), probably because the next pointer was not initialized to nullptr.
struct node {
char data{};
int count{};
node *left{};
node *right{};
int height{};
node *next{};
};
Similarly, my compiler warns about an uninitialized variable res. So that too should be initialized like char res{};.
This seems to work for the maxChar function. The second overload calls the first overload, which calls itself recursively. They don't have to have the same names.
char maxChar(node *node, int max, char res) {
if (node != nullptr) {
res = maxChar(node->left, max, res);
if (node->count > max) {
max = node->count;
res = node->data;
}
res = maxChar(node->right, max, res);
}
return res;
}
char maxChar(node *node) {
int max{};
char res{};
return maxChar(node, max, res);
}
Then if needed, you could do something like this:
char maxCh = maxChar(root);
switch (maxCh) {
case 'A': cout << "Your recommendation is A." << endl;
break;
case 'B': cout << "Your recommendation is B." << endl;
break;
}

C++: Odd sum of values of the binary tree

Trying to write a program which will sum all odd elements of binary tree. But my code (function odd_sum) returns only first odd element. Where is my mistake?
/*Creating abd printing tree*/
int odd_sum(node *root)
{ if (root == NULL) return 0;
return root->info % 2 != 0 ? root->info:0 + odd_sum(root->left) +
odd_sum(root->right);
}
int main()
{
int k,sum,h=0;
node *der=tree();
if (!der) printf ("No tree");
else
{
node *root=der,*qwe=der;
sum=odd_sum(root);
print_tree(der,h);
printf ("\nOdd sum :%d\n\n\n",sum);}
return 0;
}
If you meet an odd value in the tree you are just returning its value without branching down the tree, that's why you get only the first odd number.
The corrected version of your code is on the line of:
int odd_sum(node *root){
if (root == NULL) {
return 0;
}
else {
int add = 0;
if(root->info % 2 != 0) add = root->info;
return add + odd_sum(root->left) + odd_sum(root->right);
}
}
You need to traverse down the tree and whenever you find the node with odd value you can update your Sum variable.
void oddSum(node *root, int &Sum){
if(!root)
return;
if((root->val) & 1)
Sum += root->val;
oddSum(root->left, Sum);
oddSum(root->right, Sum);
}
Pass the root and Sum variable with reference, at the end of the recursion, you will find the sum of the odd values of tree stored in Sum.

storing the number of certain leaves in the nodes of the binary search tree(optimization)

I have to count for each subtree the number of leaves with even label whose father has odd label and the number of leaves with odd label whose father has even label and store that number in the subtree's node.
For example : this tree (the output is on the left).
This is my code
struct node {
int label;
node*right;
node*left;
int L; //i use this to store the number of leaves
};
void addnodeBST(node*&tree, int l) { //adds a node
if (!tree) {
tree = new node;
tree->label = l;
tree->right = tree->left = 0;
tree->L = 0;
return;
}
if (l < tree->label)
addnodeBST(tree->left, l);
if (l > tree->label)
addnodeBST(tree->right, l);
}
int counter(node*tree, int x) {
if (!tree)
return 0;
if ((!tree->left && !tree->right) && ((x % 2 == 0 && tree->label % 2 ==
1) || (x % 2 == 1 && tree->label % 2 == 0)))
return 1;
return counter(tree->left, tree->label) + counter(tree->right, tree-
>label);
}
void updateNode(node*tree) {
if (!tree)
return;
tree->L = counter(tree, 0);
if (!tree->right && !tree->left)
tree->L = 0;
updateNode(tree->left);
updateNode(tree->right);
}
It works, what is not fine are the functions "counter" and "updateNode" together.
"Counter" counts the number of leaves that are to be counted.
"UpdateNode" utilizes "counter" to count and then store the number of leaves in each subtree into L (which i defined in the struct).
This way i have a recursive function into another recursive function and i visit each node multiple times.
How can i optimize my code?
This way i have a recursive function into another recursive function and i visit each node multiple times.
The part before andmakes your code ugly, but the real devil lies in how you chose to traverse the tree.
In your updateNode function, the value of L for a node is simply sum of it's left and right subtree. So instead of calling them at the end of your function (preorder) like you do now, if you call them earlier (postorder); now you know their L and instead of calling counter, you simply add them up. You visit every node exactly once.
You can completely delete your counter function.
Here is modified code (comments explain the code) :
//helper to check leaves, null nodes are not leaf
bool isLeaf(node* tree){
return (tree && (!tree->right) && (!tree->left));
}
//change return type to catch child node's 'L' value through recursive calls
int updateNode(node*tree) {
if (!tree) return 0; //0 for null, for example tree->right for '24'
if (isLeaf(tree)) tree->L = 0; //All the leaves
int a,b;
//find 'L' for left child into a
if(isLeaf(tree->left)){
if(tree->left->label%2!=tree->label%2) a=1; //this will be true for '24' and '10'
else a=0;
}
else a = updateNode(tree->left);
//Now find 'L' for right child into b
if(isLeaf(tree->right)){ //this will be true for '10'
if(tree->right->label%2!=tree->label%2) b=1;
else b=0;
}
else b = updateNode(tree->right);
//combine them
tree->L = a+b; //this will be true for '20'
return tree->L; //return for parent's sake
}
And driver to run it:
void inorder(node* tree){
if(!tree) return ;
inorder(tree->left);
printf("%d : %d %d\n",tree->label,tree->L,isLeaf(tree) );
inorder(tree->right);
}
int main(int argc, char const *argv[])
{
node* tree = 0;
addnodeBST(tree,20);
addnodeBST(tree,10);
addnodeBST(tree,24);
addnodeBST(tree,17);
addnodeBST(tree,23);
addnodeBST(tree,5);
updateNode(tree);
inorder(tree);
return 0;
}
And..your addnodeBST will fail for equal values. Change the second if to else.

Recursive method to find value in linked list

template<class Type>
int StringList<Type>::find(Type value)
{
int count = 0;
// Start of linked list
Node<Type> *current = head;
// Traverse list until end (NULL)
while (current != NULL)
{
// Increase counter if found
if (current->data == value)
{
count++;
}
// If not, move to the next node
current = current->next;
}
cout << value << " was found " << count << " times" << endl;
return 0;
// same function but using Recursive method
// Start of linked list
Node<Type> *current = head;
int count = 0;
// Thinking this is the base case, since its similar to the while loop
if (current == NULL)
{
return 0;
}
// same as the while loop, finding the value increase the count, or in this case just prints to console
if ((current->data == value))
{
cout << "Found match" << endl;
return 0;
}
else
{ // If it didnt find a match, move the list forward and call the function again
current = current->next;
return find(value);
}
}
the function is supposed to find the value searched and return how many times that certain value was in the linked list.
how can I turn the first method, which uses a while loop, into something that does the same thing but uses recursion?
For starters instead of the return type int it is better to use an unsigned type like for example size_t
You can use the following approach. Define two methods. The first one is a public non-static method find defined like
template<class Type>
size_t StringList<Type>::find( const Type &value ) const
{
return find( head, value );
}
The second one is a private static method with two parameters defined like
template<class Type>
static size_t StringList<Type>::find( Node<Type> *current, const Type &value )
{
return current == nullptr ? 0 : ( current->data == value ) + find( current->next, value );
}
In order to use recursion, you will need to change the signature of your find function (or add a new function with the different signature) to take a node pointer as a parameter:
template<class Type>
int StringList<Type>::find(Type value, Node<Type> *where)
{
if (where != nullptr)
{
// Do things
}
}
Then, when you traverse the list, you pass where->next to the function. Once you hit the end of the list, with a nullptr value, the stack unrolls.
A key aspect of recursion as that the function or method being used only has to process a single node of your container. It then calls itself with the next node to be processed until there are no more nodes. In order to make this work, that function needs the node to process as a parameter, which is where your current code runs into problems.
Keep in mind that the elegance and simplicity of recursion is not free. Every call that a method makes to itself eats up stack, so a sufficiently large container can result in a crash if the stack for your process is depleted.
how can I turn the first method, which uses a while loop, into
something that does the same thing but uses recursion?
The following would be closer to what you want. You really should provide an [MCVE] ... the lack of which forces many guesses and assumptions about your code.
// It looks like StringList is a class (I ignored template issues),
// and it appears that your class holds 'anchors' such as head
// StringList is probably the public interface.
//
// To find and count a targetValue, the code starts
// at the head node, and recurses through the node list.
// I would make the following a public method.
//
int StringList::findAndCountTargetValue(int targetValue)
{
int retVal = 0;
if (nullptr != head) // exists elements to search?
retVal = head->countTV(targetValue); // recurse the nodes
// else no match is possible
return(retVal);
}
// visit each node in the list
int Node::countTV(const int targetValue)
{
int retVal = 0; // init the count
if (data != targetValue) // no match
{
if(nullptr != next) // more elements?
retVal += next->countTV() // continue recursive count
}
else
{
std::cout << "Found match" << std::endl; // for diag only
retVal += 1; // because 1 match has been found
if(nullptr != next) // more elments
retVal += next->countTV(); // continue recursive count
}
return (retVal); // always return value from each level
}

Print first 20 nodes of a tree

Ok so I'm working on my first tree and I need to adjust it to print out the first 20 nodes of a tree. My Inorder, Preorder, and Postorder full prints are working flawlessly but I cannot seem to figure out how to get the print to stop after the first 20 nodes printed.
void printino(tnode *c, int cnt)
{
if (c == NULL)
return;
if (cnt < 20)
{
cnt++;
printino(c->lchild, cnt);
cout << c->val << " " << cnt << endl;
printino(c->rchild, cnt);
}
}
is what I did in attempt to stop the print after 20 nodes. My count is clearly not working as it still prints every node. I added a line to cout my count and its not working correctly.
Sample output is as follows:
17 7
18 8
19 6
20 5
21 7
22 6
with the first number being the value of the node and the 2nd number being my count. I'm going to be honest and say I'm not really sure what I'm counting or why/when/how its resetting.
From what I can tell, its counting the depth of the node in the tree? not how many nodes have been printed?
Any assistance would be great!
In simplest terms, you can do something like below :-
void printInorder(tnode *root, int k, int cnt)
{
if(root != NULL)
{
printInorder(root->left, k, cnt);
if(cnt < k)
{
cout << root->data;
++cnt;
}
printInorder(root->right, k, cnt);
}
}
Change the type of param "int cnt" to "int & cnt", using reference param
Arguments can be passed to a function by two methods, They are. pass by value; pass by reference. If pass by value, the value changed inside the function never affect the real value outside the function. So if you wanna to count the size of printed nodes, you should use method pass by reference.
move cnt++ to after printing left son:
void printino(tnode *c, int cnt)
{
if (c == NULL)
return;
if (cnt < 20)
{
printino(c->lchild, cnt);
cnt++;
cout << c->val << " " << cnt << endl;
printino(c->rchild, cnt);
}
}