简体   繁体   中英

Attaching nodes to a tree in C++ (Reference and pointer help.)

I am writing a balancing binary tree for class, but I am having some confusion as to how to use pointers and references in C++ (coming straight from Java). The code below results in a segfault, because no node has actually been added to the tree, curr has just been switched to the new Node . How would I go about making it so that the new Node goes to where curr is pointing to on the tree, rather than just reassigning curr ?

void BalancedTree::insert(int input)
{
    cout << "Insert started\n"; //DEBUG
    Node* trailingNode;
    Node* curr;

    curr = this->root;

    while(curr != NULL){
        cout << "Addloop\n";    //Debug
        if(input < curr->data){     //input smaller than current
            cout << "Left\n"; //DEBUG
            trailingNode = curr;
            curr = curr->left;
        }else{                      //input larger than current node
            cout << "Right\n"; //DEBUG
            trailingNode = curr;
            curr = curr->right;
        }
    }   

    insert(curr, input);
    cout << "test" << endl; 
    cout << root->data << " added\n";   //DEBUG
//  curr->parent = trailingNode;    //Set the parent

    size++;                         //Increase size
}

//Helper method
void BalancedTree::insert(Node*& curr, int input)
{
    curr = new Node(input);
}

If we have the following tree and attempt to insert the value 3 :

             2
            / \
       1 <--   --> 4
      / \         / \
     N   N       N   N

( N is NULL ) after the while loop as posted has completed:

  • trailingNode is pointing to the Node with value 4
  • curr is NULL (the left branch of Node with value 4 )

then insert() assigns a new Node to curr but never attaches it to the left branch of the Node with value 4 .

To attach you could change the call to insert() :

insert(input < trailingNode->data ?
           trailingNode->left :
           trailingNode->right,
       input);

You need to handle the case when the tree is empty. There are other ways that this could be achieved but hopefully this will point you in the right direction.

You can do it with a double pointer. Make cur actually reference (in C++ case point to) the last node reference you need to change:

    Node ** curr;
    curr = &this->root;

    while(*curr != NULL){
        cout << "Addloop\n";    //Debug
        if(input < (*curr)->data){     //input smaller than current
            cout << "Left\n"; //DEBUG
            trailingNode = curr;
            curr = &((*curr)->left);
        }else{                      //input larger than current node
            cout << "Right\n"; //DEBUG
            trailingNode = curr;
            curr = &((*curr)->right);
        }
    }   

    insert(curr, input);
    cout << "test" << endl; 
    cout << root->data << " added\n";   //DEBUG
//  curr->parent = trailingNode;    //Set the parent

    size++;                         //Increase size
}

//Helper method
void BalancedTree::insert(Node** curr, int input)
{
    *curr = new Node(input);
}

I think this should do the trick for you, but have not tried it - just edited in the edit here, so please forgive me if I made some simple coding error.

1) initialize the pointers to NULL:

Node* trailingNode = NULL;
Node* curr = NULL;

2) no need to explicitly check for NULL in the while loop:

while(curr){

3) The call to insert(curr, input) is always called with a NULL pointer! And even if it would not be NULL that pointer is still just a regular pointer having no relation with the node you retrieved it from. Taking a reference to it will not fix this. Instead you need to create a new node and assign it to either the left or right of the trailingNode, fe:

if (!curr->right) {
    curr->right = new Node (input);
    break; // exit while
}

Pointers are value types, similar to references or ints in Java.

Passing variables by reference creates an alias to that variable, so you can change its value in the function. When you do insert(curr, input); , it modifies the value of the pointer variable curr , making it point at a newly created node. The more or less equivalent situation in Java would be:

Node curr;

if([...]) {
    [...]
    curr = curr.left;
}
else {
    [...]
    curr=curr.right;
}
[...]
curr = new Node();

Now you can see how this doesn't actually insert anything into the tree. Now, if you want a variable to indicate an actual left or right member of a node, instead of just having the same value (pointing at the same object) as that member, you need to have a pointer to the member (field) itself - as the member is of a type 'pointer to Node ', a pointer to the member would have to be a pointer to (pointer to Node ), or in C++ notation Node** .

Now if you pass that 'pointer to pointer' to a function, you can modify through it the value of the referenced left or right member. This also means you don't need to modify the value of curr (and therefore pass it in by reference) - it will still point to the same left or right member (or possibly the root member of your BalancedTree object), only that member's value will be changed to point to the newly created element.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM