Remove an element with single Linked List (Explanation needed) - java

I gone through one site. it has given following code set.
it works perfectly and I completed my task. But I have a doubt with this code. And I am unable to find.
Code:
public class Node
{
private int data;
private Node next;
/**
* #return the data
*/
public int getData() {
return data;
}
/**
* #param data the data to set
*/
public void setData(int data) {
this.data = data;
}
/**
* #return the next
*/
public Node getNext() {
return next;
}
/**
* #param next the next to set
*/
public void setNext(Node next) {
this.next = next;
}
Node(int d)
{
data = d;
next = null;
}
}
class Sam
{
Node head; // head of list
/* Linked list Node*/
/* Inserts a new Node at front of the list. */
public void push(int new_data)
{
/* 1 & 2: Allocate the Node &
Put in the data*/
Node new_node = new Node(new_data);
/* 3. Make next of new Node as head */
new_node.setNext(head);
/* 4. Move the head to point to new Node */
head = new_node;
}
/* Given a reference (pointer to pointer) to the head of a list
and a position, deletes the node at the given position */
void deleteNode(int position)
{
// If linked list is empty
if (head == null)
return;
// Store head node
Node temp = head;
// If head needs to be removed
if (position == 0)
{
head = temp.getNext(); // Change head
return;
}
// Find previous node of the node to be deleted
for (int i=0; temp!=null && i<position-1; i++)
temp = temp.getNext();
// If position is more than number of ndoes
if (temp == null || temp.getNext() == null)
return;
// Node temp->next is the node to be deleted
// Store pointer to the next of node to be deleted
Node next = temp.getNext().getNext();
temp.setNext(next); // Unlink the deleted node from list
}
/* This function prints contents of linked list starting from
the given node */
public void printList()
{
Node tnode = head;
while (tnode != null)
{
System.out.print(tnode.getData()+" ");
tnode = tnode.getNext();
}
}
/* Drier program to test above functions. Ideally this function
should be in a separate user class. It is kept here to keep
code compact */
public static void main(String[] args)
{
/* Start with the empty list */
Sam llist = new Sam();
llist.push(7);
llist.push(1);
llist.push(3);
llist.push(2);
llist.push(8);
llist.push(23);
llist.push(56);
System.out.println("\nCreated Linked list is: ");
llist.printList();
llist.deleteNode(4); // Delete node at position 4
System.out.println("\nLinked List after Deletion at position 4: ");
llist.printList();
}
}
Here is my doubt.
In 'deleteNode(int position)' method 'header' is assigned to new object('temp')
And below changes done with temp, I am ok with that. after this temp object copy didn't assign to header.
Node next = temp.getNext().getNext();
temp.setNext(next);
But in printList method they used header object, and it display remaining elements after removal
public void printList()
{
Node tnode = head;
while (tnode != null)
{
System.out.print(tnode.getData()+" ");
tnode = tnode.getNext();
}
}
I just wondering how could be the changes of temp object replaced with header object (without assign temp object to header object)
Please any one help me on this

Let's say we have a LinkedList 1,2,3,4,5
Inside void deleteNode(int position) method, both head and temp are pointing to the node 1. If we want to delete a node at position 2 (node with value 3) in the list, its iterating temp until position-1 which is node with value 2.
When temp is at node with value 2 then next node is 3 & its next node is 4 is assigned to next of node 2 effectively deleting 3 as 2 is pointing to 4 directly. Note its still temp node which is being altered.
head is still pointing to 1 and so printing is working fine.
If you observe carefully head is unchanged in the entire process.

The code is perfectly fine
The purpose of Header in Delete Function is to keep pointing to First Node of Linked List.
The purpose of temp in Delete Function is to travel to that node which is at position-1 location and change next linking address.
Your Question:
How the changes will be saved, if not assigning back to header?
Answer:A person of basic programming language knowledge will understand that any change to a variable occurs immediately.In case of Linked List , all Nodes are Linked to one another.If temp is assigned to header, the head of the linked list will become unreachable.Which we don't want as header is only variable pointing to head of linked list in whole program.
Temp means temporary variable which is discarded after use.

Related

How can I remove a specified node from a linked list?

I've made a remove method that removes an object from a singly linked list.
So far the method removes the first node and the second node without a problem. When removing the third node and onward the method removes everything between the specified node and the head node. My question is how can I make my method remove the specified node and not everything before it?
I know I need to keep a reference to the previous node in order to assign its next node to the specified nodes next node. This will close the gap and remove the node. I understand the logic but can't seem to implement it.
public class List_test{
public Node head;
public List(){
head = null;
}
public List(Node head_) {
this.head = head_;
Node ref = head;
}
public void remove(Node node) {
Node ref= head;
if (ref.equals(node)) {
head = head.next;
return;
}
while (ref != null) {
if (ref.equals(node)) {
head.next = node.next;
}
ref = ref.next;
}
}
public static void main(String[] args) {
new List_test();
}
For removing a node, why are you changing the head pointer? You should be using the previous node and point it to the next node of the node to be removed.
I think this page have nice explanation for this topic:
deleting node in linked list c/c++, java, python

deleteNode have problems

my question is about a exercise in lintcode which requires delet node, but for some reason my simple program won't work.
For example, input (1->2->3->4->null, 3) should output (1->2->4->null), my idea is delete next node and "copy" its value to input THIS node.
/**
* Definition for ListNode.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int val) {
* this.val = val;
* this.next = null;
* }
* }
*/
public class Solution {
/**
* #param node: the node in the list should be deleted
* #return: nothing
*/
public void deleteNode(ListNode node) {
// write your code here
ListNode pnext;
if (node != null) {
if (node.next != null) {
ListNode tempnode = node.next;
if (node.next.next != null) {
pnext = node.next.next;
}
else {
pnext = null;
}
node.next = null; //delete next node
node = tempnode; // give next node to THIS node
node.next = pnext; // link next
}
}
else node = null;
}
}
I am very confused about giving value to node, does node1 = node2 even work? I know node.val can. Can anyone simply guide me please?
You did not include in your post what actually happens, and you did not include the part where you create your list, so I can only assume what happens is that you do not delete 3, but delete 4? Or does it not delete anything at all?
So you have a method that should delete a Node, and the Node you want to delete is given as a parameter. But as your list is only linked one way you have no way of determining the node before it (which holds the reference to the node you want to delete). Actually the delete method should be as easy as this:
public void deleteNextNode(ListNode node) {
if(node == null || node.next == null) return; //nothing to delete
if(node.next.next == null){
node.next = null;
return;
} else{
node.next = node.next.next;
}
}
Although I did not test it. As long as you don't store any other references to your nodes this is sufficient, otherwise you need to call next.null explicitely in the else part.
Edit: My function deletes the Node that follows the Node you pass, but you want a function that deletes the Node you pass it. The problem here is that the previous node stores the reference to the Node that you want to delete, but you have no way of determining that Node with only the reference to the Node you want to delete. So either you use this function and always pass the previous node, or you make a wrapper function and run through the list and always safe the previous Node and call the function with that node:
public ListNode deleteNode(ListNode start, ListNode deleteMe)
{
ListNode prev = start;
if(start == deleteMe) return start.next;
while(prev.next != null) {
if(prev.next == deleteMe)
deleteNextNode(prev);
prev = prev.next;
}
return start;
}
Note that I made the function return a ListNode, this is always the first Node of the List (in case you decide to delete the first node).
I hope this helps
You are complicating it unnecessarily and it is not that tough. As I see, you are just taking the ListNode as the parameter and not the data which you want to delete. Also, since you are using if and not while or for, you'll never end up iterating the whole list.
You should modify your function to take both the node as well as the data and start using a loop to iterate the complete list.
Here is the code snippet:
private void deleteNode(ListNode node, int data) {
while(node != null && node.data != data) {
node = node.next;
}
if(node != null) {
System.out.println("Deleted Node With Data: " + node.data);
node = node.next;
}
}
I think by:
node = tempNode; // give next node to THIS node.
You meant:
node.val = tempNode.val; // give next node value to THIS node.
That way, the next node's value is copied into the current node.
Next you would want to also do:
node.next = tempNode.next;
This way, the node effectively becomes the tempNode. I think this was your intention.. ?

Inserting a new Node at the beginning of a LinkeList in Java

I have checked few posts that we have in SO.
Insert new node at the beginning of Linked-List
How do I insert a node at the beginning of a linked list?
And implemented a simple LinkedList in java that works just fine.
What I can't get my head around is how adding a new Node to the beginning of the LinkedList would actually work.
Here is how my code snippet for adding a Node to the beginning of the LinkedList looks like:
public class SinglyLinkedList
{
//Private variable to keep tab of the HEAD of the linked list.
private ListNode head;
//Private variable to keep track of the node count in this singly linked list.
private int length;
.
.
.
/**
* Insert a ListNode at the beginning of this List.
*/
public synchronized void insertAtBegin(ListNode newNode)
{
//Set current head as the next of input ListNode
newNode.setNext(head);
//Set the input ListNode as the new head of this SinglyLinkedList
head = newNode;
//Increment the SinglyLinkedList length
length++;
}
.
.
.
}//End of class SinglyLinkedList
The ListNode class represents a Single Node like so:
/**
* Represents a Node of the Linked List.
*/
public class ListNode
{
private ListNode next;
private int data;
/**
* Constructors
*/
public ListNode()
{
next = null;
data = Integer.MIN_VALUE;
}
public ListNode(int data)
{
next = null;
this.data = data;
}
/**
* Accessor methods.
*/
public int getData()
{
return this.data;
}
public void setData(int data)
{
this.data = data;
}
public ListNode getNext()
{
return next;
}
public void setNext(ListNode listNode)
{
this.next = listNode;
}
public String toString()
{
return Integer.toString(data);
}
}//End of class ListNode
The 2 lines that really confuse me are:
//Set current head as the next of input ListNode
newNode.setNext(head);
//Set the input ListNode as the new head of this SinglyLinkedList
head = newNode;
The more I try to analyze these two lines, I feel it will create a circular reference structure instead of pushing in the "newNode" in place of "head".
May be I don't quite understand how Java references are passed around.
Is there an explanation as to why the above two lines won't end up in a circular reference?
It seems you understand conceptually how the LinkedList gets a new head node. Your question is more related to Java itself.
Remember that Java is pass-by-value; When you are passing objects around, you aren't passing the value of the object - you are passing the value of the pointer to that object. Is Java "pass-by-reference" or "pass-by-value"?
So with that in mind, let me break down those 2 lines.
newNode.setNext(head)
The value in head is a pointer to a node. So the setNext function is receiving, in accordance to pass-by-value, a pointer to a node. It is NOT receiving a pointer to head.
head = newNode;
in this line, we reassign head's VALUE to be a POINTER to the newly created node. The value in newNode.next is still a pointer to the previous head.
You are encountering a very common confusion with Java, and believe me it is VERY VERY common (hence the 2k upvotes on the SO I referenced above). I hope this addresses your main source of confusion!
Imagine you have the following LinkedList:
2 -> 3 -> 4 -> 5
and you want to insert a node with a value of 1 at the beginning. Let's call this node newNode.
Now look at this line: newNode.setNext(head); You are making newNode's next value point to head, which in this case is pointing to the node with a value of 2. This is what your list looks like now:
1 -> 2 -> 3 -> 4 -> 5
However, head is still pointing to the node with the value of 2, so you have to fix that by making head point to the node with a value of 1, which is newNode. That is what the line head = newNode; does.
When your list is moving from right to left, i.e. 1 then after new node insertion it becomes 2->1 then after fresh insertion it becomes 3->2->1, In this case you need to take care of two things only : head (the first element of the list) & temporary node which is to be inserted next. Here is the pseudo code for that:
` while(you_want_to_insert_new_node) //temporary is the node to be inserted freshly
{
Insert(temporary->data); //Insert data in temporary node
temporary->next=head;
head=temporary;
}
`
When your list is moving from left to right, i.e 1->2 then it becomes 1->2->3 and so on, you need to take care of 3 things: head, the current node and the temporary. Here is the pseudo code for that:
`
current=head;
while(you_want_to_insert_new_node) //temporary is the node to be inserted freshly
{
Insert(temporary->data); //Insert data in temporary node
current->next = temporary;
current=temporary;
}

Recursion of Linked List

When given an array of integers, I'm trying to change each element with the product of the integers before it.
For example, int[] array = {2,2,3,4}; is now: {2, 4, 12, 48};
I added each element to a LinkedList, and I'm trying to do this recursively.
This is what I have:
Node curr = list.getFirst();
product(curr);
public static void product(Node curr)
{
if(curr == null)
{
return;
}
else
{
int data = curr.getData() * curr.getNext().getData();
Node newNode = new Node(data);
curr.setNext(newNode);
// product(curr);
}
}
The first product works: {2,4}, but when I try to put in the recursion, I get a stackoverflow. Any suggestions??
Edit: So the reason that I'm either getting a stackoverflow or null pointer exception is because I'm updating the list, and then trying to get the next integer(but since there's only two elements in the list, there isn't a getNext()). I'm not sure how to fix this.
It looks like you were getting a bit tied up in the recursion. I modified your method to accept a Node along with the product from the previous iteration. At each step of the iteration I update the value in the already-existing List, so there is no need for using the new operator.
public static void product(Node curr, int value) {
if (curr == null) {
return;
}
else {
int data = value * curr.getData(); // compute current product
curr.setData(data); // update Node
product(curr.getNext(), data); // make recursive call
}
}
There are actually two issues with the code.
The recursion never ends, i.e. it is not actually moving to a smaller "subproblem" as the recursion is calling the same node again
and again.
After creating a new node and modifying the next we also need to connect the node "after" the next node otherwise the link will be
lost. Please check the below method which addresses both the issues.
Although I didn't do an excessive testing it is working for simple dataset.
Original List:
2->4->5->6->8->null
Multiplied List:
2->8->40->240->1920->null
public void product(Node curr) {
if (curr.getNext() == null) {
return;
} else {
int data = curr.getData() * curr.getNext().getData();
Node newNode = new Node();
newNode.setData(data);
Node nodeAfterNextNode = curr.getNext().getNext();
newNode.setNext(nodeAfterNextNode);
curr.setNext(newNode);
product(newNode);
}
}
It is because you call recursive method on the current node, so it is actually never move forward in the LinkedList. You can simply update the next node's data and call the recursive method on it. See the code below:
Node curr = list.getFirst();
product(curr);
public static void product(Node curr)
{
Node next = curr.getNext();
if(next == null)
{
return;
}
else
{
int data = curr.getData() * next.getData();
next.setData(data);
product(next);
}
}

What happens to the initial null value set to head of Linked List?

I have been making an implementation of a Linked List to manipulate it to do various things so I could better learn it and I have come across something which I don't understand.
I have made three classes: Node, LinkedListExample, LinkedListTest
My node class looks like:
public class Node {
Node next;
Object data;
// Node constructor
public Node(Object dataValue) {
next = null;
data = dataValue;
}
public Object getData() {
return data;
}
public void setData(Object dataValue) {
data = dataValue;
}
public Node getNext() {
return next;
}
public void setNext(Node nextValue) {
next = nextValue;
}
}
My Linked List looks like:
public class LinkedListExample {
private Node head;
private int listCount;
public LinkedListExample() {
head = new Node(null);
listCount = 0;
}
public void add(Object data) {
Node temp = new Node(data);
Node current = head;
while (current.getNext() != null) {
current = current.getNext();
}
current.setNext(temp);
}
public int size() {
for (Node n = head; n.next != null; n = n.next) {
listCount++;
}
return listCount;
}
public String toString() {
String result = "";
Node current = head;
while (current.getNext() != null) {
current = current.getNext();
result += current.getData() + " ";
}
return result;
}
public String headString() {
String result = "";
Node current = head;
//current = current.getNext();
result = current.getData() + ""; /* Returns null currently */
/* If previous line replaced by result = current.getData().toString() it would result in NULL POINTER EXCEPTION */
return result;
}
}
Finally, my Linked List Test class looks like:
public class LinkedListTest {
public static void main(String[] args) {
LinkedListExample example = new LinkedListExample();
example.add(1);
example.add(2);
example.add(3);
System.out.println("The list looks like: " + example.toString());
System.out.println("The size is: " + example.size());
System.out.println("The list head is: " + example.headString());
}
}
My question is in my constructor, I create a Node object, head, and set it to null. I later go on to add three objects, 1 2 and 3 to my Linked List. I am now confused as to what is in my Linked List? Is the null value included or not? Why or why not?
When I run the program as is, my print statement would say The list looks like 1 2 3. But if I was to flip the lines within the while loop in my toString() method in LinkedListExample to look like:
current = current.getNext();
result += current.getData() + " ";
Then the output would be The list looks like null 1 2.
Does null never get replaced?
The same goes for headString(). It currently outputs The list head is: null but if I were to uncomment the previous line, I would get The list head is: 1.
On a side note, what is also the difference between using "" and toString() because as commented out in the code above, in one situation it prints out null while the other throws a null pointer exception?
Sorry if these questions are simple, I just am lost on this concept.
This is one particular way of implementing a linked list. The "head" node is not counted as part of the list.
If you counted the head node as part of the list, then when you add an item, you will find that you need to add it differently depending on whether it's the first node or not. Removing also works differently depending on whether the node is the first node.
To simplify the code, you can create a "header node" that is not used to store a value. If you do this, then you don't need to think about how to insert or remove nodes at the start of the list. Nodes with data are always after the head node, so they're never at the start.
you create a new Node and set the data value to null. So in your c'tor you create a new Node with next=null and data=dataValue=null.
So your LinkedListExample head is an element:
Node: next=null, data=null
Your add()-method creates a temporary node and sets a (temporary) current node.
Temp: next=null, data=1
Current=head: next=null, data=null
As current has no next you replace it:
Head: next=1, data=null
Next: next=null, data=1
And so on.
You head stays the same, but output null wont have an effect, it's just empty.
So, your null-head never get's replaced and the change in output is because of your
while (current.getNext() != null) {

Categories