java remove node linked list - java

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.

Related

Remove All Occurrences of a Given Value from a Doubly Linked List

Alright, so cut a long story short, what I'm trying to do here is remove all instances of value e from a doubly linked list. As far as I know, my logic is at least mostly right, but for some off reason it isn't actually removing any of the nodes in my test cases.
public boolean removeAll(int e) {
DIntNode dummy = head,next = null;
if (head == null)
return false;
while (dummy != null) {
if (dummy.getData() == e) {
next = dummy.getNext();
dummy.getNext().setPrev(null);
dummy = next;
return true;
}
else
dummy = dummy.getNext();
}
return false;
}
This is what I currently have for my code of the metho. My logic here was to use a dummy DIntNode that starts at the head and a "next" node to help me shrink the list, so to speak. In other words, if the list was something like "1<-> 1 <-> 2 <-> 3", the function would change it to "2<->3", in theory. The reason this is a boolean function is because I'm required to return true if the given value is removed form the list.
Is there just another step in the logic that I'm missing, or is the methodology itself just unreliable? I'm very unsure at this point, so any and all help would be greatly appreciated.
You set
dummy.getNext().setPrev(null);
But previous node also have reference to next node you try to remove. You should set this reference to next active value.
That because when you want to get all linked list previous value still know about node you remove, because of next node reference
You can try with the following code:
if (dummy.getData() == e) {
DIntNode temp = dummy.getPrevious();
temp.next = dummy.getNext();
temp = dummy.getNext();
temp.previous = dummy.getPrevious();
return true;
}
This used the previous reference. So the previous node will now have reference to the next node of your dummy node (node to be deleted). And similarly, the next node of dummy node will have reference of previous node of your dummy node. So, the dummy node will loose its connection/link from its doubly link list and that's what we want!
Please try.
Two issues with the code:
When relinking a doubly linked list, where removing B from A - B - C, you need to set the next node for A to be C as well as the previous node for C to be A. With trying to keep you method names:
A.setNext(current.getNext());
C.setNext(current.getPrev());
With your code, if you find an occurrence, you return, which means that no other instances will be removed since you jump out of that method. You will probably need a new boolean removed variable, that is set to false, return true changed to removed = true and return false changed to return removed.
The method exits after the first encounter of 'e'.
If you want to remove all instances of 'e', then you should have something like this:
boolean listChanged = false;
while (dummy != null) {
if (dummy.getData() == e) {
// update list
...
listChanged = true;
}
...
}
return listChanged;
Also, you should not write your code like this:
dummy.getNext().setPrev(...); // throws NPE if next is null

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.

returning an object from a method dealing with Linked List nodes

i'm writing a method using linked list to delete even number indexes from the list (i'm not using List<object> list = new LinkedList<object>() <--- i know this is kinda easier.., i'm implementing node class in this problem (which i'm really confused at right now.)
Well, the problem tells me to delete the even number indexes from a List, and return a new List. But i don't know what to do here (this method is in LinkedIntList class that also contains ListNode class)? And please check my code if it's right or what i can do to improve. Thanks.
public ????????? removeEvens() {
    ListNode current = front;
    while(current.next!= null) {
        current = current.next.next;
    }
    return ???????????;
}
EDIT: i've tried NodeList but it still give me an error so i guess i'll post a pic.
Since you want to return a new List, the return type should be a ListNode or a LinkedList.
public ListNode removeEvens(){
ListNode current = front;
//Since we are setting current's next to current.next.next, we need to make
//sure that we don't get a null point exception.
while(current.next!=null){
//removes all event nodes.
current.next = current.next.next;
current = current.next;
}
return current;
}
A LinkedList can be represented by a ListNode. If you want to return a LinkedList, simply change the return type of the function and return a new LinkedList with the current list node passed into the constructor.

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

beginner java code regarding an add method for adding two nodes in a linked list

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.

Categories