searching for an element in BST - c++

Following is the code for searching an element in BST.
can anyone please explain what &(*cur)->right or &(*cur)->left means in the code?
Thank You
TreeNode *insertIntoBST(TreeNode *root, int val)
{
TreeNode **cur = &root;
while( *cur )
cur = (val > (*cur)->val) ? &(*cur)->right : &(*cur)->left;
*cur = new TreeNode(val);
return root;
}

cur is a pointer to pointer, thus, to access its children, you need to dereference it (*cur) and only then access the element (->left, ->right).
After you got the next element (right or left), which is a pointer, you need to store it in cur. But cur is a pointer to pointer, so you need to take a reference of if (using the & operator).
The overall expression is the ugly &(*cur).
By the way, the reason you need a pointer to pointer, is because of the line *cur = new TreeNode(val);.
If you would simply use a pointer, this line would do nothing, and only change your temporary pointer. Since you are using a pointer to pointer, you are changing the original node in the tree.

Those properties are right and left children of the current node. and the while traverses the tree to find the suitable place for the value as its bigger or less than current node as the Binary Search Tree definition

Related

Understanding the logic behind Pointers to Pointers and linked lists in C++ (drawing nodes)

I'm still trying to understand pointers, drawing nodes and everything but I can't seem to understand some things.
For example here is a function that should delete nodes with even values from a list
void delete_even()
{
node **p= &head;
while (*p)
{
if ((*p)->data % 2 == 0)
{
node *nextptr=*p;
*p=(*p)->next;
delete nextptr;
}
else
{
p= &(*p)->next;
}
}
}
So as I understand it. p is pointing to the pointer named head and head is pointing to the first node.
If I write just p, I'm talking about the thing that p is pointing at, in this case the pointer head head
If I write *p, I'm talking about the thing that p is pointing at and the one more data data dereferencing. In this case, the first node.
Let's say we have a linked list with 4 nodes.
Also p is a pointer to a pointer so it should always point to a pointer and not a node. As I understand it.
1.
Now, while (*p) (In English that means: as long as the thing that p pointing at and one more data dereferencing )
I look at * as levels.
and * means return the value stored in the address kept in the pointer variable
If it's just p the pointer look at the whatever the pointer points at.
If it's *p do the same thing but one more level, so in this case the first node?
Looking at the list we see that the first node is 1. It's not even so we take this part of the if statement:
p= &(*p)->next;
In English( Make the thing p points at = to the first node through dereferencing and and then getting the address of the next member of this value.
A)I'm not sure if p= ~to something~ makes the thing p is pointing at change it's value
2.
That would make both pointers point at the second node. and the head pointer moved, I don't think it's right...
B) or p= ~to something~ makes the pointer p point to something else
2.1
For this case we are gonna follow the 2.1 approach.
Now that the second node is 2 and it's even.
Make a new pointer named nextptr and make it point to the same thing *p is pointing at
*p is currently pointing at the next pointer and the next is pointing to the second node.
Then we make the thing *p is pointing at currently which is the next data member that contains the address of the second node of the first node and make = to the second node's next (which is the address of the 3rd node).
3
Are my logic and drawing correct? because that's what I'm trying to understand
Note - head is a global variable as coded. It could have been passed as a parameter, and the updated value of head returned.
Initially:
head = pointer to the first node
node**p = &head : p = ptr to head
If the first node value even, then:
node *nextptr=*p; : nextptr = ptr to first node
(*p) = (*p)->next : head = ptr to second node
delete nextptr : delete first node
else if first node value not even
p = &(*p)->next; : p = ptr to (first node.next)
so that *p updates first node.next if second node even
and head remains pointer to first node

Pairwise swapping of elements in a linked list (by changing pointers)

The problem statement is the following:
Given a singly linked list, write a function to swap elements pairwise. For example, if the linked list is 1->2->3->4->5->6->7 then the function should change it to 2->1->4->3->6->5->7, and if the linked list is 1->2->3->4->5->6 then the function should change it to 2->1->4->3->6->5
Here is my solution:
void swapPairs(Node* head) {
if (!head->next || !head)return head;
Node* current = head->next;
Node*prev = head;
while (true) {
Node* next = current->next;
current->next = prev;
if (!next || !next->next) {
prev->next = next;
break;
}
prev->next = next->next;
prev = next;
current = prev->next;
}
}
The issue with the solution is that when it gets to the end of the function, the head no longer points to the beginning of the list since both current and prev have been moved. I've seen other solutions online which do the same thing as I'm doing here, but maybe since they are implemented in C instead of C++, there is some aspect of their code that allows for the head to remain pointing to the start of the list.
I realize that this is probably a really simple issue to solve, but I'm just not currently seeing the solution. What would be the best way to maintain the beginning of the list throughout the algorithm?
The task at hand will be much simpler once you undergo a slight paradigm shift. This might seem more complicated at first, but after pondering it a bit, its simplicity should be obvious.
Simply said: instead of carrying a pointer around -- to the first of each pair of list elements -- as you walk through the list, carry a pointer to the pointer to the first of each pair of list elements. This sounds complicated, on its face value; but once the dust settles, this simplifies the task at hand greatly.
You must have a head pointer stored separately, and you're passing it to swapPairs():
Node *head;
// The list gets populated here, then ...
swapPairs(head);
That's what you're doing now. But rather than doing this, pass a pointer to the head node, instead:
swapPairs(&head);
// ...
void swapPairs(Node **ptr)
{
while ( (*ptr) && (*ptr)->next)
{
// swap the next two elements in the list
// ...
// Now, advance by two elements, after swapping them.
ptr= &(*ptr)->next->next;
}
}
The body of the while loop is going to swap the next two elements in the list, and let's skip over that part for now, and just focus on this bit of logic that iterates through this linked list, a pair of elements at a time. What's going on here?
Well, you are trying to walk through the list, two elements at a time.
Remember, ptr is no longer the pointer to the first element of the pair. It's a pointer to wherever the pointer to the first element of the pair happens to live. So the initial ptr is pointing to your original head pointer.
Once you understand that, the next mental leap is to understand that you want to cycle through your iteration as long as there are at least two elements left in the list:
while ( (*ptr) && (*ptr)->next)
*ptr is the next element to the list, the first of the pair, and (*ptr)->next would therefore be the pointer to the second in the pair. Because of how we're iterating, ptr can be proven, by contract to never be NULL. So, if *ptr is NULL, you reached the end of the list. But if *ptr is not NULL, there's at least one element left, and (*ptr)->next is the "next 2nd element". If (*ptr)->next is NULL, the original list had an odd number of elements in it, so on the last iteration you ended up with *ptr pointing to the odd duck. And you're done in that case too, no need to go any further.
Finally:
ptr= &(*ptr)->next->next;
This simply advances ptr by two elements of the list. Remember, ptr is a pointer to wherever the pointer to the first of the next two elements in the list "happens to live", and this now sets ptr to point the where the pointer to the first of the ***next**** two elements in the list happens to live. Take a piece of paper, draw some diagrams, and figure this out yourself. Do not pass "Go", do not collect $200, until this sinks in.
Once you wrapped your brain around that, the only thing that's left is to swap the pairs. That's it. The body of the loop can simply be:
Node *first=*ptr;
Node *second=first->next;
Node *next=second->next;
*ptr=second;
second->next=first;
first->next=next;
That's it. You're done. And, guess what? Your original head is now automatically pointing to the right head node of the swapped list.
Now, wasn't that easy?
Change the signature of the function to
Node* swapPairs(Node* head)
and save the new head after the first swap, then at the end after your while loop's closing }, return that new head, to replace the old list head held by the caller, which would use this something like:
list = swapPairs(list);
You can keep a pointer to the new head at the beginning of the function and update the head at the end of the function with that. Note that I changed the argument from Node* to Node ** because we want to update the pointer value so that when we update head, we write to the same memory location that passed to this function. As a result, the correct value of head will be available in the caller of this function when we return from it.
void swapPairs(Node **head) {
if (!(*head)->next || !(*head))
return;
Node *new_head = (*head)->next; // the new_head
Node *current = (*head)->next;
Node *prev = (*head);
while (true) {
Node *next = current->next;
current->next = prev;
if (!next || !next->next) {
prev->next = next;
break;
}
prev->next = next->next;
prev = next;
current = prev->next;
}
*head = new_head; // now update the head
}

Understanding pointers in binary tree

I'm new to C++ and I normally use Java, so I have a hard time to get into pointers and references. I have to do a variation of binary search tree with inner nodes and leaf nodes (only leafs contain the data).
class Node
Node *parent;
Node *left;
Node *right;
//other stuff
}
I need to implement operator<< which adds a new node with value to the tree.
//adding a node to tree
void operator<<(int value){
if(size == 0){
//stuff
} else {
Node* temp = root;
getLeaf(temp,value);
//other magic
//temp will be used to append a new node into tree,
//so it has to point to the actual node in the tree
delete temp;
}
}
The point of function getLeaf is to find a leaf (may or may not contain the desired value) and store it into temp, which needs to be accessible in the operator<< function.
int getLeaf( Node* temp, int value) const{
int depth = 0;
//goes trough all inner nodes until it finds specific leaf
while(temp->isInner()){
++depth;
if(value < temp->getValue()){ //searched value is smaller
temp = temp->getLeft(); // to left subtree
continue;
} else {
temp = temp->getRight(); //to rightsubtree
continue;
}
return depth;
}
I am really confused how to do this and what is the right combination of pointers and values. If I set
Node* temp = root;
getLeaf(temp,value);
won't root get overridden while traversing the tree in getLeaf function?
Plus I need temp to point to actual node in the tree, so I can append a new node into it.
Could you please explain?
Migrating from Java to C++ is a bit tough. Migrating from C++ to Java is equally tough. To make things easy you just need to experiment.
In C++, pointers are variables that point to the location of another variable in memory and references are pointers that syntactically behave like the variable whose address is pointed to.
When arguments are passed to a function, the function does NOT receive the original arguments but a copy of them. The work you did is implement the traversal based on the above concepts. So how does it all "magically" work?
Your function: getLeaf(Node *&temp, int value) searches the correct leaf node and assigns it to temp at which insertion is to be performed. temp here is a copy of a reference to the pointer temp(in operator <<). So when the reference temp is assigned to in getLeaf, the pointer temp in operator << it points to is modified.
If I set
Node *temp = root;
getLeaf(temp,value);
won't root get overriden while traversing the tree in getLeaf function?
Note here that temp and root are two different pointers that point to the same variable. The content of the pointers is the same, they aren't and hence root is NOT overridden, when temp is updated.
But there is a problem later on in the code. If you delete temp;, root will also be deleted at the end of insertion as delete deletes the content pointed to by the pointer. Do NOT delete a pointer that is not allocated by a new.
Provide a separate function to free the dynamically allocated memory used by the tree, and call it at the end when you are done experimenting.

Just trying to insert a node and set the pointer in it to the next node C++

I feel really silly asking this, as it seems really simple, but I just can't figure it out. All I want to do is set the node pointer to the next node in the list. The function is from a teacher, I wrote the body, so I don't want to mess with the head of the function.
void LList::insert(int num, int at)
{
node* n = new node(num);
if (!n) throw runtime_error("Can't allocate node!");
if(!root || at == 0){
// if empty list - new node is root…
if (!root) root = n;
}
if(root){
node* nextNode = new node(num);
int numF = 0;
for (node* t = root; t != NULL ; t = t->next){
numF++;
if(numF == at){
n->next=t->next;
t->next=n;
}
}
}
}
Since it seems you are using n for the new node to be inserted into the linked list (I'm inferring that it's a singly linked list from the existing code and class name), there are a few things you have to do off the top of my head:
Identify the existing member of the list after which the new node will be inserted. You are making an attempt to do this already with that for loop, but in my opinion you may want to rewrite that as a while loop since you probably don't want it to keep iterating after the insertion position has been identified. Alternately, you could short-circuit out of the for loop with a break once you've found the right place for insertion, but I don't like that for stylistic reasons. :)
Set the newly inserted node's next pointer to the same location to which the next pointer of the node identified in #1.
Set the next pointer of the node identified in #1 to point at the new node, thus re-establishing the integrity of the chain.
Your code looks like it is attempting to do #2 and #3 out of order, which won't work. You're obliterating the value of t->next before you've had a chance to point n->next at it.
Finally, you may need to define some behavior to which you can fall back in case you are adding to a position not already defined in the list (i.e. inserting into the fourth position of a linked list that currently has three elements). You may need to re-jigger your loop to terminate when t->next is null rather than when t itself is null - otherwise you lose the hook to be able to connect the (currently) last element of the list to your new node.

Creating and adding a new node to a linked list

It is difficult to understand how this node is being created, Can you please write step-wise what this set of code is actually doing, and what actions they represent?
void list::create_node(int value)
{
struct node *temp;// Please write in words the meaning of this statement
temp = new(struct node);// is this a dynamic node? )
temp->info = value;// is this value being assigned to this node?
if (last == NULL)// what is this set of code testing??
{
last = temp;// who is this last; the node which has been created?
temp->next = last; // is the node pointing to itself being only one node?
}
else
{
temp->next = last->next;((( // What is this statement saying?
last->next = temp;// What is this statement saying?
last = temp;// What is this statement saying?
}
}
void list::create_node(int value)
{
The above line declares a function that creates a node with the given value and inserts the node into the list. The code must be examined to see where the new node is inserted.
struct node *temp;
Declares a pointer to a node. The memory has not been allocated yet, only a pointer that will be used later.
temp = new(struct node);
Allocates memory for a node from the dynamic (runtime) memory area (a.k.a. heap). Calls the constructor of the node structure to initialize the memory, if a constructor exists.
The pointer temp is now pointing to the node object.
temp->info = value;
This assigns the value to the data field, info. Need the declaration of struct node in order to confirm this guess.
if (last == NULL)
{
Assuming that last is a pointer and points to the last node, this check is looking for an empty list. Common implementation is to have pointer values set to null to mark the end of the list.
last = temp;
temp->next = last;
}
The above code inserts the new node as the last node. The last pointer allows fast access to the end of the list. This allows for reverse iteration without having to traverse all the links to find the last node.
Some implementations set the next field to null to indicate the end of the list, others like this one, make it point to the last node.
else
{
temp->next = last->next;
At this point, the list is not empty.
The new node is made to point to the same node that the last node points to.
This is best understood by drawing the node boxes and arrows pointing to the nodes.
last->next = temp;
Updating the last node to point to itself. See the above section.
last = temp;
Updating the pointer to the last (end of list) node to point to the new node.
}
}
I suggest you draw the linked list and walk through this algorithm a couple of times to see how it works. Also review the singly linked list data type.
The circular reference of the last node may be confusing to you. This may not be the standard implementation that most books describe, but it is valid.