【问题标题】:Counting number of nodes in Binary Search Tree C++计算二叉搜索树 C++ 中的节点数
【发布时间】:2020-03-23 07:58:40
【问题描述】:

我很难理解为什么下面的函数CountNodes() 会计算 BST 中的所有节点。

如果我们假设我们有以下 BST:

            20
          /   \
         10    30
        /  \  /  \
       5  15 25  35

如果我打电话给CountNodes(pointer to root node 20); 那么相关的if 声明不会:

    if(root->left!=NULL)
    {
        n=n+1;
        n=CountNodes(root->left);
    }

只需查看节点 10 并说,是的,它不为空,将 1 加到计数器 n,然后调用 CountNodes(pointer to 10),这将再次将我们从左分支发送到 5。那么当5leftright变量是NULL,因此整个CountNodes函数只返回n等于int 3

我想我很难准确理解 CountNodes 的参数值何时更新。我们是否查看right 并检查其NULL 是否并更新计数器,然后在左侧查看CountNodes(pointer to 10) 的第一次递归调用中更新参数值,即使右侧查看出现在代码中的左侧递归调用之后?

#include<iostream>
using namespace std;

int n=1;

struct node
{
    int data;
    node* left;
    node* right;
};

struct node* getNode(int data)
{
    node* newNode=new node();
    newNode->data=data;
    newNode->left=NULL;
    newNode->right=NULL;
    return newNode;
}

struct node* Insert(struct node* root, int data)
{
    if (root == NULL)
        return getNode(data);

    if (data < root->data)
        root->left  = Insert(root->left, data);

    else if (data > root->data)
        root->right = Insert(root->right, data);

    return root;
}


int CountNodes(node*root)
{
    if(root==NULL)
        return 0;

    if(root->left!=NULL)
    {
        n=n+1;
        n=CountNodes(root->left);
    }

    if(root->right!=NULL)
    {
        n=n+1;
        n=CountNodes(root->right);
    }
    return n;
}

int main()
{  
    node* root=NULL;
    root=Insert(root,10);
    Insert(root,5);
    Insert(root,20);
    Insert(root,4);
    Insert(root,8);
    Insert(root,15);
    Insert(root,25);
    cout<<"Total No. of Nodes in the BST = "<<CountNodes(root)<<endl;

    return 0;
}

【问题讨论】:

  • 我会避免使用全局变量n。在递归中使用具有副作用的全局变量是非常错误的......
  • 我建议您尝试找到一个解决方案,其中n 是一个本地变量而不是全局变量。
  • 首先,您绝对应该将n定义为countNodes的局部变量。然后通过 分配 n 作为递归调用的结果,您会丢失以前的信息。你需要+= 而不是......
  • 另外,通过 n = ... 后跟 n = ... 你会丢失第一个作业。
  • 实际上,您可以非常简单地做到这一点:return root == nullptr ? 0 : 1 + count(root-&gt;left) + count(root-&gt;right); – 下一个递归调用中的 null-check 补偿了对可用子项的丢弃检查。 1 + ... 计算当前节点本身,它取代了您现在拥有的 n = n + 1

标签: c++ recursion binary-search-tree


【解决方案1】:

你正在覆盖 n 的值

    n=CountNodes(root->left);

您应该从子树中添加计数。

    n = n + CountNodes(root->left);

还有另一个错误是,如果节点有左右树,则计算该节点两次,如果节点没有子树,则永远不计算。

if(root->left!=NULL)
{
    n=n+1;                      // Adding one for this node.
    n=CountNodes(root->left);
}

if(root->right!=NULL)
{
    n=n+1;                      // Adding one for this node again?
    n=CountNodes(root->right);
}

我认为你应该这样做:

if(root->left!=NULL)
{
    n = n + CountNodes(root->left);
}

if(root->right!=NULL)
{
    n = n + CountNodes(root->right);
}
n = n + 1;

接下来是在进入函数时检查 null。因此,您无需在进行递归调用之前测试 null。

n = n + CountNodes(root->left);
n = n + CountNodes(root->right);
n = n + 1;

然后我们可以将其简化为:

int CountNodes(node* root)
{
    if (root == nullptr) {
        return 0;
    }
    return 1 + CountNodes(root->left) + CountNodes(root->right);
}

【讨论】:

  • 其实,你甚至不需要这两个 if,如果你放弃它们,递归调用中对 root 的 null-check 会赶上,从而导致 n += 0...跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-07
  • 1970-01-01
  • 2014-05-10
  • 2015-05-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多