java List type variable - java

I have been breaking my head with below code which I made. The problem is that when I do
tail.child = null;
it is also making my childPoint's child as null.
tail is instance variable with below definition:
public List tail;
public void removeMultiLinkList() {
List headPoint = head;
while (headPoint.next != null) {
List childPoint = headPoint;
while (childPoint.child != null) {
tail.next = childPoint.child;
tail = tail.next;
tail.child=null;
childPoint = childPoint.child;
}
headPoint = headPoint.next;
}
}
I have made this method to solve the problem of multilevel link list and convert it into linear singly link by in non recurssive manner

Examine what you are doing:
tail.next = childPoint.child;
tail = tail.next;
In here, tail is childPoint.child (reference identity)
Then, you do:
tail.child=null;
This means, you actually set childPoint.child.child = null; - because chilePoint.child and tail are different names for the same object.
And then, you assign:
childPoint = childPoint.child;
But you assign childPoint to the same object you just changed - so the new childPoint's child, is null!
A very easy workaround is to copy by value (by creating a copy constructor) the elements from one list to the other.
An alternative might be to keep copying references - but without changing child at all. At the end of your algorithm, do some post-processing and set e.child = null for each element e in your list.

Related

Why we can use Node head = null without instantiate the 'head' in Java?

I am reading someone's code. It is about getting input numbers and convert those number into a Linked list. The part of the code is like this:
class Node {
int value;
Node next;
Node() {
next = null;
}
}
Firstly We need to create a head node to indicate head and we let the head be null like this Node head = null.
My limited experiences of java tell me that head is supposed to be a Node type object here. So why we can use Node head = null without instantiate the head?
I think at least I should create Node head = new Node(); then we can use Node head = null;
Anyone can explain it to me?
Node head = null;
This line states that there are no items in the linked list. This is valid in Java and indicates that although head can contain a Node object (or an object of a derived class), it is currently empty.
To add an item to the list, there is likely some code such as:
public void addItemToLinkedList(int value) {
if (head == null) {
head = new Node();
head.value = value;
} else {
...
}
}
So if there is no first Node (when head equals null) then head is created. Otherwise if head already exists, the else block would execute which would look for the end of the list and add another Node.
head is supposed to be a Node type object here
This is optional. Java allows head to be a Node object, or null, to indicate that head is not referencing any nodes at all.
The value of null is special in Java. It is allowed to go wherever an object can go. It indicates that the variable to which you assign null is empty. This is perfectly fine, assuming that the rest of your program deals with null checking.

How does ListNodes work in java implementation

I was reading about nodes in java .. I found this example .. I just can not understand how the ListNode works in java .. I did read about it but I still can not understand it .. Here is the code :
public class SingleLinkedList<E> {
private ListNode<E> first;
/ ** Creates an empty list. * /
public SingleLinkedList() {
first = null;
}
/ ** Returns a list of the elements that match e.
otherwise returned an empty list. * /
public SingleLinkedList<E> allMatches(E e) {
SingleLinkedList<E> res = new SingleLinkedList<E>();
ListNode<E> n = first; // why we create a new node and put it equal to first ?
while (n != null) {
if (n.element.equals(e)) {
ListNode<E> tmp = new ListNode<E>(n.element);
tmp.next = res.first; // what is happening here ?
res.first = tmp; // why we do this step?
}
n = n.next;
}
return res;
}
private static class ListNode<E> {
private E element;
private ListNode<E> next;
/* Creates a listnode which contains e. */
private ListNode(E e) {
element = e;
next = null;
}
}
}
I do not understand the allMatches method ... I put some comments next to each line I did not understand it ...
First question: ListNode<E> n = first; // why we create a new node and put it equal to first ?
Second question: tmp.next = res.first; // what is happening here ?
Third question : res.first = tmp; // why we do this step?
Fourth question :if (n.element.equals(e)) { // can we use == instead of equals in this case?
Please can you answer my questions? thanks
First question: ListNode n = first; // why we create a new node and put it equal to first ?
No new node is created here. A reference is created and it refers to first. New Node is created only when new operator is used. It is assigned with first because we are going to scan through the linked list one by one. Just having the reference to first node is sufficient because first contains reference to the second if it exists.
Second question: tmp.next = res.first; // what is happening here ?
the method allMatches(e) returns a linked list of all nodes which has element value equal to e.element. Whenever there is a match, create a new node. This new node points to the current first element. This is half complete. Read the next question answer and then try to understand.
Third question : res.first = tmp; // why we do this step?
Here res.first is updated with the newly created node. Why? Because we made our new node to point to the current first element. As this new element precedes current first element, we have to update the first element to point to newly created node.
Fourth question :if (n.element.equals(e)) { // can we use == instead of equals in this case?
Nope. Because == works only if both are same object. Here there might be chances that objects are different but there contents are equal. It really depends on how it is being used in the application. In general, the answer is NO.
I think the reason why the the new node n is pointed at first is because you're going to create a new separate linked list called res that is a new linked list of just the results of the search and you want it pointed at the first node in the linked list you will examine namely the list that calls the method.
The reason why tmp.next = res.first is because we are going to insert tmp as the new first element in res and we will attach the old res on after it. Does that make sense? I think drawing a picture of what is going on will help clear up what is happening.

Implementation of removeFirst() method in SLinkedList in java

I got the following code from one book for implementing a singly linked list. And I don't understand some lines of code in the removeFirst() method, which removes the first node from the LinkedList.
class ListNode{
private String element;
private ListNode next;
public ListNode(){
element = null;
next = null;
}
public ListNode(String s, ListNode n){
element = s;
next = n;
}
//Access method
public String getElement(){
return element;
}
public ListNode getNext(){
return next;
}
//Modify method
public void setNext(ListNode n){
next = n;
}
}
public String removeFirst(){
if(head == null)
return null;
else{
ListNode temp = head;
head = head.getNext();
temp.setNext(null); //Which I don't understand, is it necessary?
size --;
return temp.getElement();
}
}
It seems that the statement temp.setNext(null); can be omitted. So why it is here, does it has anything to do with the garbage colletion in java. Since I am new to Java, any suggestions or ideas?
It depends on the entire implementation of the linked list, which you have not included in your question. However if it is possible for objects to hold a reference to a node even after if has been removed from the list, then the line is necessary.
Suppose we have a long chain of nodes A -> B -> C -> .... Suppose all of these nodes have been removed from the list, but that we still hold onto a reference to A. If all the nodes still held a reference to the next, this would prevent all of the nodes from being garbage collected. Simply setting the next node to be null ensures that only A cannot be garbage collected.
It is likely that implementations of a linked list do mean that references to nodes can be retained. For example, many implementations of Iterator hold a reference to the current node.
Consider this code:
Iterator<String> iterator = list.iterator();
while (i.hasNext()) {
if ("foo".equals(i.next())) {
i.remove();
break;
}
}
// lots more code
This code searches a list for the first occurrence of the String "foo". If it is found, it removes the "foo" from the list and breaks from the loop. The trouble with this is that the Iterator i is still in scope for the remaining code and still holds a reference to a node. This node may be in the middle of the list if the break occurred. Without setting next to be null, this would prevent all subsequent nodes from being garbage collected while i is still in scope, even if the list is cleared.
Note that you should generally make an iterator local to a loop anyway, like this
for (Iterator<String> i = list.iterator();;i.hasNext())
Let us suppose, single linked list of nodes is : A --> B --> C --> D with head node as A. Now, lets go though your removeFirst() method. When it get called, if(head == null) condition doesnt satisfy because our head node "A" is not NULL. Then it execute else statement,
temp = head //take head reference into temporary variable
head = head.getNext(); //As we want to delete first Node which is head so we are setting head to next node (i.e. head --> next) which is Node "B"
Now, to delete A (first Node) we need to break connection between A (which is previous head)--> B (current head) and that will done by
temp.setNext(null); //so out linked list became A B-->C-->D
and then as one node is deleted so in next statement it decreases size of link by size--.
I think we also set the temp reference to NULL as temp=NULL to make deleted node eligible for garbage collection.

Deep Copy Constructor for Linked List in Java

I have a HW assignment and only one small part of it is to make a copy constructor which makes a Deep Copy of the linked list which you have entered in its parameters.
I understand that this means, that the List you have entered remains unchanged, and that the new linked list is isolated from the "old" one. My code gives me a new list which is exactly the same as the old one (the one you enter as a parameter) and this is what I want, but the old one is changed.
Here is the constructor:
public SortedLinkedSet(SortedLinkedSet<T> copy) {
if (copy == null) {
this.firstNode = null;
} else{
SortedLinkedSetNode firstNode1 = new SortedLinkedSetNode(copy.getFirstNode().value);
this.firstNode = firstNode1;
// so basically I am chaining elements from "copy" to firstNode1 and then making "this" = to firstNode1.
while (copy.firstNode.next !=null) {
firstNode1.add(copy.getFirstNode().next.value);
this.firstNode = firstNode1;
copy.firstNode = copy.firstNode.next;
// at the end of this loop I have a successful new linkedList with the same value, but "copy" has been changed
}
}
}
If for example I enter a linked list which has the values (1,2,3) -- with this constructor i get back a new linked list with values 1,2,3 but the old one just has 1.. If someone can help me with why this is going wrong it would be great. Thanks
UPDATE : As Ireeder pointed out, and with a test I did, I am almost sure that the problem is in the statement :
copy.firstNode = copy.firstNode.next;
i deleted the current code, and did the following test:
SortedLinkedSetNode firstNode = new SortedLinkedSetNode(copy.getFirstNode().value);
this.firstNode=firstNode;
firstNode.add(copy.getFirstNode().next.value);
this.firstNode = firstNode;
firstNode.add(copy.getFirstNode().next.next.value);
this.firstNode = firstNode;
and this Works perfectly(but I knew in advance i'm testing with only 3 element list).How would i do it with a while loop without using such a statement as :
copy.firstNode = copy.firstNode.next;
I have to somehow move along the "copy" list ?
It's hard to say what the problem is without seeing the source for SortedLinkedSetNode, but you seem to be modifying your original with this statement:
copy.firstNode= copy.firstNode.next;
This probably advances firstNode to the end of your original linkedset, resulting in the original having one element. Also, confusingly the original is called "copy". You may want to rename it so you can understand your code better.
When creating a deep copy, you shouldn't modify the structure you want to copy.
In this case, you can just use a temporary variable to store the reference to the current node you are on, without modifying your original data structure. Try this:
this.firstNode = firstNode1;
// so basically I am chaining elements from "copy" to firstNode1 and then making "this" = to firstNode1.
SortedLinkedSetNode currentNode = copy.firstNode;
while (currentNode.next !=null) {
firstNode1.add(currentNode.next.value);
this.firstNode = firstNode1;
currentNode = currentNode.next;
}
First the original to copy from, is called copy, like in do copy this one?
You did have some mix-up with the correct nodes and the code was not kept simple enough.
A recursive solution to simplify things seems appropriate:
public SortedLinkedSet(SortedLinkedSet<T> original) {
Objects.requireNotNull(original);
this.firstNode = copyNodes(orignal.firstNode);
}
private SortedLinkedSetNode copy(SortedLinkedSetNode originalNode) {
if (originalNode == null) {
return null;
}
SortedLinkedSetNode node = new SortedLinkedSetNode(originalNode.value);
node.next = copy(originalNode.next);
return node;
}
If the node's value would need deep copying too, that could be done at one place.
A loop would still be simple. One way:
private SortedLinkedSetNode copy(SortedLinkedSetNode originalNode) {
SortedLinkedSetNode firstNode = null;
SortedLinkedSetNode previousNode = null;
while (originalNode != null) {
SortedLinkedSetNode node = new SortedLinkedSetNode(originalNode.value);
if (firstNode == null) {
firstNode = node;
} else {
previousNode.next = node;
}
previousNode = node;
originalNode = originalNode.next;
}
return firstNode;
}

Java LinkedStack next = head?

So I have this code for Linked Node Stack (in short Linked Stack) and It confuses me very much! I have an exam tomorrow on that and it confuses me a lot! So take a look:
class Node<T> {
T item; // data in node
Node<T> next = null; // successor node
Node(T item0, Node<T> next0) {
item = item0; next = next0;
}
}
That is easy to understand no problem, we create a class called Node (it's a data structure) which contains an item of type T (can be String, Integer etc..) and another Node called next to indicate the next Node in line. Everything is clear. Off with that!
Now's time for the Stack itself, so here's the code:
class Stack<T> {
private Node<T> head = null; // first node (null if empty)
Stack() {}
Stack(int n) {}
boolean isEmpty() {return(head==null);}
boolean push(T t) {
head = new Node<>(t,head);
return true; // always space available
}
T pop() {
if (head==null) return null;
T t = head.item;
head = head.next;
return t;
}
}
Now here's where I lose my mind! OK so! First off when we initiate the Stack we create a Node with name head okay! Got it and it's null yes! Next, black magic to me is when we use the push(T t) method. So we say head = new Node<>(t, head) okay okay! slow down there fellow! We replace the existing null head with a new Node which contains the data t and as the next node, it carries itself?? so head = data, head(null,null)..? What if we add a 2nd element? it's going to be again head = data, head(data, head(null, null)... ?
Please explain this to me in plain english! :(
The line
head = new Node<>(t,head);
is executed in the order
1) new Node<>(t,head)
2) head = ...
So when you create the new Node object you pass in the old value of head, not a reference to itself.
To be less confusing this line can be rewritten as
Node<T> oldHead = head;
head = new Node<>(t, oldHead);
So when the stack is empty head = null
When we add one item head = (item1, null)
When we add another item head = (item2, (item1, null))
The Node created by push does not contain a reference to itself. When you perform an assignment in Java, the variable being assigned (on the left-hand side of the equal sign) is not altered until after everything on the right side is fully resolved and constructed.
Therefore, at the time that Java executes the Node constructor to create the new head node, the value of head within the Stack object still points to the previous head. The new Node for head is thus created with the new data, plus a reference to the previous head Node. Then, only after the new Node object is fully created (and has a next value pointing to the previous head), the value of head within the Stack object is assigned to the newly-created object.
I think you are over thinking this. So the way a stack works is similar to a linked list. So if you have an empty list, head = null. You got that part right.
So what you are doing when you call push is adding that new node to the top, so it would be the new head node.
head = new Node<>(t,HEAD);
now the new node is at the top of the list and the second argument of Node (which is HEAD)is pointing to the old node that was the head of the linked list.
so on first push, it isn't hard to understand:
first call to push: head = new node(t, NULL) because the old head node is NULL
second call to push: head = new node(t, head) and head (the second argument here) is pointing to what was the old head and is now the next item on the list
When you do head = new Node<>(t, head), you are updating the head of the stack to a Node with Node.item = tand Node.next = oldHead, which in this case is null
because you haven't put anything in it.
If we add 1 element to an empty stack we get Node(data1,null). If we add a second item to the stack we get Node(data2, Node(data1, null))

Categories