I have a *, and I'm trying to get my remove method to removes and returns a specific targeted items. I tried a lot of different way trying to make it work, but it keeps giving me the NPE.
Here is my first remove():
Here is my second remove() that was able to make the code compile:
Here is my LinearNode:
Student class:
To remove should be fairly straightforward and you already have the general idea:
public Student remove(Student items) {
LinearNode previous = null,
current = head;
// iterate over all the nodes starting at the head, maintaining a reference to the previous node as you go
while (current != null && current.items.compareTo(items) != 0) {
previous = current;
current = current.next;
}
// At this point you have either a) found the Node with matching items or b) not found it
if (current == null) {
// not found in the list
return null;
}
// At this point you know where the Node is, and you have a reference previous node as well
// so it's easy to reattach the linked list to remove the node
if (previous == null) {
// The head node was the match if previous is not set, so make sure to update the head Node accordingly
head = current.next;
}
else {
previous.next = current.next
}
return current.items;
}
Use try catch on the suspicious code, till you find which line causing the problem.
This will tell you if you are looking at the right place.
For Example:
while (current != null) {
try{//1st level try
if(current.items.compareTo(items) == 0) {
try{ //2nd level try
if(previous == null) {
head = head.next;
return items;
}
else {
previous.next = current.next;
return items;
}
}catch(NullPointerException e ){
StackTraceElement t = e.getStackTrace()[0];
System.out.println("catch lvl 2 at line: " + t.getLineNumber());
}
}
else {
previous = current;
current = current.next;
}
}catch(NullPointerException e){
StackTraceElement t = e.getStackTrace()[0];
System.out.println("catch lvl 1 at line: " + t.getLineNumber());
}
}
EDIT:
You can try to put this "try catch" and wrap all your main function:
try{
...
}catch(NullPointerException e ){
int i=0
for( StackTraceElement t : e.getStackTrace()){
System.out.println("stack[" + i + "]: " + t.getLineNumber());
i++;
}
}
EDIT2
public Student remove(Integer studentId)
{
LinearNode previous = null;
LinearNode current = head;
while (current != null) {
//if everything is OK you can remove the 2 ifs
if(current.items == null){
//something is really wrong on insert
}
else if(current.items.getId() == null){
//something is really wrong on insert
}
else if( studentId.compareTo(curent.items.getId()) == 0) {
//return value is curent.items;
if(previous == null) {
head = head.next;
return curent.items;
}
else {
previous.next = current.next;
return curent.items;
}
}
else {
previous = current;
current = current.next;
}
}
//not found!
return null;
}
Related
would anybody be able to help me with this problem I've been having? I'm trying to implement a doubly linked list for the first time and have been frustrated trying to get my code to work for my remove class:
public void remove(int data) {
if(length == 0) {
return;
}
if (head.data == data){
head = head.next;
length--;
}
Node current = head;
while (current != null) {
if(current.data != data) {
current = current.next;
length--;
}
current = current.next;
}
}
I know this question may have been asked before, but I was unable to understand the differences in other people's code as it was much more complex. It's been a really difficult day trying to get this one method working without getting a NullPointerException and help would be appreciated! Thanks.
You want to remove a single node or part of the front list?
If you are trying to remove a single node, your current node is used as a pointer to find the node to be removed, when you find such node, you can change the node's value, if this is the last element, you can set the previous node's next node to null, else set the previous nodes' next node to the node's next node, and change the node's next node's previous node to the node's previous node.
public void remove(int data) {
if(length == 0) {
return;
}
if (head.data == data){
head = head.next;
length--;
}
Node current = head;
while (current != null) {
if (current.data != data) {
current = current.next;
} else {
if (current.next == null) {
current.pre.next = null;
} else {
current.pre.next = current.next;
current.next.pre = current.pre;
}
length--;
}
}
}
Try this:
public void remove(int data) {
if (isEmpty()) {
throw new NoSuchElementException();
}
if (this.size == 1 && this.head.getData() == data) {
this.head = this.tail = null;
this.size--;
return;
}
if (this.head.getData() == data) {
this.head = this.head.getNext();
this.head.setPrevious(null);
this.size--;
return;
}
if (this.tail.getData() == data) {
this.tail = this.tail.getPrevious();
this.tail.setNext(null);
this.size--;
return;
}
for (Node<T> current = this.head; current != null; current = current.getNext()) {
if (current.getData() == data) {
Node<T> previous = current.getPrevious();
Node<T> next = current.getNext();
previous.setNext(next);
next.setPrevious(previous);
this.size--;
return;
}
}
throw new NoSuchElementException();
}
I am trying to delete an specific element from the linkedlist, however i am getting null pointer exception. Could any one pls fix my below mentioned code...
public void deleteElement(T num)
{
Node<T> ele = new Node<T>(num);
if(head == null){
System.out.println("Underflow");
return;
}
Node<T> temp = head;
while(temp != null)
{
if(temp.data == num){
temp.previous.next = temp.next;
return;
}
else
temp = temp.next;
}
size--;
}
You should modify inside your while loop like this:
while(temp != null)
{
if(temp.data == num) {
if(temp.previous != null) {
temp.previous.next = temp.next;
}
// you have to link-up the next's previous with temp's previous too
if(temp.next != null) {
temp.next.previous = temp.previous;
}
temp = null; // to deference the node and let garbage collector to delete/clear this node
break; // don't return here otherwise size-- won't execute
}
temp = temp.next;
}
Before referencing temp.next and temp.previous as lvalue you should check whether they are null otherwise it will throw NullPointerException.
Hope it helps!
You have to find Node object whose data is equal to T num. Use such loop:
for (Node<T> x = first; x != null; x = x.next) {
if (num.equals(x.data)) {
unlink(x);
return true;
}
}
Where first is pointer to first node. In method remove you have to unlink found Node x from linked list:
T remove(Node<T> x) {
// assert x != null;
final T element = x.data;
final Node<T> next = x.next;
final Node<T> prev = x.prev;
if (prev == null) {
//if x is first node(head)
first = next;
} else {
// link x.next to x.prev.next
prev.next = next;
//unlink x
x.prev = null;
}
if (next == null) {
//if x is last node(tail)
last = prev;
} else {
// link x.prev to x.next.prev
next.prev = prev;
//unlink x
x.next = null;
}
// reset data
x.data = null;
size--;
return element;
}
I am making a simple linked list and I'm trying to implement a method that allows me to delete the last node of the linked list. At some point, my method is wrong and I'm not sure where the error is and how to fix it. Here is the code!
public Nodo deleteEnd() {
Nodo aux;
if (head == null) {
throw new NoSuchElementException("Element cant be deleted");
} else {
aux = head;
while (aux.next.next != null) {
aux = aux.next;
}
size--;
}
return aux;
}
You need to assign the next of the last but not least node to null:
if(head.next == null) {
// head is last!
head = null;
size = 0;
} else {
previous = head;
current = head.next;
// while current is not last, keep going
while(current.next != null) {
previous = current;
current = current.next;
}
// current is now on last!
previous.next = null;
size--;
}
public Nodo deleteEnd() {
if (head == null) {
throw new NoSuchElementException("Element can't be deleted");
}
Nodo current = head;
Nodo next = current.next;
// Check if there is only the head element.
if ( next == null )
{
size--;
head = null;
return current;
}
// Skip to the end.
while (next.next != null) {
current = next;
next = next.next;
}
// Break the link to the next element.
current.next = null;
size--;
return next;
}
Add
aux.next = null;
after the while loop - then there will be no reference to the last element.
try reducing one .next:
while (aux.next != null) {
aux = aux.next;
}
I am trying to add Point into a linked list, in order to keep track of the frequency of each data entry. Everytime I run this code it gives me a NullPointerException. I don;t understand why, to me it seems as if after it adds the frequency it creates a gap but I cant seem to fix it.
if(firstNode == null)
{
addPair = new Pair(aData, 1);
firstNode = new Node(null, addPair, null);
lastNode = firstNode;
currentNode = firstNode;
numberOfNodes++;
}
else
{
currentNode=firstNode;
for(int count = 0; count<numberOfNodes; count++)
{
if(currentNode.data.fst().equals(aData))
{
addPair = new Pair(aData,currentNode.data.freq()+1);
if(count==0)
firstNode= new Node(currentNode,addPair,null);
currentNode = new Node(currentNode,addPair,null);
break;
}
if(count == (numberOfNodes-1) && currentNode.data.fst() !=(aData))
{
addPair = new Pair(aData,1);
Node newNode = new Node(currentNode, addPair, null);
currentNode.next = newNode;
lastNode = newNode;
numberOfNodes++;
break;
}
currentNode = currentNode.next;
}
}
numberOfEntries++;
private class Node
{
private Node previous;
private Pair data;
private Node next;
private Node(Node previousNode, Pair<T,Integer> addPair, Node nextNode)
{
previous = previousNode;
data = addPair;
next = nextNode;
}
}
If you are receiving a NPE at the line if(currentNode.data.fst().equals(aData)) then either currentNode == null or currentNode.data == null or currectNode.data.fst() == null. The first thing to do in diagnosing the problem is to find out which of these is the case. I suggest you put the following statements before this line and rerun your code:
assert currentNode != null;
assert currentNode.data != null;
assert currentNode.data.fst() != null;
Apart from that diagnosis there are a number of ways you could make your code safer. Firstly you really have no need to use a count to iterate through your linked list. Much safer would be to end when the next pointer is null:
for (Node current = firstNode; current != null; current = current.next) {
if (current.data.equals(aData)) {
// increment counter
return;
}
}
The main problem is in this line
firstNode= new Node(currentNode,addPair,null);
When you increase frequency of first node you are not setting the next Node, so you got list of only one node, but with size of many. Similar problem with line
currentNode = new Node(currentNode,addPair,null);
Also all first if statement is wrong. You are corrupting links in the list, it should be something like this
if (currentNode.data.fst().equals(aData)) {
addPair = new Pair(aData, currentNode.data.freq() + 1);
// create new node
Node c = new Node(currentNode.previous, addPair, currentNode.next);
// set links to new node
if (currentNode.previous != null) {
currentNode.previous.next = c;
}
if (currentNode.next != null) {
currentNode.next.previous = c;
}
if (count == 0) {
firstNode = c;
}
break;
}
To simplify your code and decrease possible errors I could recommend to write some function like incFrequency() in Pair class. Then in the loop do something like this
if (currentNode.data.fst().equals(aData)) {
currentNode.data.incFrequency();
break;
} else if(count == (numberOfNodes-1) && currentNode.data.fst() !=(aData)) {
// add new node to the end
}
Also you could rewrite you for loop
currentNode = firstNode;
// iterate through list
while (currentNode != null) {
// process currentNode
...
// move to the next node
currentNode = currentNode.next;
}
I am trying to store the strings in a LinkedList. I am not allowed to pre-sort, but find the place and pass the string to the linked list. When i pass the strings through text file, the string do not go through the last else condition.
My input file has
joe
appy
appz
zebra
cat
When it reaches appz, it doesn't go through any statement. It is supposed to insert the last else condition and print 5, but doesn't do that.
/**
* Gets the string and arranges them in order
* #param newString
*/
public void store(String newString) {
LinkedListNode current = head;
System.out.println(newString);
// if no element in the list
if (current==null){
System.out.println("1");
makeNode(newString);
}
// if only 1 elements in the list
else if(current.getNext()==null ){
System.out.println("2");
if(newString.compareTo(current.getName())<0){
insertBefore(current.getName(),newString);
} else{
insertAfter(current.getName(),newString);
}
}
// if the element is smaller than the head in the list
else if(newString.compareTo(current.getName()) < 0){
System.out.println("3");
LinkedListNode temp = makeNode(newString);
temp.setNext(current);
head=temp;
}
// if the element is greater than the tail in the list
else if(newString.compareTo(findTail().getName()) > 0){
System.out.println("4");
insertAfter(findTail().getName(),newString);
}
// for more than two elements in the list
else{
System.out.println("5");
while(!(newString.compareTo(current.getName())>0 && newString.compareTo(current.getNext().getName())<0 ) && current.getNext()!=null){
current=current.getNext();
}
if(newString.compareTo(current.getName())<0){
insertBefore(current.getName(),newString);
}
else{
insertAfter(current.getName(),newString);
}
}
} // end of store()
You have some issue with the insertBefore. I updated it.
public void insertBefore(String later, String name){
if(head==null){
head = new LinkedListNode(name,null);
}
else if(head.getName()==later){
LinkedListNode newNode = makeNode(name);
newNode.setNext(head);
head=newNode;
}
else{
LinkedListNode current = head;
while(current.getNext().getName()!=later){
current=current.getNext();
}
LinkedListNode newNode = makeNode(name); // create the new node
newNode.setNext(current.getNext());
current.setNext(newNode);
}
} // end of insertBefore()
When you are traversing, you are not supposed to change the head reference. To traverse, simply do this:
Node tmp = head;
while(tmp != null) tmp = tmp.next;
This will become very handy to figure out where to insert new nodes or where to go to remove existing nodes.
Your class should also have methods to addFirst, addLast, insertBefore, insertAfter. In the code below, Object is whatever data type your need (in your case, String)
public void addLast(Object item)
{
if(head == null)
{
addFirst(item);
}
else
{
Node<Object> tmp = head;
while(tmp.next != null)
{
tmp = tmp.next;
}
tmp.next = new Node<Object>(item, null);
}
}
public void addFirst(Object item)
{
head = new Node<Object>(item, head);
}
public void insertAfter(Object key, Object item)
{
Node<Object> tmp = head;
while(tmp != null && !tmp.data.equals(key))
{
tmp = tmp.next;
}
if(tmp != null)
{
tmp.next = new Node<Object>(item, tmp.next);
}
}
public void insertBefore(Object key, Object item)
{
if(head == null)
{
return null;
}
if(head.data.equals(key))
{
addFirst(item);
return;
}
Node<Object> previous = null;
Node<Object> current = head;
while(current != null && !current.data.equals(key))
{
previous = current;
current = current.next;
}
//insert between current and previous
if(current != null)
{
previous.next = new Node<Object>(item, current);
}
}
In my opinion, you should not have a nested if/else construct to figure out where to insert. That should be up to the method you are invoking.
Secondly, the conditions you are using to control the flow of execution in your code are disparate. Your IF condition is if the list is empty. If it is, create a new node and add it to the list. That condition is followed by checking for a list containing only one node. After that, you are not checking for the length of the list. The expected logic is that you should be checking for a list size greater than one; and yet this is your fall through case (the last else). If you are going to be doing that kind of check outside the insert methods, then do something like this (stubbing your code):
if (current==null){
System.out.println("1");
makeNode(newString);
}
// if only 1 elements in the list
else if(current.getNext()==null ){
System.out.println("2");
if(newString.compareTo(current.getName())<0){
insertBefore(current.getName(),newString);
} else{
insertAfter(current.getName(),newString);
}
}
// if the list has more than one element
else
{
// figure out where it goes (before or after) and insert
}
If you notice, the else/if and else blocks do basically the same thing. Therefore, your code can (and should) be simplified as follows:
if (current==null){
System.out.println("1");
makeNode(newString);
}
// if the list has one or more elements
else
{
// figure out where it goes (before or after) and insert
}