Dummy nodes in linked lists - java

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

Related

Convert General "Family" Tree to Binary Tree (Not BST)

I am currently considering different ways to accomplish the task of converting a family-type general tree (where each parent can have as many children as necessary) to a binary tree such that the left child of the parent node is inserted to the left of the parent and the right child of the parent node is inserted to the right of the (oldest) child node and so on.
This is the structure of how the binary tree must look like when converted from the general tree: https://www.geeksforgeeks.org/convert-a-generic-treen-array-tree-to-binary-tree/
I fed in my data by creating class object GTNode for the General Tree to add the nodes with the following values being passed:
//name = value1; numChildren = value2
GTNode gtn = new GTNode (String name, int numChildren);
No issues with constructor, this is purely to illustrated the main focus of the node is indeed the name of the family member. Thus this really can't be converted and sorted by a Binary Search Tree and is not the point of the resulting program I'm trying to create.
I was able to create methods to traverse the tree just fine, but it really doesn't help in the conversion process to the CONVERTED binary tree.
Therefore I created an additional section of code to create a linked list of the data. The reason why I did this was to establish pointers along the list which would point to the correct parent to add children to. Siblings would then be added to the right of the oldest sibling based on pointers based on where we were along real-time adding of nodes in the tree. By this time you can imagine I have two pointers going in my linked list traversal and three pointers along the tree nodes.
I can't seem to make good progress on an algorithm to create this binary tree from the data. here's a little sample code mostly pseudo code to show you basically how I'm adding nodes to the converted-style binary tree based on general tree data.
p=q=first; //initialize to first node f the linked list of family data
//ex. [Tom, 2] [Marc,1] [Ron,0] [Billy, 0] where Marc and Ron are Tom's children, and Billy is Marc's child)
z=root;
//I already established x, y = root earlier and moved pointer .next in order to add children nodes to the siblings
//here we establish x and y pointers for the tree and add our root node and first child node, which will always be to the left.
//I left it out of the while loop, because I was running into problems with null pointers.
{
while (p.next!=null && q.next!=null)
{
for (i = n; i>0; i--) //int n = node.numChildren; was declared earlier and then decreased
// n-=1 to accommodate the first child being added to left of parent node;
{
//add nodes left or right to parent node: still trying to figure out the appropriate condition
//statements to determine addLeft or addRight from node
}
//here we change the pointer of the GENERAL tree parent node based on the linked list
// add new to binary tree to the right of the last child i.e.
y = new BTNode(p.value,p.numChildren);
y = x.right;
x = y.parent;
x = y; //move pointer along
q = q.next; //q moves from Tom to Marc.
n = q.numChildren;
//go to beginning of while loop and as you can see, if n>0 it iterates based on the number of children
// if n=0 exits loop and creates a new node to the right
}
}
I'm wondering if this is an acceptable track to go down in terms of operability. Optimization I'm not as focused on because this is a difficult task... but could be taken into account.
Looking for pseudocode or java code shippers that would help in establishing an algorithm along these lines, or error in my logic. Again, not looking for an argument against doing a conversion like this because I want to see what it would look like as is.
Thanks!

How to implement Doubly Linked List after the first element

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.

Why does this recursion function only set once?

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).

How to get a node reference in a binary tree?

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.

Why do we need a temp variable to delete a node from a linked list?

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.

Categories