【问题标题】:How can I return leaf nodes randomly in a BST?如何在 BST 中随机返回叶节点?
【发布时间】:2020-04-01 20:29:37
【问题描述】:

我想获得一个叶节点作为输出(只是其中一个)。但每次都不是同一个叶节点...我想在“srand”的帮助下每次都获得一个不同的叶节点函数...我尝试使用数组来解决此问题,但未能成功。然后我决定在评论这篇文章的朋友的帮助下继续使用不同的算法...
如果左边的孩子很奇怪,我会生成一个随机整数,反之亦然...... 但是得到与输出相同的节点并不能解决问题...

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;
    } */
    }

}


这是我的主要功能:

我有 13 或 NULL 作为输出

#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);
}

【问题讨论】:

  • 当你说“随机”时,你的意思是用统一的概率选择任何特定的叶子吗?或者是否可以使用受树平衡方式影响的非均匀概率进行选择?
  • 一种方法是向每个节点添加一个字段,该字段计算当前节点下方的节点数,并在每次插入/删除树时更新它。然后选择一个随机元素,从根开始,以与每侧节点数成正比的概率下降左或右分支。
  • @YTE1008 抱歉,但这并不能真正回答我提出的问题。
  • 所以你的意思不是“随机”而是“任意”?然后总是沿着左边的树枝走,直到你碰到一片叶子。
  • '我尝试过,但无法成功使用此解决方案"。然后展示该尝试,以便我们帮助指出它的问题所在。

标签: c data-structures binary-tree binary-search-tree


【解决方案1】:

您可以通过利用您已经知道的信息来大大简化您的代码。例如,循环的前几行是:

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;
        }
    }

当你进入循环时,你就知道,最多有一个子指针为空。所以你知道如果p-&gt;left == NULLp-&gt;right 不能为空。否则你永远不会进入循环体。并且因为如果两个子指针都为空(即p 指向叶节点),则不会进入循环体,因此没有理由在分配指针后检查叶节点。 while 条件会酌情退出循环,p 会指向一个叶子节点,可以打印数据了。

此外,您可以通过在到达有两个子节点的节点时选择一个新的随机数来增加您获得的叶节点的可变性。

生成的代码更短更简单。它减少了重复的代码并消除了冗余的逻辑检查。

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);
}

“随机选择一个子节点”可以使用ternary operator进一步浓缩:

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

(是的,吹毛求疵的人,我知道== 0 实际上并不是必需的。不过,它更清楚,尤其是对于经验不足的程序员。无需告诉我每次有人写== 0 时都会有一只小猫死去。 )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 2015-08-14
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    • 1970-01-01
    • 2020-01-16
    相关资源
    最近更新 更多