在具有全局根目录的BST中插入节点

问题描述

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

node* root;   //global root

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

node* insert(node* localroot,int item)
{

    if(localroot == NULL){
        localroot = getNode(item);
    }
    else if(item < localroot->data)
        localroot->left = insert(localroot->left,item);
    else if(item > localroot->data)
        localroot->right = insert(localroot->right,item);
    root = localroot;
    return root;   //Why do I have to return root if it is global? 
                   //without this output is wrong
}

void inorder(node* root)
{
    if(root != NULL){
        inorder(root->left);
        std::cout << root->data << ' ';
        inorder(root->right);
    }
}

void postorder(node* root)
{
    if(root != NULL){
        postorder(root->left);
        postorder(root->right);
        std::cout << root->data << ' ';
    }
}

int main()
{
    insert(root,15);
    insert(root,9);
    insert(root,2);
    insert(root,1);
    insert(root,4);
    insert(root,18);

    std::cout<<"inorder traversal of tree is: ";
    inorder(root);
    std::cout << "\npostorder: ";
    postorder(root);

    return 0;
}

通常在main中,我们将插入称为root = insert(root,10);(其中root在main()内部声明)。
我想声明root全局性,但是insert函数不能为空,它必须返回node *值,我可以对此进行解释。
如果有更好的方法,请共享(实际上我想将insert设为void类型)。
问候

解决方法

您编写insert的方式要求它始终返回修改或创建的节点。这样可以确保没有子节点的节点上的insert设置正确的成员(左或右)。

您可以通过传递对要设置的指针的引用来将root重写为纯命令性的内容:

void insert(int item,node*& localroot = root) {
    if (localroot == nullptr) {
        localroot = getNode(item);
        return;
    }

    if (item == localroot->data) {
        return;
    } else if(item < localroot->data) {
        insert(item,localroot->left);
    } else if(item > localroot->data) {
        insert(item,localroot->right);
    }
}

要实现的关键点是对localroot的分配将反映在数据结构中,因此:

  • 第一次调用insert(item)时,localroot是对root的引用,它是一个空指针。因此,第一个子句适用,并且您用新节点覆盖localRoot。因为localRoot是对root的引用,所以它也会被更新。
  • 在随后的插入调用中,您将下降树,直到最终到达节点N,在该节点处您必须进一步下降,但子节点为nullptr。当您现在下降时,localRoot绑定到N->leftN->right,第一个子句将再次使用指向新创建的节点的指针覆盖该值。

如果默认参数对您来说太神奇了,请分成两个函数:

void insert_helper(int item,node*& localroot) {
    // as above
}

void insert(int item) {
    insert_helper(item,root);
}
,

函数insert的返回类型意味着您必须通过以下方式调用它

root = insert(root,15);

在您的函数中,这些语句

root = localroot;
return root;   //Why do I have to return root if it is global? 
               //without this output is wrong

错了。

使用函数声明,可以通过以下方式定义函数

node* insert( node* localroot,int item )
{

    if ( localroot == NULL ){
        localroot = getNode( item );
    }
    else if ( item < localroot->data )
        localroot->left = insert( localroot->left,item );
    else if ( item > localroot->data )
        localroot->right = insert( localroot->right,item );

    return localroot; 
}