【问题标题】:Binary Search Tree Insertion using a void function使用 void 函数插入二叉搜索树
【发布时间】:2017-06-15 10:43:04
【问题描述】:

我编写了两种不同的代码来插入二叉树,一种有效,另一种无效。

这是我的节点的样子:

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

以下是node* newnode(int a)的代码

node* newnode(int a)
{
    node *temp=new node;
    temp->data=a;
    temp->left=nullptr;
    temp->right=nullptr;
    return temp;
}

以下是两种不同的插入代码:

这个返回一个指向节点的指针:

 node* insertion(node *root, int a)
 {
    if(root==nullptr)
        return newnode(a);
    else if(a<root->data)
        root->left=insertion(root->left, a);
    else
        root->right=insertion(root->right, a);
 }

这个返回void:

void insertion2(node *root,int a)
{
    if(root==nullptr)
        root=newnode(a);
    else if(a<root->data)
        insertion2(root->left,a);
    else
        insertion2(root->right,a);
}

返回 void 的那个不起作用。根据我的分析,在函数调用之后,root 仍然是nullptr。谁能解释一下为什么它不起作用?

【问题讨论】:

  • 这里root在函数中被修改,对main中的root没有影响。上面的函数调用修改了函数局部的变量,整体没有影响
  • 我认为这是问题所在,但后来我认为将函数参数作为指针传递是一种通过引用传递的方法。因此,在函数insertion2 中对root 所做的任何更改也应该在main 中可见(root 是指向node 的指针)。还是我都搞错了?
  • 不,这里不是这样。看看你是否对root 指向的数据(类似于*root = something)进行了任何更改,那么只有它在rootmain's 副本中可见,但在这里你正在对root 本身进行更改。这里地址本身是按值传递的,因此对root 所做的任何更改都将是函数的本地变量。
  • insertion 肯定也坏了。 root ! =nullptr 所在的任何分支都没有 return,因此行为未定义。
  • 您可能希望接受给出的答案之一。只是对回答的人行屈膝礼。

标签: algorithm c++11 data-structures binary-search-tree


【解决方案1】:

在第二个函数中,根始终是一个局部变量,因此更新它不会改变主根变量,因为指针本身不是通过引用传递的。您可以通过引用调用来实现这一点,只需更改您的 函数标题如下:void insertion2(node *&amp;root,int a).

【讨论】:

    【解决方案2】:

    请注意,在insertionversion 中,您有root-&gt;left = insertion(root-&gt;left, a)root-&gt;right = insertion(root-&gt;right, a),但在insertion2 中没有相同的效果。实际上,insertion2 除了泄漏内存之外什么都不做。

    【讨论】:

    • 但在if-else 的情况下,我将root-&gt;leftroot-&gt;right 作为参数之一传递。因此,当调用函数时,如果让我们说 root-&gt;leftnullptr 那么它不会与 root-&gt;left=newnode(a) 相同,因为现在 root-&gt;left 已变为 root
    • insertion 我返回newnode(a)。因此,函数返回一个指向保存在root 中的新节点的指针。而在insertion2 中,我将newnode(a) 保存在函数本身中。那么两者实际上不一样吗?就像root=insertion(root,3); insertion(root,5); insertion(root,10);insertion2(root,3); insertion2(root,5); insertion2(root,10); 不一样(就像函数本身有一行写着root=newnode(a))?
    • 在第二个版本中,您永远不会向 root->left 或 root->right 写入任何内容,您正在写入变量名 root,而不是写入它指向的对象。跨度>
    • 终于明白了。为了使insertion2 工作,我必须进行以下更改:void insertion2(node *&amp;root, int a)。修改后,代码运行流畅。
    【解决方案3】:

    回答你的问题。

    您的插入函数的问题是根变量将指向被调用位置的 nullptr(NULL),并且分配了新内存并指向插入函数内部的局部引用。对新内存位置的引用更改不会对引用@调用位置产生任何影响。正如其他人所指出的,此调用将始终在@clearer 答案中泄漏内存。

    使此功能发挥作用。移动对象创建部分@调用地点,只留下插入到这个函数。

    类似下面的东西应该可以工作。

    void insertion2(node *root, node *new_node)
    {
        if(root==nullptr)
            root=new_node;
        else if(a<root->data)
            insertion2(root->left,new_node);
        else
            insertion2(root->right,new_node);
    }
    
    // Create the new node and call the insert function
    new_node = newnode(a);
    insertion2(root, new_node);
    

    希望它能澄清你的疑问!

    【讨论】:

      【解决方案4】:

      这种方式在使用 void 返回类型时工作正常。声明一个全局变量,first..如果要插入的节点是first..则设置为1..稍后将其更改为0.

      void insertRoot(struct node* newnode){
          root=newnode;
      }
      
      void insert(struct node* root, int data)
      {
          if(first==1){
                  insertRoot(createNode(data));
                  first=0;
          }else{
              if (data < root->data){
                  if(root->left==NULL){
                      root->left=createNode(data);
                  }else{
                      insert(root->left,data);
                  }
              }
              else if (data > root->data){
                  if(root->right==NULL){
                      root->right=createNode(data);
                  }else{
                      insert(root->right,data);
                  }
              }
          }
      }
      

      【讨论】:

        【解决方案5】:

        调用方法的根指针也需要更新。因此,您必须使用类似的方法调用 Insert2 方法:Insert2(&BSTNodePtr, a)。当您传递变量 BSTNodePtr 的地址时,Insert2 方法可以更新它的内容。

        试试这个:

        void Insert2(BSTNode **root, int a){
            if (*root==NULL){
                *root = new BSTNode(a);
            }
            else if (a<= (*root)->data){
                Insert2(&((*root)->left), a);
            }
            else{
                Insert2(&((*root)->right), a);
            }
        }
        

        【讨论】:

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