二进制搜索树-插入节点

时间:2020-10-09 01:42:49

标签: c++ binary-search-tree

我正在尝试实现将节点插入二进制搜索树的功能。我正在使用以下代码,但是当我尝试打印到屏幕时,我看到的只是“ root = 1”。关于我在做什么错的任何建议吗?

#include <iostream>

class BTNode {
public:
   int item;
   BTNode *left;
   BTNode *right;
   BTNode(int i, BTNode *l=nullptr, BTNode *r=nullptr):item(i),left(l),right(r){}
};

BTNode *root = nullptr;
void insert(int i) {
   if (root==nullptr)
      root=new BTNode(i);
   else if(i<root->item){
      root=root->left;
      insert(i);
   }
   else{
      root=root->right;
      insert(i);
   }
}

int main()
{
   insert (5);
   insert (10);
   insert (1);
   
   if (root) 
   {
      std::cout << "root = " << root->item << std::endl;
      if (root->left)
         std::cout << "root->left = " << root->left->item << std::endl;
      if (root->right)
         std::cout << "root->right = " << root->right->item << std::endl;
   }
   
   return 0;
}

3 个答案:

答案 0 :(得分:2)

您的代码的效果如下

  1. insert(5):创建一个值为5的新BTNode并将其分配给root
  2. insert(10):创建一个值为10的新BTNode并将其分配给root。您不再引用以前创建的节点
  3. insert(1):创建一个值为1的新BTNode并将其分配给root。您不再引用先前创建的两个节点中的任何一个。

您可以以这种方式实现insert函数,通常是BTNode类的成员函数,这就是为什么我将它们称为private / public,但是由于您选择将它们实现为类之外的函数,因此我将其保持这种方式。

首先,您具有公共插入功能

void insert(int i){
      insert( i,root);// call the private function. see below
}

您有一个私有插入函数(请注意,指针变量应按引用传递,否则它将更改指针的副本)

void insert(int i,BTNode *& t){
    if(t==nullptr)t=new Node(i);
    else if(i<t->item)insert(i,t->left);
    else insert(i,t->right);
}

答案 1 :(得分:0)

我在下面写下了代码。

BTNode *root = nullptr;
BTNode* insert_node(int ivalue, BTNode* _parent) {
    if (_parent == nullptr) {
        return _parent = new BTNode(ivalue);
    }
    else if (ivalue<_parent->item) {
        _parent->left = insert_node(ivalue, _parent->left);
    }
    else {
        _parent->right = insert_node(ivalue, _parent->right);
    }
    return nullptr;
}
void insert(int i) {
    BTNode*newnode = insert_node(i, root);
    if (newnode)root = newnode;
}

int main()
{
    insert(5);
    insert(10);
    insert(1);
    //insert(2);
    //insert(4);
    if (root)
    {
        std::cout << "root = " << root->item << std::endl;
        if (root->left)
            std::cout << "root->left = " << root->left->item << std::endl;
        if (root->right)
            std::cout << "root->right = " << root->right->item << std::endl;
    }

    return 0;
}

答案 2 :(得分:0)

您的insert函数正在将新节点正确添加到树中。但是,作为副作用,有时会更改全局变量root指向根的左节点或右节点,从而使树的其余部分丢失。除非insert,否则您的root == nullptr函数应永远不要更改根。

因此,建议您重写函数insert,使其完全不使用root,而将指向该节点的指针作为函数参数。该指针必须通过引用传递,而不是值,因为函数insert必须能够更改所传递的实际指针(如果它是nullptr)。为此,您可以例如将函数原型更改为以下内容:

void insert( BTNode &*pp_node, int i );

这也将使您的递归函数调用正常工作,因为现在可以像这样重写函数:

void insert( BTNode *&node, int i )
{
    if ( node == nullptr )
        node = new BTNode( i );
    else if ( i < node->item )
        insert( node->left, i );
    else
        insert( node->right, i );
}

您的函数main必须像这样重写:

int main()
{
    insert( root, 5 );
    insert( root, 10 );
    insert( root, 1 );

    [...]
}

但是,由于您不再需要root作为全局变量(因为现在将其作为函数参数传递了),因此最好将其声明为局部变量,如下所示:

int main()
{
    BTNode *root = nullptr;

    insert( root, 5 );
    insert( root, 10 );
    insert( root, 1 );

    [...]
}

尽管此递归解决方案可以解决问题,但迭代解决方案将更加有效。因此,您可能想像这样重写函数insert

void insert( BTNode **pp_node, int i )
{
    while ( *pp_node != nullptr )
    {
        if ( i < (*pp_node)->item )
            pp_node = &(*pp_node)->left;
        else
            pp_node = &(*pp_node)->right;
    }

    *pp_node = new BTNode( i );
}

此解决方案需要使用指向指针的指针(所谓的双指针),而不是指向指针的引用,因为无法重新分配引用。

但是,由于insert的函数原型已经更改,因此您还必须相应地修改函数main

int main()
{
    BTNode *root = nullptr;

    insert( &root, 5 );
    insert( &root, 10 );
    insert( &root, 1 );

    [...]
}
相关问题