Where to place DeleteNode in Java Node class? - java

I have the following Node class used to implement linked list:
class Node {
Node next = null;
int data;
public Node (int d) {
data = d;
}
void AppendToTail (int d) {
Node end = new Node(d);
Node current = this;
while (current.next != null) {
current = current.next;
}
current.next = end;
}
}
And I want to create a method that given a Node, it will delete it from a Linked list. So, I know how to create a function like this. But I am unsure how would I make it fit in my class.
Node deleteNode(Node head, Node toDelete) {
Node n = head;
if (n.data == toDelete.data) {
return head.next;
}
while (n.next != null) {
if (n.next.data == toDelete.data) {
n.next = n.next.next;
return head;
}
n = n.next;
}
return head;
}
However, I am failing to see how would I put that into my Node class. Any suggestions?

Make the function a static function in the Node class.

A problem I see would be you not putting the append and delete functions into the linked list class rather than in the node class. You should have the node class be totally separate from the linked list class. Therefore you can have the append and delete methods in the linked list class that add and delete instances of your node class. This helps you because then you don't have to worry about the node class one its created, you can just focus on the implementation in the linked list class.

Related

How to create object of a non static class enclosed inside another class in Java?

I am trying to create a method that reverses a Linked List. I have a class that creates a linked list
public class LinkedList<t> {
public class Node {
t item;
Node next;
}
private Node firstNode;
public Node getFirstNode() { return this.firstNode; }
public void appendToTail(t item){
if(this.firstNode == null){
this.firstNode = new Node();
this.firstNode.item = item;
return;
}
Node current = this.firstNode;
while(current.next != null){
current = current.next;
}
current.next = new Node();
current.next.item = item;
}
}
The method for reversing the linked list is in my "Main" class
public static LinkedList reverseLinkedList(LinkedList<Integer> l){
LinkedList.Node current = l.getFirstNode();
LinkedList<Integer> reverse = new LinkedList<Integer>();
LinkedList.Node head = reverse.getFirstNode();
while(current != null){
LinkedList.Node newHead = new reverse.Node();
newHead.item = current.item;
newHead.next = head;
head = newHead;
current = current.next;
}
return reverse;
}
For every new node that I want to add in the front of my new reversed linked list I need to create a new instance of "Node" class which enclosed inside the "LinkedList" class. "Node" class cannot be static since its "item" attribute is set to the same generic type from "LinkedList" type. So, I need a instance of the class "LinkedList" so that I can access "Node" class and create its object. In the above code I have used the "reverse" instance on "LinkedList" to do exactly that. But I get an error saying "Package reverse does not exist". This must be because I am trying to use it as a package. How may I solve this issue?
I must be able to solve this issue by separating "Node" class from "LinkedList". Is there anyway else I can do so without doing that?
Update this line:
LinkedList.Node newHead = new reverse.Node();
, To be
LinkedList.Node newHead = reverse.new Node();
If the requirement is only to reverse linkedlist, use Collections.reverse method which takes a list as a parameter and returns the reversed list.
I'm not seeing a problem with creating Node as static. Does doing it this way fix the problem? I've changed the type parameter names to make it more clear what is being declared and when an existing type parameter is being reused.
public class TestList<T> {
private Node<T> head;
private static class Node<X> {
X element;
Node<X> next;
}
public void add( T element ) {
Node<T> node = new Node<T>();
node.element = element;
if( head != null )
node.next = head;
head = node;
}
public T get() {
return head.element;
}
}
class External {
public static <Z> void reverse( TestList<Z> arg ) {
TestList.Node<Z> temp = new TestList.Node<>();
temp.element = arg.get();
// etc.
}
}

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.. ?

Linked list - insert before method causes the linked list to continue forever

When I call this insert before method, it does what it is supposed to do at first, but then it causes the linked list to keep going on and on forever until i click stop (with system out print). I can't find where it goes wrong in this method
private boolean insertBefore(Node aNode, Node beforeNode)
{
Node currentNode;
Node prevNode;
//aNode= new Node();
currentNode = this.getHead();
while(currentNode!=null && currentNode.getNext()!=aNode)
{
if(currentNode == beforeNode)
{
prevNode = this.getPrevious(beforeNode);
prevNode.setNext(aNode);
aNode.setNext(beforeNode);
//aNode.setNext(currentNode);
return true;
}
currentNode = currentNode.getNext();
}
currentNode.setNext(beforeNode);
return false;
}
This is much simpler than the code specified above, given you have a doubly-linked list there is no need to loop over all the elements:
private boolean insertBefore(Node aNode, Node beforeNode) {
if(beforeNode.getPrevious() != null) {
beforeNode.getPrevious().setNext(aNode);
aNode.setPrevious(beforeNode);
} else {
head = aNode;
}
aNode.setNext(beforeNode);
beforeNode.setPrevious(aNode);
}
If the beforeNode is at the head of the list, your new node becomes the head.
Otherwise, there is a node behind your beforeNode. This must now point at your new node.
Either way, your new node's next pointer points at the beforeNode node.

Trouble with an inner iterator classes remove method

Hi I am making a linked list data structure and within the list I define an iterator inner class. I am currently having trouble with the remove method. The functionality that I want is that it cannot be called on the if the next has not been called or the current element in the list has been removed already. Here's what I have.
private class ListItr implements java.util.Iterator<E>{
private Node<E> currentNode;
private Node<E> nextNode;
private Node<E> previousNode;
public ListItr(List<E> theList){
previousNode = new Node<E>(null);
currentNode = new Node<E>(null);
nextNode = theList.head;
currentNode.setSuccessor(nextNode);
}
public boolean hasNext(){
return nextNode != null;
}
public E next(){
if(nextNode == null)
throw new NoSuchElementException();
previousNode = currentNode;
currentNode = nextNode;
nextNode = nextNode.getSuccessor();
return currentNode.getElement();
}
public void remove(){
if(currentNode == null)
throw new IllegalStateException();
nextNode = currentNode.getSuccessor();
previousNode.setSuccessor(nextNode);
currentNode = null;
size--;
}
}
As you can see this will successfully remove the node in the list by splicing around it, setting the current node to null. However if it is called on the first without calling next, it will still run when I do not want it to. I can hack around it by adding a flag nextNotCalled, setting it to true in the constructor, then setting it false when next is called however I feel that that is not the way to go about it...
If the question is in general how to do it, I'd look at how Josh Bloch and Neil Gafter did it. Look at the class definition for Itr (line 330).

Categories