【问题标题】:Insert a node in BST with global root在 BST 中插入一个具有全局根的节点
【发布时间】:2021-01-29 03:54:32
【问题描述】:
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 中,我们将 insert 称为 root = insert(root, 10);(其中 root 在 main() 中声明)。
我想声明 root 全局但插入函数不能为 void 它必须返回 node* 值我可以得到解释。
如果有更好的方法请分享(实际上我想让 insert 成为 void 类型)。
问候,

【问题讨论】:

  • 如果你保证你的函数会返回一个node *,你必须返回一些东西。如果将其返回类型更改为void 并省略返回语句,会出现什么错误?
  • 如果我设置了 void 那么它会显示编译错误 localroot-&gt;left = insert(localroot-&gt;left, item); 这行说“void value not ignored as ought to be”我不会返回 void 这就是我将 root 设为全局的原因。跨度>
  • 虽然允许对全局变量和局部变量以及函数参数使用相同的名称,但最好避免这样做,因为它会导致难以追踪的错误。尤其是在重构时代码块被移动时;)

标签: c++ recursion insert binary-search-tree function-definition


【解决方案1】:

您编写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 的引用,所以也会更新。
  • 在随后的 insert 调用中,您将顺着树向下,直到最终到达节点 N,您必须进一步向下,但子节点为 nullptr。当您现在下降时,localRoot 绑定到 N-&gt;leftN-&gt;right,并且第一个子句将再次使用指向新创建的节点的指针覆盖该值。

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 是的,先生,我只是为了更好地理解而进行试验。感谢您的宝贵时间。
    猜你喜欢
    • 1970-01-01
    • 2017-06-14
    • 2012-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多