I know that recursion keeps being executed till it meets the base case.
However, why does this recursion function only set head's child once?
When the head becomes null, it returns the node and sets the head's either left child or right child as node.
I get this concept, but why doesn't this recursion function sets all the left children or right children as nodes even though it's recursion function?
One more question, this recursion stops when the head is null, but why doesn't this recursion set null's child as node? this recursion sets previous of null's head's child as node. Why is it?
public Node<Integer> insert(Node<Integer> head, Node<Integer> node){
if(head == null){
return node;
}
if(head.getData() >= node.getData()){
head.setLeftChild(insert(head.getLeftChild(), node));
} else {
head.setRightChild(insert(head.getRightChild(), node));
}
return head;
}
What we have here is a binary search tree insertion function.
The function takes two nodes as parameters: head being the root of the binary tree, and node is the new node you are inserting into it.
The new node will be inserted in such a way that a depth-first in-order traversal of the tree will yield an ascending sequence of integers.
why does this recursion function only set head's child once?
It sets all tree nodes along the path from root node to inserted node's position on the way out of recursion. Only the first assignment is meaningful though, because all others just set the same node without change.
why doesn't this recursion function sets all the left children or right children as nodes even though it's recursion function?
Each call of the function in this recursion sets left, right or no child. If you follow the execution carefully, you will see at which position in the tree which child is set.
why doesn't this recursion set null's child as node?
The recursion exit condition prevents any operations on a head if it's value is null - it returns the node that you want to insert instead to the previous recursion call where the actual insertion takes place.
insert returns in most cases head. Whenever it returns head, head.setLeftChild(insert(head.getLeftChild(), node)) results in head.setLeftChild(head.getLeftChild()) and head.setRightChild(insert(head.getRightChild(), node)) results in head.setRightChild(head.getRightChild()). i.e. in most cases, the calls to setLeftChild and setRightChild don't change the left/right child of the current head Node.
Only when insert(head.getLeftChild(), node) or insert(head.getRightChild(), node)) is passed a null value (i.e. when head.getLeftChild() or head.getRightChild() are null), the recursive call returns the new Node, node, which causes head.setLeftChild(insert(head.getLeftChild(), node)) to result in head.setLeftChild(node) and head.setRightChild(insert(head.getRightChild(), node)) to result in head.setRightChild(node).
Related
I'm trying to create a double linked list in Java. With the following elements inside each node:
public class Node {
int data;
Node next;
Node before;
}
data is just a number (0 to 9). Node next indicates the next pointer in a list, and Node before the before pointer in a list.
In the first loop where i ask for list == null is the first element in a list, which i indicate that the new.before = null so its the first element in the linked list. And the new.next=list so it can continue building the list without entering the loop again.
But i'm stuck when i try to link the other elements in the list, not the first one. I have the idea which i need to link the element before and the next element. But i dont know how to implement this idea.
This is the code for generating the doubly linked list.
public static Node CreateDoubleLinkedList(Node list, int data)
{
Node nuevo=new Node();
new.data=data;
new.next=null;
new.before=null;
Node aux=list;
if(list==null)
{
list=new;
new.next=list;
new.before= null;
return list;
}
else
{
/* I dont know how to implement the idea of the doubly linked list after the first element*/
new.before=aux;
while(aux.next!=null)
{
aux=new.next;
}
return list;
}
}
Okay, so when attaching nodes to a doubly-linked list there are more links, and therefore more cases to be concerned about.
(1) The list is empty. Add the incoming node to the head of the list. The next pointer and the before pointer point to nothing (null)
(2) There is one node in the list, and we append the incoming node to the front of the list. Here we append the incoming node's next to the head of the list, and the node that was already there points the before pointer back at the incoming node.
(3) Okay, now assume the incoming node goes in between two nodes. This is more complicated. Attach the incoming node's before to the previous node, and then attach the incoming node's next to the node that's next in the list. Now, relink the previous node's next to point at the incoming node, and then do the same with the node in front, but this time with the before link.
(4) Okay, one last case to be concerned about. Append the incoming node at the end of the list. This is similar to appending to the front of the list, but now, we use the incoming node's back pointer to point at the previous node, and like all the other cases, don't forget to update the link at the previous node. In other words, point the previous node's next pointer at the incoming node.
I have an Ordered Insertion sort method which sorts an item in a linked list in ascending order as it is been added.
//getData() returns the data in that Node
//getLink() returns the link to the next Node
//setLink() sets the link of the Node
//top is the reference to the first node
public void ordInsert(int newItem) {
IntNode prev = null;
IntNode next = top;
while(next!=null && next.getData()<newItem){
prev = next;
next = next.getLink();
}
IntNode newNode = new IntNode(newItem,next);
if(prev==null)
top = newNode;
else
prev.setLink(newNode);
}
I am trying to create a method that sorts the entire list by using this ordered sorting method.
Here is what I have tried
public void inSort(){
IntNode next = top;
if(next != null){
ordInsert(next.getData());
top.setLink(next.getLink());
inSort();
}
return;
}
Right now it is just an infinite recursive method which crashes my program.
I need to know what I am doing wrong and how to go about it not the code.
Input: 3000 400 40 120 70
Expected Output : 40 70 120 400 3000
Tracking the infinite recursion
The problem you are having now is that the node being sorted into the list is not being removed.
Let's have a look at the example input you provided:
Input: 3000 400 40 120 70
At the start, top is pointing to the 3000 node. In inSort, next is set to point where top points, and 3000 is the value to be inserted.
With the call to ordInsert, the initial condition
while(next!=null && next.getData()<newItem)
is never true, because next.getData() is always equal to newItem (it is the very object you are trying to reinsert!). As a consequence, the top node is recreated and inserted at the top and top consequently set to point there. Thus, the list is now:
3000 3000 400 40 120 70
with top pointing to the first element.
Since next is a reference to the same object as top, tops link is now set to the 3000 next to it. And you find yourself in the same situation as before, only the list is preceded by another element.
Calling again to inSort() will repeat that process indefinitely to yield the result
3000 3000 ... 3000 400 40 120 70
Issues
Elements to be inserted are not removed, leading to an expansion of the list
Resetting of top in inSort invalidates the premise for the while loop in ordInsert.
Suggested solution
The method ordInsert only works if the list, the new element gets inserted into, is already sorted. So, the strategy should be:
1. Detach element at index 0
2. Sort remaining list
3. insert detached element into sorted list
Thus, first save a reference to the top of the list, then advance the top marker to the next element and set the detached (previous top) element to point to null. That won't invalidate the premise of the while loop because top is still referencing the top of the list (the element at index 0 has been removed from the list).
Then make the call to inSort() of the now shortened list. After a successful call, use ordInsert() to insert the detached element. Best to make it work with IntNode rather than creating an entirely new element.
For the recursion to work, assert that top is referencing the beginning of the list (shortened [after detaching] or extended [after reinserting]) so that for any recursion step, the program's state is valid. And watch out for the base case, when top == null.
In inSort, the stop condition is if(next == null).
next is top and top is the head of the list (not the last node). Therefore, the recursion never stops.
Also, instead of sorting the existing linked list, you are inserting new data, the code duplicates nodes infinity.
I'm doing this assignment right now and one of the methods I need to write is getting a node reference given a certain String label.
One of the fields in my node contains a String called label and I want to check my entire tree to see if a particular node contains that specific String.
How would I go about doing this?
So far I have a method called getNodeReference that takes a String label and I want to do something like:
if(root != contain the String) {
--search the left children, middle children, then right children (I guess its a ternary tree)
}
if (left.node != contain the String) {
--keep searching left, if you cant find it go on to middle. etc.
}
The kind of operation you are referring to are called Tree Traversals. A good reference on how to perform them is:
https://en.wikipedia.org/wiki/Tree_traversal
But an example could be (in pseudocode):
Set up a queue.
Enqueue the root.
While the queue is not empty:
Dequeue an item.
If the item matches, return it.
Else
Iterate over the children of the item, enqueuing them
in order from left to right.
This is referred to as a Breadth First Search. It is up to you to figure out how to do a similar Depth First Search, but I'll give you a hint. A stack might be involved.
Q: When are they used? (Homework question)
1st and last node in the list
Sometimes used as 1st and last nodes in the list
Never used as 1st and last nodes in the list
Wikipedia says,
A sentinel node is a specifically designated node used with linked
lists and trees as a traversal path terminator. A sentinel node does
not hold or reference any data managed by the data structure.
I'm thinking B but I don't really know.
Look, there is a significant difference between a "Dummy" node and a "Sentinel" node.
Dummy nodes "Sometimes get used as first and last nodes in the list".
When you initiate a linked list a common approach is to create a dummy node, and interestingly it's the last node at the same time.
Obviously not always first or last nodes of a LL are dummy records.
Please note that you can use a dummy node without any data and a null pointer as a sentinel that shows the last node in the LL.
You may wonder is it possible to have a LL without any dummy node?
Answer: Yes. You can hold initialization of your LL until the insertion of the first data entry, and to that point just have null pointer as the LL, and after insertion(s) hold a pointer to the head node and always use a null pointer as "Next" node of the tail node.
I refer you to this page for more insight.
Yes, Answer is 2. Sometimes used as first and last nodes in the list.
To answer this question you need to understand need and use of dummy node. I will explain this with the help a link list problem.
Say you have Delete a node in a singly link list and only pointer to that node is given to you, How do you delete ??
Answer : If we have HEAD node we can simply traverse until we find that node and delete it, but this will not work if we have pointer of last node, because last node points to NULL.
Here we need DUMMY node. which is a blank node that help us build new node of delete node later.
In case of doubly link list this problem can be in either direction.
Definition of dummy node : a dummy node at the front/end of the list that is there only to reduce the need for special-case code in the linked-list operations. It is an empty template to build new nodes later.
problem here is we don't have any head node. We only have pointer to target node only.
Solution will be like this we will copy data from next node to node what to delete and delete next node.
struct node *temp = node_ptr->next;
node_ptr->data = temp->data;
node_ptr->next = temp->next;
free(temp);
but this will not work if we have pointer of last node, because last node points to NULL.
Here we need DUMMY node. which is a blank node that help us build new node of delete node later.
In case of doubly link list this problem can be in either direction.
Definition of dummy node : a dummy node at the front/end of the list that is there only to reduce the need for special-case code in the linked-list operations. It is an empty template to build new nodes later.
Reference : http://pages.cs.wisc.edu/~vernon/cs367/notes/4.LINKED-LIST.html
In algorithms questions, we always pass the head of the linked list as the argument. If you are changing the position of the head node and you need to return the new head node, the problem will be how are you gonna return the new head. That's why we initially create a dummy node and dummy.next will point to the head. So, if you are potentially modifying the head of list, use dummy node
One of Apple interview questions is to swap the pair of nodes and return the new head in one way linked list.
Since, the linked list is one way, after we swap the first 2 nodes (in question u need to swap all), how are we gonna keep the reference of the head node. That's where we use the dummy node.
dummy=new ListNode(dummyValue, head)
dummy node will always point to the first node, so re return dummy.next
There is one common question in linked list questions: Remove the n'th node from the end.
To solve this, we initialize slow pointer and fast pointer. first we traverse the fast pointer n times so when we keep traversing the fast pointer and we reach the end of the list, slow pointer will be n node behind.
However, to remove a node from a linked list, we just have to cut the pointer to that node. If nothing points to that node, it will be garbage collected.
For example, if we have 5 nodes and we need to delete 2nd node from the end, the 3rd node from the end points to the node that we are trying to delete. So we actually have to keep a reference of 3rd node from the end and assign its next to the last node. So we create a dummy node and slow pointer will be starting from there. It will be easier to show on an image:
If the nth node was point to the head of the linked list, we would have returned null. since dummy.next is head, we will return dummy.next
I once ran into the problem where I did this:
previous is the previous node of current. current is the current node we are looking at.
This is so prev.next points to the element after current.
prev.next = current.next;
However, I forgot why this doesn't work and we have to do this instead:
Node temp = current.next;
prev.next = temp;
current = temp;
Why do we need a temp variable to delete a node from a linked list
Since when you remove reference from an element
You do NOT need temp variable as in code below to release link from current to the next.
prev.next = current.next;
current.next = null; // release this link
current = null; // optional
After removing we have: current is not referenced by previous node and current.next is null.
Because linkedList is a list where each element has a link to the next element (actually, it also has a link to the previous element).
Thus, it is very easy to remove an element from the list in comparison to ArrayList where elements are stored in array and removing an element means shifting every element in array after it.
In computer science, a linked list is a data structure consisting of a group of nodes which together represent a sequence. Under the simplest form, each node is composed of a data and a reference (in other words, a link) to the next node in the sequence; more complex variants add additional links. This structure allows for efficient insertion or removal of elements from any position in the sequence.
Refer here Linked List
We create Temp node in the delete method because we do not want to modify the start node pointer since we always need the start pointer of a linked list, so instead of modifying the start pointer we create a temporary pointer.