I have a question about how Linked List stores datas and references each other.
public class LinkedList {
static class Node {
int data;
Node next;
// Constructor
Node(int d)
{
data = d;
next = null;
}
}
public static void main (String[] args) {
Node first = new Node(1);
Node second = new Node(2);
Node third = new Node(3);
Node fourth = new Node(4);
Node fifth = new Node(5);
first.next = second;
second.next = third;
third.next = fourth;
fourth.next = fifth;
second = fourth;
System.out.println(second.data + "is fourth");
while (first != null) {
System.out.println(first.data);
first = first.next;
}
}
}
This code prints out
4 is fourth
1
2
3
4
5
However, I thought it should be
4 is fourth
1
4
5
Because I changed "second" value to "fourth" value
Anyone could explain what is happening here?
It's important to understand what happens when you call a method or create a new variable in memory in order to understand this behavior. Basically, there are two portions in memory where data is stored for something like this - the stack and the heap. The stack stores static information and has a fixed size, whereas the heap can store more complicated data (i.e. objects) and has no defined limitation on size, aside from the amount of memory you have available in the first place.
When you instantiate an object in Java, the object itself (the values and properties) are defined and stored in the heap, whereas a reference to the data, or the memory address of the object in the heap, is stored in the variable on the stack. This is why when you do something along the lines of
ExampleObject o = new ExampleObject();
System.out.println(o);
prints out something like ExampleObject#fa243dsf
This output isn't the object itself, which may have certain properties that you have defined, rather it outputs the reference to the object itself. When you do something like o.exampleProperty what you've done is dereferenced the object, meaning you told Java to go into the memory address of the object and get the exampleProperty value.
Now to come back to your question, the exact same thing happens with the next property on each Node, it's not storing the object itself, but a reference to that object. Let's imagine these are the memory address locations for each of the Node instances you created (just for example purposes, these aren't the exact locations where they are being stored by Java on your machine, nor are they proper memory addresses):
first has an address of 111
second has an address of 222
third has an address of 333
fourth has an address of 444
fifth has an address of 555
Now, your LL looks like this after assigning the next values:
first.next = Node#222
second.next = Node#333
third.next = Node#444
fourth.next = Node#555
fifth.next = null
Now, when Java reaches the line second = fourth, you haven't changed the object data itself, but merely the memory address that the variable second points to. What I mean by this is that second now points to address 444, and if you run System.out.println(second);, you will now see Node#444 be outputted to the console, however, you have not modified the original object that second referred to, nor have you modified the values of the LinkedList. This means that the value at memory address 222 has not changed, and so since first.next points to Node#222, the value of the Node created and stored at address 222 is the same as it was originally. This is why when you print out second.data at the end, you get the same value as fourth.data, but why the LinkedList itself hasn't changed to what you thought it would change to. If this explanation still wasn't very clear, I suggest you look into variables storing/passing data by reference vs by value, as that is the concept that outlines the behavior you are seeing vs what you had expected.
Related
public class StackWithLinkedList<P> {
private Node top = null;
public StackWithLinkedList(){}
public void push(P val){
Node newNode = new Node(val);
if (this.top != null) {
newNode.nextLink = top;
}
this.top = newNode;
}
public void traverse(){
Node currentNode = this.top;
while(currentNode != null){
System.out.println(currentNode.val);
currentNode = currentNode.nextLink;
}
}
private class Node{
Node nextLink;
P val;
public Node(P val){
this.val = val;
}
}
}
Look at this code in the traverse(),
Node currentNode = this.top;
here an object of type Node is created that points to the already existing this.top node object.
So it means, two references pointing to the same object in memory isn't it?
But when I use the traverse() method, both the object works independently as the currentNode gets to Null after traversing but the this.top remains unchanged, holding all the nodes that have been pushed.
I tried debugging and i saw this.top has the same memory address as the currentNode.
In the end,
I am not able to figure out why is it?
You are conflating "object" and "reference". For example in the sentence
For example here:
Look at this code in the traverse(),
Node currentNode = this.top;
here an object of type Node is created that points to the already
existing this.top node object.
No object of type Node is created here (there is no new, that's how you know).
What is defined here is a (local) variable of type Node. And the reference that is stored in this.top is also assigned to currentNode.
So it means, two references
pointing to the same object in memory isn't it?
Yes, this part is again correct.
Think of a reference like a sheet of paper. The paper can be empty (i.e. the reference is null) or it can have some address written on it (i.e. it points to some object).
Now currentNode is a piece of paper that happen to have the same address written on it that this.top also has written on it (it's a tiny bit more complicated, because this is a piece of paper written on it and if you look at that address then you'll find some other piece of paper labelled top that has some address written on it, but that doesn't fundamentally change how this works).
At some point later in the code currentNode gets reassigned (i.e. the content of the piece of paper gets changed). First to a different address (i.e. the address scribbled out and replaced with another one) and then eventually with null (i.e. you scribble out the content and leave it "blank").
But just because you wrote on that piece of paper doesn't mean that the other piece of paper (found via this.top) has changed. There is no reason for to it change: they are two independent pieces of paper that at one point happen to have had the same stuff written on them.
Or put differently: assigning a new value to currentNode has absolutely no effect on the object previously referenced by currentNode.
If you had done currentNode.nextLink = null instead of (basically) currentNode = null then that would be different:
currentNode = null means "remove the address written on the piece of paper labelled currentNode.
currentNode.nextLink = null means "go to the address written on the piece of paper labelled currentNode, there find a piece of paper labelled nextLink and remove the address written on it.
The first one just changes the reference currentNode and the second one actually changes the object pointed to by currentNode.
Edit: it seems your confusion stems from the debugging view where it says currentNode = {StackWithLinkedList$Node#801}. You seem to interpret this as "currentNode is the object {StackWithLinkedList$Node#801}", but that's not what it means.
currentNode is never an object. It can't be. Java variables/fields can't hold objects. So what that display really means is: currentNode currently references the object represented as {StackWithLinkedList$Node#801}.
I am implementing singly linked list in Java, and I have a problem.
In addition and removal of nodes, many people use temporary node like this:
public Object removeFirst() {
Node temp = head;
head = temp.next;
Object returnData = temp.data;
temp = null;
size--;
return returnData;
}
Why is this temp node necessary? At first glance, I think all I have to do in order to remove first element is to change second element into head node.
So my question is that in java, what does object= object mean? Do 2 objects become exactly same inheriting every fields and methods?
temp is not needed. It is used to obtain the data of the removed Node after the head variable is no longer referencing that Node, but that can be done without it:
public Object removeFirst()
{
Object returnData = head.data;
head = head.next;
size--;
return returnData;
}
what does object= object mean?
A class provides the blueprint for objects; you create an object from a class.
The new operator returns a reference to the object it created. This reference is usually assigned to a variable of the appropriate type
Assume that you have create new object head
When you copy one object to another object, then second reference is created to the object.
Node temp = head;
If you make second object (reference) as null,this object is still accessible with first reference (head).
Do 2 objects become exactly same inheriting every fields and methods?
Yes since only reference is different but object is same.
You can find more details in oracle documentation page
When you did not create object ( instantiate class):
When you create an object with new operator:
When you assign object to another object:
In Java programs, is it right to set an object equal to another one? To be more specific, I'm studying binary trees and I noticed in the following code:
public Node find(int key)
{
Node current = root;
while(current.iData != key)
{
if(key < current.iData)
{
current = current.leftChild;
} else {
//...
}
}
}
that both Node current = root; and current - current.leftChild; are setting an object equal to another one. Is this right?
setting an object equal to another one. Is this right?
No, that's not right.
What's actually happening is, you're changing the reference of one variable to another object.
So:
Node current = root; // "current" will point at the same object as `root`.
and
current = current.leftChild; // "current" will point at the same object as `leftChild`.
note -
When assigning primitive types with = is a completely different behaviour when assigning reference types with =.
First of all, you need to need a basic concept in Java: Java does manipulate objects by reference, and all object variables are references.
So when you have Object o1 and Object o2, in fact o1 and o2 are just references to memory spaces that hold the object not the object itself.
When you have o1 == o2 , you are comparing the two references not the objects themselves but if you want to compare them you need to override the equals() method.
Now, let's talk about your case:
Node current = root; this means that current and root are referring to the same object (the same location in memory). So there is only one object and two references.
public class ListNode{
ListNode next=null;
int val;
public ListNode(int val){ this.val=val; } }
ListNode node=new ListNode(3);
ListNode mm=node; mm=null;
System.out.println(node==null); -------> false
ListNode nn=node; nn.val=100;
System.out.println(node.val); --------->100
First I assigned node to mm, but after I assigned null to mm, node did not change to null. But when I assigned node to nn, and I changed the value of nn, the value of node changes! Do you know why?
You need to understand the difference between objects and variables (which "point to" or "refer to" objects).
Let's walk through your code.
Part one
ListNode node=new ListNode(3);
ListNode mm=node;
mm=null;
ListNode node=new ListNode(3);
Here we have done two things:
We've created a new ListNode object with a val equal to three. This object lives out in memory, on the heap.
We've assigned this new object to the variable named node. So node refers to or points to this object.
node ---------> ListNode(val = 3)
Next,
ListNode mm=node;
Now we have another variable called mm, and it is now referring to the same object that node refers to.
node ---------> ListNode(val = 3)
/
mm ---------/
Finally,
mm=null;
Here we say that mm now refers to nothing (null). However, the object in memory remains unchanged.
node ---------> ListNode(val = 3)
mm ---------> (nothing)
Part two
ListNode nn=node;
nn.val=100;
System.out.println(node.val); // Prints "100"
ListNode nn=node;
Again, we have another variable called nn and it is now referring to the same object that node refers to.
node ---------> ListNode(val = 3)
/
nn ---------/
Next
nn.val=100;
Here, we are actually saying: "Take whatever object nn refers to, and set his val member to 100."
node ---------> ListNode(val = 100) [note value changed!]
/
nn ---------/
Lastly,
System.out.println(node.val);
Here we are saying "Take whatever object node refers to, and get the value of his val member." But remember, node and nn are referring to the same object. So the change we made on the previous line is reflected by this output too!
Conclusion
In many programs, we may have many variables that point to one particular object. No matter which variable we use to get to that object, the changes will be made and show up via any of the variables that point to him.
Changes to the variables themselves mean nothing to the other variables! That is why assigning null to mm had no consequence to node. The only way to make an object "go away", is to ensure that there are no remaining references to that object. At this point it is eligible for garbage collection.
node and mm are two separate variables, referencing to the same object. When you assign null to mm, you're simply removing the reference to the object stored in mm, not affecting the object or the value stored in node. On the other hand, when you change the value in the object, none of the variables that reference that object change, only the values inside the object and so when you print the value referenced by any of them, you see the updated value.
class Nodetype
{
int info;
Nodetype next;
Nodetype(int i)
{
info=i;
next=null;
}
}
My textbook has this code to create Linked List dynamically.
The question is, when the programs is executed line-by line, it defines variable 'info' as type 'int' & then variable 'next' as Nodetype.
What is actually happening here?
does it mean that variable 'next' will contain -
Constructor 'Nodetype'
int info
Nodetype "next" where "next" will again have all 1,2,3 & then 3 will again have 1,2,3...and so on....till infinity?
I'm really irritated because I'm unable to understand how it works, can someone easily explain this?
Your code follows very well the definition of list: a list is null or an element followed by a list.
The "element", in your case, is defined by an int value, and the "followed by" part is the next variable; in Java variables (when they are not literals, as int values are) are actually pointers, so while they are not initialized they don't store any valid value and they don't point to any memory area (i.e. their value is null), so while the next variable is kept as-is your element is not followed by any other. To dynamically add elements to your list you need a pointer to the last element you added, otherwise you would not be able to find them again:
int i = 0;
Nodetype head = new Nodetype(i++);
Nodetype last = new Nodetype(i++);
head.next = last;
while (i<5) {
Nodetype temp = new Nodetype(i++);
last.next = temp;
last = temp;
}
while(head) {
System.out.println(head.info);
head = head.next;
}
Notice how, with the last few lines, you lose the head pointer and you have no way to get back the starting point of your list.. Keep that in mind when working with lists ;)
At first variable next doesn't point to any object(it points to null). At some time you will make it point to another node with next = new NodeType(number). The idea is that you use composition - you have one instance of class which has a reference to another instance. It is like nodeA points to nodeB, nodeB points to nodeC. Here you have three instances and the first instance has a reference to the second instance and the second instance has a reference to the third instance. The third instance is the last one and its next instance points to null.
the field next is a reference to an object of type Nodetype. at first it will point to nothing - since it is instantiated to null. when you assign a value to it, it will point to that value only, nothing will continue infinitely unless you create a cycle within the list.
You created class NodeType and inside of the class you defined object of that class. So that object (in your example next) will have int info variable NodeType next object and constructor.
It will contain Null, as the variable is not initialized to any value.
Nodetype is your class that defines the data a node instance will contain as well as the reference to the next node in the linked list. That reference to the next node will be an object of type Nodetype. Nothing too difficult here, this is the classic implementation of a Linked List.
You might want to check out this great linked list resource from Stanford.
The way this works is that the list is made up of single elements, each of which only has a pointer to the one that comes after it:
Nodetype next;
The information each element within the list actually holds is this:
int info;
You can think of a list like a "chain": it's not really a single object, but a compound object of a number of links. From each link, you can only see the next link (or, in case of linked lists that have references in both directions: the next and the previous link), so in order to have all elements available, you will have to keep the reference to the first element in the "chain".
Note: List objects are single objects that have a reference to the first link of the "chain".
next is a reference to another Nodetype instance. If next == null it means the current element is the last one in the list.
Let's see an example:
Nodetype node = new Nodetype(0); // i = 0, next = null
Nodetype anotherNode = new Nodetype(1); // i = 1, next = null
node.next = anotherNode; // now the first node has a ref to the second
#include<stdio.h>
#include<stdlib.h>
void print_list(int *arr,int *size,int *capacity)
{
printf("capacity = %d; size = %d; elements = ",*capacity,*size);
for(int i=0;i<(*size);i++){
printf("%d ",arr[i]);
}
printf("\n");
}
int * push_back(int *arr,int data,int *size,int *capacity)
{
int *b;
if(*size == *capacity){
*capacity = 2*(*capacity);
b = (int *)malloc(sizeof(int)*(*capacity));
for(int i=0;i<(*size);i++){
b[i]= arr[i];
}
b[*size]=data;
*size=*size+1;
print_list(b,size,capacity);
return b;
}
arr[*size]=data;
*size=*size+1;
print_list(arr,size,capacity);
return arr;
}
int main()
{
int size=0;
int n;
int x;
int *arr;
arr = (int *) malloc(sizeof(int));
int capacity=1;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&x);
arr=push_back(arr,x,&size,&capacity);
}
}
its working.