在具有全局根的 BST 中插入一个节点

Insert a node in BST with global root

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 全局但插入函数不能无效它必须 return node* value 我能得到一个解释吗?
如果有更好的方法请分享(其实我想把insert做成void类型)
此致,

您编写 insert 的方式要求它始终 returns 它修改或创建的节点。这确保 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 的引用,所以也会更新。
  • 在随后的 insert 调用中,您将沿着树下降,直到到达节点 N,您必须在该节点进一步下降,但子节点为 nullptr。当您现在下降时,localRoot 绑定到 N->leftN->right,第一个子句将再次用指向新创建的节点的指针覆盖该值。

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

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

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

你的函数的 return 类型 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; 
}