-2

I want to get one of the leaf nodes as an output(just one of them).But not the same leaf node for everytime...I want to get a different leaf node for everytime with the help of "srand" function...I tried to solve this problem using array but could not be successfull.Then I decided to go on with a different algorithm with the help of a friend who commented on this post...
I am generating a random integer if it is odd I go on with the left child ,vice versa... But get the same node as an output can not solve the problem...

void LeafNodesRandomly(BST*p)
{
int i;
srand(time(NULL));
i=rand()%2;//Generating a random int for determining to go right or left of a current node
//printf("%d\t",i);

while(p->left !=NULL || p->right !=NULL)
{
    if(p->left==NULL && p->right!=NULL)//Just have a right child
    {
        p=p->right;
        if(p->left==NULL && p->right==NULL)//If the right child is a leaf node print and break
        {
            printf("%d\t",p->data);
            break;
        }
    }

    if(p->left!=NULL && p->right==NULL)//Just have a left child
    {
        p=p->left;
        if(p->left==NULL && p->right==NULL)//If the left child is a leaf node print and break
        {
            printf("%d\t",p->data);
            break;
        }
    }

    if(p->left!=NULL && p->right!=NULL)// The current node have two children
    {
        if(i==0)
        {
            p=p->left;
            if(p->left==NULL && p->right==NULL)// If the randomly generated int is "0" go left child and if the left child is a leaf node print and break
            {
                printf("%d\t",p->data);
                break;
            }
        }

        if(i==1)
        {
            p=p->right;
            if(p->left==NULL && p->right==NULL)// If the randomly generated int is "1" go right child and if the right child is a leaf node print and break
            {
                printf("%d\t",p->data);
                break;
            }
        }
    }



 /*if(i==0) // If you open this if and else block you can randomly reach some of other leafs!!!
    {
        i=i+1;
    }
    else
        i=i-1;
    } */
    }

}


This is my main function:

I have 13 or NULL as an output

#include <stdio.h>
#include <stdlib.h>
#include<time.h>
#include "bst.h"

int main()
{
    BST*root=NULL;

    root=AddNode(root,9);
    root=AddNode(root,11);
    root=AddNode(root,7);
    root=AddNode(root,13);
    root=AddNode(root,10);
    root=AddNode(root,5);
    root=AddNode(root,6);
    root=AddNode(root,8);

   LeafNodesRandomly(root);
}
YTE 1008
  • 49
  • 8
  • 2
    When you say "randomly" do you mean with a uniform probability of selecting any particular leaf? Or is it okay to select with a non-uniform probability affected by exactly how the tree is balanced? – Patrick Roberts Apr 01 '20 at 20:30
  • 2
    One way is to add a field to each node that counts how many nodes are below the current one, and update it on each insertion/deletion into the tree. Then to choose a random element, start at the root, and descend the left or right branch with probability proportional to the number of nodes on each side. – Nate Eldredge Apr 01 '20 at 20:33
  • The problem with probabilistic output is it might output more than one, or none at all. – jwdonahue Apr 01 '20 at 20:36
  • @PatrickRoberts just any of the leaf nodes...No matter which one... – YTE 1008 Apr 01 '20 at 20:37
  • 2
    @YTE1008 sorry but that doesn't actually answer the question I asked. – Patrick Roberts Apr 01 '20 at 20:39
  • 1
    If you store your nodes in an array, then you can randomly select one from that array. If it turns out to be a leaf node, you are done, if not, try again. Or iterate the tree and return an array of pointers to leaf nodes, then randomly select one of those. – jwdonahue Apr 01 '20 at 20:40
  • @jwdonahue For example there are 4 leaf nodes in BST.I want to return JUST one of them randomly...Without any specipication or algorithm...I just want a leaf node out of 4...No matter which one... – YTE 1008 Apr 01 '20 at 20:40
  • 2
    So you don't actually mean "randomly" but rather "arbitrarily"? Then just always follow the left branch until you hit a leaf. – Nate Eldredge Apr 01 '20 at 20:41
  • 1
    @YTE1008 `while (p != NULL && p->left != NULL) p = p->left; return p;` there you go. – Patrick Roberts Apr 01 '20 at 20:43
  • @YTE1008, an algorithm is required. – jwdonahue Apr 01 '20 at 20:43
  • Suppose I use srand as an algo – YTE 1008 Apr 01 '20 at 20:44
  • That's not an algorithm, that's a standard library function. – Patrick Roberts Apr 01 '20 at 20:45
  • This sounds like an [XY problem](https://en.wikipedia.org/wiki/XY_problem). – jwdonahue Apr 01 '20 at 20:46
  • @jwdonahue storing the leaf nodes in array and selecting an element from this array randomly was an option for me,,to be honest I tried but could not be successfull with this solution...I am open for your help if you have time...Maybe instead of recursion we have to use iterative method... – YTE 1008 Apr 01 '20 at 20:47
  • 2
    'I tried but could not be successful with this solution". Then show that attempt so we can help point out what is wrong with it. – kaylum Apr 01 '20 at 20:48
  • @kaylum It did not even work and I delete it... – YTE 1008 Apr 01 '20 at 20:57
  • 1
    Start with the root as the current node. If the current node has two children, use `rand() % 2` to decide whether to go left or right. If the current node has one child, go to that child. If the current node has no children, then that node is the randomly selected leaf. – user3386109 Apr 01 '20 at 21:00
  • 1
    See [this question](https://stackoverflow.com/questions/7343833/srand-why-call-it-only-once) for information about how to use `srand()`. `srand()` is used to seed the random number generator. And `rand()` is used to get a random number. – user3386109 Apr 01 '20 at 21:08
  • 1
    @user336109 These seems very logical,I will try this...Thanks...If I can do this,I do not need an array also... – YTE 1008 Apr 01 '20 at 21:08
  • @YTE1008 Those who are asking questions are trying to help by getting you to clearly state your requirements so that they can provide good answers. That's in the spirit of Stack Overflow. Your unhelpful attitude, on the other hand, is not at all in that spirit. I suggest you read and think about https://stackoverflow.com/help/how-to-ask and the included links, and consider whether your question and your responses in comments really correspond to those guidelines. – Jim Mischel Apr 02 '20 at 04:38
  • I think my question is so Clear and the people who really want to help and who wants to satisfy his ego and show he is a master ,he is the best of the best of the best is ALSO SO CLEAR...The one who must read those things is that kind of people I think... – YTE 1008 Apr 02 '20 at 04:46
  • 1
    Your first problem is `while(p->left !=NULL && p->right !=NULL)`. You probably should learn how to use the debugger, and single-step your code to see where you're going wrong there. You should also read https://www.geeksforgeeks.org/rand-and-srand-in-ccpp/, because you're using `srand` incorrectly. – Jim Mischel Apr 02 '20 at 18:02
  • @JimMischel I edited my code and it gives me output as either (6 or 13) or (8 or 10) . And this is enough for me...Thanks for your help everybody... – YTE 1008 Apr 06 '20 at 18:45

1 Answers1

1

You can simplify your code quite a bit by making use of information you already know. For example, the first few lines of your loop are:

while(p->left !=NULL || p->right !=NULL)
{
    if(p->left==NULL && p->right!=NULL)//Just have a right child
    {
        p=p->right;
        if(p->left==NULL && p->right==NULL)//If the right child is a leaf node print and break
        {
            printf("%d\t",p->data);
            break;
        }
    }

When you enter the loop, you know that, at most, one of the child pointers is null. So you know that if p->left == NULL, p->right cannot be null. Otherwise you never would have entered the loop body. And because the loop body won't be entered if both child pointers are null (i.e. p points to a leaf node), there's no reason to check for a leaf node after assigning a pointer. The while condition will exit the loop as appropriate, p will be pointing to a leaf node, and you can print the data.

In addition, you can increase the variability of which leaf node you get by picking a new random number whenever you get to a node that has two children.

The resulting code is much shorter and simpler. It reduces duplicated code and eliminates redundant logic checks.

void LeafNodesRandomly(BST*p)
{
    // Seed the random number generator.
    srand(time(NULL));

    // Randomly select a leaf node
    while(p->left !=NULL || p->right !=NULL)
    {
        if(p->left==NULL)//Just have a right child
        {
            p=p->right;
        }
        else if(p->right==NULL)//Just have a left child
        {
            p=p->left;
        }
        else // The current node have two children
        {
            // Randomly select a child node.
            int i = rand()%2;
            if(i==0)
            {
                p=p->left;
            }
            else
            {
                p = p->right;
            }     
        }
    }
    // When you get here, p is pointing to a leaf node.
    printf("%d\t",p->data);
}

The "randomly select a child node" can be further condensed by using the ternary operator:

// Randomly select a child node.
p = (rand()%2) == 0 ? p->left : p->right;

(Yes, nitpickers, I know that the == 0 is not actually necessary. It is more clear, though, especially to less experienced programmers. No need to tell me that a kitten dies every time somebody writes == 0.)

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351