void insert(int key)
{
insertRec(key, root);
}
void insertRec(int key, Node *current)
{
if(current==NULL)
current = new Node(key);
else if(key <= current->value)
insertRec(key, current->leftChild);
else
insertRec(key, current->rightChild);
}
How come this doesn't work?
In the insert function, key value and root of the tree are passed to insertRec. If the node is null, create a new node and set it to the key value. Else, either recursively go left or right until the node hits a null spot and insert a new node there.
It's not true the code 'doesn't work'. Of course it works, just as it is written. The problem is you wrote something different from what you need.
when you pass an argument to insertRec(), the routine gets a copy of a pointer to the Node object. So when you assign a value in
current = new Node(key);
you overwrite a local copy in the local variable current. The calling function (and its data) do not know about it.
If you want the caller to recieve the new value, declare a function takes a reference to a variable:
void insertRec(int key, Node *¤t)
Related
Printed out the address of head and &head:
head:0x603050
&head :0x7fffffffe4b8: what does this signify?
void push(node* &head,int key)// Inserts items at front of link list
{
node* linkNode=new node(); //declares new node
linkNode->data=key;
if(head==NULL) //if the link list is empty then create a new one.
{
linkNode->next=NULL;
head=linkNode; //1
}
else
{
linkNode->next=head;
head=linkNode;
}
}
Main function where all other functions are called from
link list is 8,4,2
main function
int main(int argc, char** argv)
{
node* head=NULL; //initializing head to NULL
push(head,2); //creating link list
push(head,4); //this requires &head
push(head,8); //link list is 8,4,2
selectSort(head); //this does not require &head
reverse(head); //this requires &head
return 0;
}
Why do we need to pass it by reference of reference such as in push(node* &head, int key)
Otherwise it won't work to set the given linkNode as current head:
if(head==NULL) //if the link list is empty then create a new one.
{
linkNode->next=NULL;
head=linkNode; // <- This statement changes the head variable passed from main()
}
What you have is a reference to a pointer (head) that will be 'returned' from the push() function, and set the head pointer passed from the caller correctly:
node* head=NULL;
push(head,2); // sets head to the node created for key '2'
Don't forget to delete all the node instances you have created with new node();. In a different context as you're showing, this might lead to memory leaks.
That's not a "reference of reference"; it's a reference to a pointer.
It means that, once the pointer head has been set to point to the new element, within the function, this change also affects the pointer you originally passed in to the function.
selectSort(head); //this does not require &head
It probably should do, actually, if the function performs a sort over all elements of the list.
reverse(head); //this requires &head
After this call, head now points to the new head of the list. This would not be possible if you'd passed head by value.
An alternative implementation might return the new head pointer, instead of using this "out parameter" convention.
The reason you must pass head to the push function is because your push function is expecting to modify the value of the head pointer. If you don't pass it by reference, any changes to it will only be available within the function call. For example, if it was not passed by reference, and you passed head (initialized to NULL), to the push function, a new item would be created, but your value for head would only be updated inside the function. Once you left the function, it will still be NULL (because you passed the pointer by copy).
Note that this can go away if you create a linked list class instead of treating your nodes as a linked list themselves (that is, encapsulate the nodes under a list interface - which is what the standard library does).
I've pinpointed my issue to this specific function, it's the helper function for my binary tree. Before this function call there is a node but instead of growing it seemingly just replaces that node. When I look at my code in my head it all makes sense but I can't figure out what I'm doing wrong.
Here is the function that calls add:
void BSTree::Insert(Client &newClient) {
if (isEmpty())
{
Node *newNode = new Node(newClient);
this->root = newNode;
}
else
add(this->root, newClient);
}
and here is my add() function:
BSTree::Node* BSTree::add(Node *node, Client &newClient) // helper function for Insert()
{
if (node == nullptr)
{
Node *newNode = new Node(newClient);
//node = newNode; // already tried adding this in
return newNode;
}
if (newClient.clientID < node->pClient->clientID)
return node->left = add(node->left, newClient); // already tried just returning add()
else
return node->right = add(node->right, newClient);
}
Since this is your question, I will explain what your code is doing. Imagine you have a mature binary tree already and you are adding a node to your tree. By the time you reach this line
return node->left = add(node->left, newClient);
Three separate instructions are carried out:
newClient is added to the left branch of node by add().
the left child of node is set to the return value of add().
the right hand side (RHS) of the assignment is returned by the parent function.
The issue is with number 2. If the tree you are adding to is mature already, changing left child of nodes as you're traversing the tree will cause the override effect that you're observing. In fact, the problem goes beyond overwriting leaves. Since you use the new keyword, the overwritten nodes still have allocated heap space, are never deleted and cause a memory leak.
Here are some thoughts to get you on the right direction:
Your insert() function ensures that the first time you call add(), you are not passing nullptr as the first argument. Take advantage of that and ensure nullptr is never passed into add() function by checking for nullptr before you do the recursive call. Change the return type of add() to void. You no longer need to check node is nullptr. Here's some pseudocode to guide you
void add(node, val)
if val < node.val
if node.left exists
add(node.left, val)
else
make a new object and set node.left to that object
else
if node.right exists
add(node.right, val)
else
make a new object and set node.right to that object
There is a problem with your logic. First of all, there is the insert() method which you should write like this for better understanding:
void BSTree::Insert(const Client &newClient) // use const to prevent modification
{
if (isEmpty()) { root = new Node(newClient); }
else { add(this->root, newClient); }
}
This way you are creating a new object at root directly with the help of 'root' pointer in BSTree.
Now, about the add() method. The 'node' you are passing as a parameter is a copy of the pointer variable, so the actual pointer value is not changed. See this:
BSTree::Node* BSTree::add(Node *node, Client &newClient) //logical error
You need to pass the Node* by reference like this using 'Node* &node':
BSTree::Node* BSTree::add(Node* &node, const Client &newClient)
Why is you binary tree overwriting the roots of its leaves? Answer:
Your recursive call with return statement is totally wrong.
return node->left = add(node->left, newClient);
The add(node->left, newClient) always returns the address of the leaves, and you are returning this value. It goes for recursive calls until it reaches the leaves place.
Conclusion: Since, there are a lot of bugs, I would suggest you re-write logic again carefully.
I hope this helps! :-)
I wrote the following function to practice binary search tree insertion:
void RecursiveInsert(struct Node* &root, int key) {
if (root == nullptr) {
root = new Node(key);
return;
} else if (root->key > key) {
RecursiveInsert(root->left, key);
} else {
RecursiveInsert(root->right, key);
}
}
It works, but I don't understand why should I pass in a reference to root. Does anybody know why?
You want the function to be able to change the pointer stored in the parent node of the node that you're going to insert so that it points to the new node instead of nullptr. If you don't use pass-by-reference, all the function can do is modify a local copy of the pointer, and the pointer in the actual tree won't get changed.
For example, let's say you're looking at a node, and you want to insert the new node as this node's right child.
someNode[key: 123, left: nullptr, right: nullptr]
The function is going to be called with the right pointer as an argument. You want the function to be able to change the node so it looks like this:
someNode[key: 123, left: nullptr, right: newNode]
If you don't pass-by-reference, the function can't change the right pointer of the node, since it has only been given a copy. Using the reference allows the function to actually modify the pointer stored in the node that was used as the argument.
I was creating a custom binary tree and has stumbled in the following code for correct insertion in the tree from this site.
void treeInsert(TreeNode *&root, string newItem) {
if ( root == NULL ) {
root = new TreeNode( newItem );
return;
}
else if ( newItem < root->item ) {
treeInsert( root->left, newItem );
}
else {
treeInsert( root->right, newItem );
}
}
Why do you need to passed TreeNode *&root instead of TreeNode *root?
If you pass a pointer, rather than a reference to a pointer, modifications that you do to that pointer itself would be local to your treeInsert function. This prevents you from inserting the root - the only case when you must modify the pointer itself (the third line in your source code).
For example, if you do this
TreeNode *root = NULL;
treeInsert(root, "hello");
and treeInsert takes TreeNode*, the value of root after the call of treeInsert will remain NULL, because the third line of your source code would modify a local copy of the root pointer.
Consider the case when your newItem is the root item. Then this will change your root element. This means that at the end of the operation, your note 'root' has to point to the newly inserted TreeNode.
Now if you only pass TreeNode *root, you can only change the value, but at the end, your root pointer cannot be changed. So, you have to pass your pointer by reference, so that you can change it within your function.
The pointer TreeNode* is passed by reference, so that the original pointer in the calling function can be changed, in case the tree is empty.
Otherwise, if you just pass a copy of the pointer, the modifications will be local to the function being called.
A comment is present in the code itself: Note that root is passed by reference since its value can change in the case where the tree is empty.
If you don't do this, you have a NULL pointer in the calling function representing the root of the tree, which is clearly wrong since you just inserted an element.
Some other ways of handling the situation are:
Returning the local root pointer
root = treeInsert(root, str);
Passing pointer to root pointer, so it can be changed
treeInsert(&root, str);
I am building a binary search tree. Now I am having a problem with adding a node to the tree.
void BinaryTree::add(int value, Node* node) {
if(!node)
node = new Node(value);
else if(node->key < value)
this->add(value, node->rightNode);
else if(node->key > value)
this->add(value, node->leftNode);
}
This code does not seem to work when I call:
BinaryTree test;
test.add(4, test.root);
test.add(1, test.root);
test.add(5, test.root);
test.add(2, test.root);
test.add(3, test.root);
test.add(7, test.root);
test.add(6, test.root);
After the first add call, the root of the tree 'test' is still empty.
How shall I change the code so that it will be updated when I call add and the node goes to the correct place of the tree?
Thank you very much!
You are passing the Node * by value here:
void BinaryTree::add(int value, Node* node) {
One solution is to pass by reference instead:
void BinaryTree::add(int value, Node *& node) {
^
If you pass by value the function is just receiving a copy of the Node * and so any modification to it will not be reflected back in the calling code.
Also you might want to think about what happens when value is equal to the key.
You recursively call the add function, but nowhere in there do I see you actually assigning leftNode or rightNode to the passed in node.