Update: Thanks a lot to everybody who responded!!! It made me feel that I'm not completely alone in my efforts to learn Java. Please excuse me, but I guess I didn't clarify enough what I don't get about linked lists and the exercise application -
first - how can a class definition contain an object of itself, OK I know that this is recursion but it's still a very strange and alien concept to me.
second - how exactly can a linked list object "link" to another node?
third - if two objects are separated by an equals sign it means what - that the second object disappears and what's left of it is it's "name" that now points to the first object or vice versa?
then - the thing that I don't get about the program I quoted below is the following: after the linkList class is instantiated it's constructor is called and it gives the object of class Link private Link first the value of null, i.e. sets it pointing to nothing. Then, when the first new node is created the method public void insertFirst is called, it gives the object values to its variables and then something absurd happens - the object first that points to nothing is assigned to the new item thus making both objects pointing to nothing and with the first = newLink; I'm completely lost...
I'm doing a college course on Algorithms and Data structures and since the professor is really mean and his explanations are useless I'm trying to learn on my own from a book called Algorithms and data structures by Robert Lafore.
Now I'm learning Linked lists and there is the following code example for a linked list implementation in the book:
Link.java:
class Link
{
public int iData; // data item
public double dData; // data item
public Link next; // next link in list
public Link(int id, double dd) { // constructor
iData = id; // initialize data
dData = dd; // ('next' is automatically
} // set to null)
public void displayLink() { // display ourself
System.out.print("{" + iData + ", " + dData + "} ");
}
}
LinkList.java:
class LinkList {
private Link first; // ref to first link on list
public LinkList() { // constructor
first = null; // no links on list yet
}
public boolean isEmpty() { // true if list is empty
return (first==null);
}
// insert at start of list
public void insertFirst(int id, double dd) { // make new link
Link newLink = new Link(id, dd);
newLink.next = first; // newLink --> old first
first = newLink; // first --> newLink
}
public Link deleteFirst() { // delete first item
// (assumes list not empty)
Link temp = first; // save reference to link
first = first.next; // delete it: first-->old next
return temp; // return deleted link
}
public void displayList() {
System.out.print("List (first-->last): ");
Link current = first; // start at beginning of list
while(current != null) // until end of list,
{
current.displayLink(); // print data
current = current.next; // move to next link
}
System.out.println("");
}
}
LinkListApp.java:
class LinkListApp {
public static void main(String[] args) {
LinkList theList = new LinkList(); // make new list
theList.insertFirst(22, 2.99); // insert four items
theList.insertFirst(44, 4.99);
theList.insertFirst(66, 6.99);
theList.insertFirst(88, 8.99);
theList.displayList(); // display list
while( !theList.isEmpty() ) { // until it's empty,
Link aLink = theList.deleteFirst(); // delete link
System.out.print("Deleted "); // display it
aLink.displayLink();
System.out.println("");
}
theList.displayList(); // display list
}
}
I just CANNOT understand the code that inserts and displays items in the linked list class.
How can it be that newLink.next = first; and first = newLink; after the new object is created?
Please help!
Each Link holds a reference .next to the next Link element (except the last element, having .next = null.
A LinkList holds a reference (.first) to the first Link object it contains.
In order to insert a new Link at the front of the LinkList, we need to do the following:
Create a new Link object to insert in front (newLink).
Let the newly created Link point to the previous first Link object as its .next
Reset the .first reference of the LinkList to the newLinkobject, effectively overwriting the previous reference (marked with a cross below).
This is exacly what's going on:
public void insertFirst(int id, double dd) {
Link newLink = new Link(id, dd);
newLink.next = first;
first = newLink;
}
What may have confused you is that this list implementation is LIFO (Last In First Out), so the last element inserted is the first one returned when traversing.
newLink.next = first; puts the former first element as the new element's next (so second)
first = newLink; puts the new element at the top of the list
There are many possible ways for linked lists to behave differently, it depends on what kind of collection you want them to be (a queue, a stack) or different patterns (single or double linked, circular) and so on.
Assume we have a linked list like this:
first -> Link("monday")
Link("monday").next -> Link("tuesday")
Link("tuesday").next -> Link("wednesday")
Now we want to have the week starting with "sunday".
First we create a new link for "sunday":
Link("sunday") # newLink = new Link(id,dd)
and tell it, that it's follower is "monday"
first -> Link("monday")
Link("sunday").next -> Link("monday") # newLink.next = first
Link("monday").next -> Link("tuesday")
Link("tuesday").next -> Link("wednesday")
Finally we correct the start of the week
first -> Link("sunday") # first = newLink
Link("sunday").next -> Link("monday")
Link("monday").next -> Link("tuesday")
Link("tuesday").next -> Link("wednesday")
You add the new Link to the head of the LinkList object by setting head = newLink;
You append the existing list to the new element's next by setting newLink.next = first;
As your new node is being added, it is being added to the start of the LinkedList, so since the pointer First was pointing to the first node in the List, but on the arrival of a newNode to the same list, this Pointer first must point to the newly added node, and the newly added node must point to the previously established first node, so that it can become the first node of the Linked List.
Hopefully this diagram can explain a bit further :
That's why you have to write newLink.next = first; and first = newLink;
Related
I have a linked list and I want to remove a node from it based on the data inside of it.
public Node deleteNode(String a){
Node<String> temp = findNode(head, a);
temp = temp.previous;
System.out.println(temp.data);
temp = temp.getNext().getNext();
return temp;
}
This is the code I have for it, which in theory should work but it's doing nothing.
If I remove the "temp = temp.previous;" line the code works but removes the node after the one I want removed. If I run it as is then it just doesn't remove anything.
The print statement shows that I'm currently working with the node previous to the one found using the findNode(head, a) method but somehow something just gets screwed up.
If you want to remove a node, you need to alter the next and previous fields of neighbouring nodes.
if (temp.next!=null) {
temp.next.previous = temp.previous;
}
if (temp.previous!=null) {
temp.previous.next = temp.next;
}
That will link temp's two neighbouring nodes to each other, bypassing temp.
Then it would probably make sense to remove temp's references to its neighbours so it doesn't look like it is still part of the list.
temp.next = null;
temp.previous = null;
If you have separate references to the head and/or tail of your list, you need to reassign them in the case where the node you removed lay at the beginning or end of the list.
I am trying out my own implementation of a double-linked list. While my code is currently functioning, I can't really figure out why. Below is an exerpt of the code:
public class DLList<E> {
public class Node {
/** The contents of the node is public */
public E elt;
protected Node prev, next;
Node() {
this(null);
}
Node(E elt) {
this.elt = elt;
prev = next = null;
}
}
Node first, last;
DLList() {
first = last = null;
}
// inserts an element at the beginning of the list
public Node addFirst(E e) {
Node node = new Node(e);
if(first==null){
first = node;
last = node;
}else{
node.next = first;
first.prev = node;
first = node;
}
return node;
}
}
In the else-block of the addFirst-function the variable next is set to the reference first and two lines later the reference first is set to the Node-object node. Surspringly (to me) this works. Shouldn't this mean that node.next is actually set to node as we basically get node.next = first = node?
EDIT:
Answers:
You're changing references (pointers) - which is why it does [work]. The last line first = node; simply changes first from pointing to the previous node to point to the current node. – alfasin
I think I figured it out. In my code I am not changing the actual object, I am just changing what objects are being referenced. In plain english my code in the else-block can be read as:
1. Set node.next to reference the object that first is referencing.
2. Set first.prev to reference the object that node is referencing.
3. Lastly, reassign first to reference the object that node is referencing. – erikejan
There are some issues in your code as mentioned in the comments, but to answer your question, no, it's not the same. In Java, you assign variables by value and not by reference. So, if you modify first after assigning it to node, it doesn't modify the value of node.
It's like,
a = 5;
b = a;
a = 4;
Here, value of b will be 5. It doesn't get changed to 4.
Compiler executes each statement sequentially. So it will not know that the value of a will be modified in the future or not.
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.
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))
Im currently having trouble trying to understand linked lists. I have some code that uses nodes and have been asked to use an iterative approach to create a new node with the string parameter stored in it, at the index position specified in the integer parameter. The old node at the index position should follow the newly inserted node.
These are the fields:
// a string that contains the full name on the filesystem of an image file.
private String imageName;
// a reference to the next ImageNode in the linked list.
private ImageNode next;
//temporary node created to start the set of nodes
private ImageNode temp = this;
And this is the code i have written so far: Note that getNext() returns the next node.
private void addIter(String imageFileStr, int pos) {
int count = 0;
while(temp.getNext() != null){
temp = temp.getNext();
count++;
if(count == pos){
temp.getNext() = ???
}
}
}
Is this the right way to go about adding two nodes? If so, this would currently only work if the node needs to be added to the end of the set of current nodes. How would i modify the code so that it allows me to add a node in the middle of set and have the old nodes follow it as stated above ("The old node at the index position should now follow the newly inserted node.")?
And finally, how do i create a variable (x) that is equal to the input from addIter so that i can set temp.getNext() = x? (currently depicted by question marks in the code).
It's impossible to completely answer this without seeing more of your implementation, but here are few things:
temp.getNext() = ??? doesn't make sense, you can't assign to a function call. You will need to add a method setNext(ImageNode node) that sets the next node to the given value.
In your add method, You need to create a new node using the input string (lets call it newNode, find the node currently at pos (lets call it existingNode), then you will need to do a couple things:
Set newNode.next to the node currently after existingNode (or null if it's the end of the list)
Set existingNode.next to newNode.
This will probably end up looking something like this:
public void add(String item, int pos) {
if (pos > length) {
// Probably just throw an out of bounds exception
}
Node existingNode = head;
for (int i = 0; i < pos; i++)
existingNode = existingNode.getNext();
Node newNode = new Node(item);
newNode.setNext(existingNode.getNext());
existingNode.setNext(newNode);
}
Let's assume you have nodes A,B,C and want to insert a new node (D) at pos 3. You will need to iterate through your list up to node 2, i.e. B. Then you save the link to the node following B into a temporary variable, say TempC: Node TempC = B.getNext().
After that you set TempC as the next node after the one you are going to insert: D.setNext(TempC). Then you set D as the next node after B: B.setNext(D). The resulting set will be: A, B, D, C
P.S. here I assume that the first node is 1, not 0.
you definitely need to create a new object and save the data into it. New object must point at the next node where you want to add it and then temp must point at the object.