This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 1 year ago.
I just tried to implement a linked list and when I only added two elements, it threw NullPointerException in the toString method in the debugger, but I can't get why. It's OK while it's empty, it prints [], but then it throws an error. Maybe you could help me to figure out what's wrong with my toString() method?
The desirable output is [A, B, C] or [] if a list is empty.
My whole code:
import java.util.Iterator;
import java.util.NoSuchElementException;
public class ListImpl implements List {
private Node head;
private Node tail;
private static class Node {
Object data;
Node next;
Node(Object d) {
data = d;
next = null;
}
}
#Override
public void clear() {
if (size() > 0) {
head = null;
tail = null;
}
}
#Override
public int size() {
int size = 0;
Node currentNode = head;
while (currentNode != null) {
size++;
currentNode = currentNode.next;
}
return size;
}
public Iterator<Object> iterator() {
return new IteratorImpl();
}
private class IteratorImpl implements Iterator<Object> {
#Override
public boolean hasNext() {
return head != null;
}
#Override
public Object next() {
if(hasNext()){
Object data = head.data;
head = head.next;
return data;
}
return null;
}
}
#Override
public void addFirst(Object element) {
Node newNode = new Node(element);
newNode.next = null;
if (head == null) {
head = newNode;
}
else {
newNode.next = head;
head = newNode;
}
}
#Override
public void addLast(Object element) {
Node newNode = new Node(element);
newNode.next = null;
if (tail == null) {
tail = newNode;
}
else {
newNode.next = tail;
tail = newNode;
}
}
#Override
public void removeFirst() {
if (head == null) {
System.err.print("The first element is absent");
}
head = head.next;
}
#Override
public void removeLast() {
if (head == null)
System.err.print("Your list is empty");
if (head.next == null) {
System.err.print("There is only one element");
}
// Find the second last node
Node second_last = head;
while (second_last.next.next != null)
second_last = second_last.next;
// Change next of second last
second_last.next = null;
}
#Override
public Object getFirst() {
if(head!=null) {
return head.data;}
else
throw new java.util.NoSuchElementException("List is empty");
}
#Override
public Object getLast() {
if(head == null){
throw new java.util.NoSuchElementException("List is empty");
}
Node last = head;
while (last.next != null)
{
last = last.next;
}
return last;
}
#Override
public Object search(Object element) {
Object result = null;
while (head.next != null)
{
if (head.data.equals(element)){
result = head.data;
}
}
return result;
}
#Override
public boolean remove(Object element) {
boolean isFound = false;
if(head == null) {
throw new NoSuchElementException("List is empty!");
}
if(head.data.equals(element)) {
head = head.next;
return true;
}
Node currentNode = head;
Node previousNode = null;
while(currentNode !=null) {
if(currentNode.data.equals(element)) {
isFound = true;
break;
}
previousNode = currentNode;
currentNode = currentNode.next;
}
if(currentNode == null) {
return isFound;
}
currentNode = previousNode.next;
previousNode.next = currentNode.next;
currentNode.next = null;
return isFound;
}
#Override
public String toString() {
Node current = head;
if(head == null) {
return "[]";
}
StringBuilder result = new StringBuilder();
result.append("[");
while(current.next != null) {
result.append(current.data + ", ");
current = current.next;
}
result.append(tail.data + "]");
return result.toString();
}
public static void main(String[] args) {
ListImpl list = new ListImpl();
list.addFirst("FirstElement");
list.addFirst("SecondElement");
System.out.println(list);
}
}
The problem is in the line
result.append(tail.data + "]");
You don't update the tail in the method addFirst() and in other methods too, if you correct that, it should work.
Feel free to add comments to my answer for clarifications.
Related
So im following along this playlist about data structures and in this video to conclude the linked list part, the professor explain we need an inner class called IteratorHelper.
Video:
https://www.youtube.com/watch?v=bx0ebSGUKto&list=PLpPXw4zFa0uKKhaSz87IowJnOTzh9tiBk&index=21
This is the code in my github with the linked list implementation and the main class called tester:
https://github.com/Ghevi/Algos-DataStructures/tree/master/src/com/ghevi/ads/linkedlists
The problem is that the tester class can't compile. If I instantiate the linked list as an ListIterator i can't access its methods. I also can't iterate trough it regardless of having the IteratorHelper inner class.
In the video he writes "implements ListI<>" is just a shorter version for ListIterator<>?
Sorry im just a beginner.
package com.ghevi.ads.linkedlists;
import java.util.ListIterator;
public class Tester {
public static void main(String[] args) {
ListIterator<Integer> list = new LinkedList<Integer>();
int n = 10;
for (int i = 0; i < n; i++)
list.addFirstWithTail(i);
int removedFirst = list.removeFirst();
int removedLast = list.removeLast();
for(int x : list){
System.out.println(x);
}
}
}
The video is not very clear, but basically LinkedList should implement Iterable, not ListIterator. IteratorHelper should implement ListIterator (see 4:20 timestamp).
Here's the fixed code:
package linkedlists;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.NoSuchElementException;
// Notes at Notes/Singly LinkedList.txt
public class LinkedList<E> implements Iterable<E> {
#Override
public Iterator<E> iterator() {
return new IteratorHelper();
}
class IteratorHelper implements ListIterator<E>{
Node<E> index;
public IteratorHelper(){
index = head;
}
// Return true if there is an element to return at the pointer
#Override
public boolean hasNext() {
return (index != null);
}
// Return the element where the pointer is and mover the pointer to the next element
#Override
public E next() {
if(!hasNext())
throw new NoSuchElementException();
E val = index.data;
index = index.next;
return val;
}
#Override
public boolean hasPrevious() {
return false;
}
#Override
public E previous() {
return null;
}
#Override
public int nextIndex() {
return 0;
}
#Override
public int previousIndex() {
return 0;
}
#Override
public void remove() {
}
#Override
public void set(E e) {
}
#Override
public void add(E e) {
}
/* For version older than java 1.8
public void remove(){
throw new UnsupportedOperationException();
}
public void forEachRemaining(){};
*/
} // inner class (can only be accessed by the outer class)
class Node<E> {
E data;
Node<E> next;
public Node(E obj){
data = obj;
next = null;
}
} // inner class (can only be accessed by the outer class)
private Node<E> head;
private Node<E> tail;
private int currentSize;
public LinkedList(){
head = null;
tail = null;
currentSize = 0;
}
public void addFirst(E obj){
Node<E> node = new Node<E>(obj);
// The order of these 2 lines is fundamental
node.next = head;
head = node;
currentSize++;
}
public void addFirstWithTail(E obj){
Node<E> node = new Node<E>(obj);
if(head == null){
head = tail = node;
return;
}
// The order of these 2 lines is fundamental
node.next = head;
head = node;
currentSize++;
}
// O(n)
public void slowAddLast(E obj){
Node<E> node = new Node<E>(obj);
if(head == null){
head = tail = node;
currentSize++;
return;
}
Node<E> tmp = head;
while(tmp.next != null){
tmp = tmp.next;
}
tmp.next = node;
currentSize++;
}
// O(1)
public void fasterAddLast(E obj){
Node<E> node = new Node<E>(obj);
if(head == null){
head = tail = node;
currentSize++;
return;
}
tail.next = node;
tail = node;
currentSize++;
}
public E removeFirst(){
if(head == null){
return null;
}
E tmp = head.data;
if(head == tail){
head = tail = null;
} else {
head = head.next;
}
currentSize--;
return tmp;
}
public E removeLast(){
if(head == null){
return null;
}
if(head == tail){
return removeFirst();
}
Node<E> current = head; // Can also write Node<E> current = head, previous = null;
Node<E> previous = null;
while(current != tail){
// The order is crucial
previous = current;
current = current.next;
}
previous.next = null;
tail = previous;
currentSize--;
return current.data;
}
public E findAndRemove(E obj){
Node<E> current = head, previous = null;
// In an empty list current = null so we skip to the last line
while(current != null){
if(((Comparable<E>)obj).compareTo(current.data) == 0){
// Beginning or single element
if(current == head)
return removeFirst();
// Ending of the list
if(current == tail)
return removeLast();
currentSize--;
// Removing the reference to the node to delete
previous.next = current.next;
return current.data;
}
previous = current;
current = current.next;
}
// Node not found
return null;
}
public boolean contains(E obj){
Node<E> current = head;
while(current != null) {
if(((Comparable<E>) obj).compareTo(current.data) == 0)
return true;
current = current.next;
}
return false;
}
public E peekFirst(){
if(head == null)
return null;
return head.data;
}
public E peekLast(){
if(tail == null)
return null;
return tail.data;
}
}
The interface methods hasPrevious, next, etc... have been moved into the IteratorHelper class which implements Iterator. The LinkedList class has an iterator() method because it implements Iterable. Now you can instantiate a LinkedList object and iterate over it in a for-loop:
package linkedlists;
public class Tester {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
int n = 10;
for (int i = 0; i < n; i++)
list.addFirstWithTail(i);
int removedFirst = list.removeFirst();
int removedLast = list.removeLast();
for(int x : list){
System.out.println(x);
}
}
}
Here's a handy chart to remind you which class should have which functions:
More on Iterable vs Iterator
I'm making the implementation of the Linked-List data structure and I'm looking foward to implement a remove method of all the occurrences of an element using recursion, here's a piece of my code:
public class MyLinkedList<T> {
private Node<T> head;
private Node<T> last;
private int length;
public void remove(T elem) {
if (!(this.isContained(elem)) || this.isEmpty())
return;
else {
if (head.value.equals(elem)) {
head = head.next;
length--;
remove(elem);
} else {
// This is a constructor which requieres a head and last, and a length
new MyLinkedList<>(head.next, last, length-1).remove(elem);
}
}
}
}
I do understand the problem, I'm working with copies of a list not with the original, so, how could I merge or make this sub to the original list?
If I had to do it with recursion, I think it would look something like this:
public void remove(T elem)
{
removeHelper(null, this.head, elem);
}
private void removeHelper(Node<T> prev, Node<T> head, T elem)
{
if (head != null) {
if (head.value.equals(elem)) {
if (head == this.head) {
this.head = head.next;
} else {
prev.next = head.next;
}
if (this.last == head) {
this.last = prev;
}
--this.length;
} else {
prev = head;
}
removeHelper(prev, head.next, elem);
}
}
For the record, if I didn't have to use recursion, I'd do it linearly like this:
private void remove(T elem)
{
Node<T> prev = null;
Node<T> curr = this.head;
while (curr != null) {
if (curr.value.equals(elem)) {
if (this.last == curr) {
this.last = prev;
}
if (prev == null) {
this.head = curr.next;
} else {
prev.next = curr.next;
}
--this.length;
} else {
prev = curr;
}
curr = curr.next;
}
}
I would suggest doing this in a separate static function instead of doing it in the actual node class since you are recursing through the entire linked list.
public void removeAllOccurences(Node<T> head, Node<T> prev, T elem) {
if (head == null) {
return;
}
if (head.value.equals(elem)) {
Node<T> temp = head.next;
if (prev != null) {
prev.next = temp;
}
head.next = null; // The GC will do the rest.
removeAllOccurences(temp, prev, elem);
} else {
removeAllOccurences(head.next, head, elem);
}
}
So I have an implementation of the Singly Linked List and I am trying to add a method which reports the second to last node of the list. However, I was not sure if I am allowed to write the method under the Node class then access it from the Singly Linked List class. If I do this, my instance variable of the node class('head' is used as a variable to access the penultimate method but also as the input of the penultimate method. Is that okay? Below is my implementation/attempt.
public class SinglyLinkedList {
private static class Node<Integer>{
private Integer element;
private Node<Integer> next;
private Node<Integer> penultimate;
public Node(Integer e, Node<Integer> n) {
element = e;
next = n;
penultimate = null;
}
public Integer getElement() {return element;}
public Node<Integer> getNext(){return next;}
public void setNext(Node<Integer> n) {next = n;}
public Node<Integer> penultimate(Node<Integer> head) {
Node<Integer> current = head;
while(current != null) {
if(head.getNext() == null) {
penultimate = head;
}
else {
current = current.getNext();
}
}
return penultimate;
}
}
private Node<Integer> head = null;
private Node<Integer> tail = null;
private int size = 0;
public SinglyLinkedList() {}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public Integer first() {
if (isEmpty()) {
return null;
}
return head.getElement();
}
public Integer last() {
if(isEmpty()) {
return null;
}
return tail.getElement();
}
public void addFirst(Integer i) {
head = new Node<> (i, head);
if(size == 0) {
tail = head;
}
size++;
}
public void addLast(Integer i) {
Node<Integer> newest = new Node<>(i,null);
if(isEmpty()) {
head = newest;
}
else {
tail.setNext(newest);
tail = newest;
size++;
}
}
public Integer removeFirst() {
if(isEmpty()) {
return null;
}
Integer answer = head.getElement();
head = head.getNext();
size--;
if(size == 0) {
tail = null;
}
return answer;
}
public void getPenultimate() {
if(isEmpty()) {
System.out.println("List is empty. Please check.");
}
else {
System.out.println("The second last node is: " + head.penultimate(head));
}
}
Remove the field penultimate. You do not want it in every node, in fact in no node, but calculated.
In the Node's penultimate method head should not be used in the loop.
//private Node<Integer> penultimate;
// head: ...#->#->#->P->null
public Node<Integer> penultimate(Node<Integer> head) {
Node<Integer> penultimate = null;
Node<Integer> current = head;
while (current != null) {
if (current.getNext() == null) {
penultimate = current;
break;
}
current = current.getNext();
}
return penultimate;
}
Or the third (second?) to last node:
// head: ...#->#->#->P->#->null
public Node<Integer> penultimate(Node<Integer> head) {
Node<Integer> penultimate = null;
Node<Integer> current = head;
while (current != null) {
if (current.getNext() == null) {
break;
}
penultimate = current;
current = current.getNext();
}
return penultimate;
}
Why not keep track of the second to last node?
private Node<Integer> head = null;
private Node<Integer> tail = null;
private Node<Integer> secondToLast = null;
private int size = 0;
public SinglyLinkedList() {}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public Integer first() {
if (isEmpty()) {
return null;
}
return head.getElement();
}
public Integer last() {
if(isEmpty()) {
return null;
}
return tail.getElement();
}
public void addFirst(Integer i) {
if (size == 1) {
secondToLast = head;
}
head = new Node<> (i, head);
if(size == 0) {
tail = head;
}
size++;
}
public void addLast(Integer i) {
Node<Integer> newest = new Node<>(i,null);
if(isEmpty()) {
head = newest;
}
else {
tail.setNext(newest);
secondToLast = tail;
}
tail = newest;
size++;
}
public Integer removeFirst() {
if(isEmpty()) {
return null;
}
Integer answer = head.getElement();
head = head.getNext();
size--;
if(size == 0) {
tail = null;
}
if (size == 1) {
secondToLast = null;
}
return answer;
}
public void getPenultimate() {
if(isEmpty()) {
System.out.println("List is empty. Please check.");
}
else {
System.out.println("The second last node is: " + secondToLast);
}
}
I am struggling to understand how to implement a remove(); for both a double and single linked class. I have figured out how to remove the first node in the double, but not in the single. First I would like to debug, problem solve the single linked class, then work on the double after that.
Here is the code I have so far for the Single Linked Class.
public class SingleLinkedClass<T> {
private Node <T> head;
private Node <T> tail;
private int size;
public SingleLinkedClass() {
size = 0;
head = null;
tail = null;
}
public void insertAtHead(T v)
{
//Allocate new node
Node newNode = new Node(v, head);
//Change head to point to new node
head = newNode;
if(tail == null)
{
tail = head;
}
//Increase size
size++;
}
public void insertAtTail(T v)
{
if(tail == null)
{
tail = new Node(v, null);
head = tail;
size++;
return;
}
Node newNode = new Node(v, null);
tail.nextNode = newNode;
tail = newNode;
size++;
}
public T removeHead()
{
if(head == null)
{
throw new IllegalStateException("list is empty! cannot delete");
}
T value = head.value;
head = head.nextNode;
size--;
return value;
}
public void removeTail()
{
//Case 1: list empty
if(head == null)
{
return;
}
//Case 2: list has one node
else if(head == tail)
{
head = tail = null;
}
else
{
Node temp = head;
while(temp.nextNode != tail)
{
temp = temp.nextNode;
}
tail = temp;
tail.nextNode = null;
}
size--;
}
public boolean remove(T v) {
Node<T> previous = head;
Node<T> cursor = head.nextNode;
if (head.nextNode == null) {
return false;
}
while(cursor != tail){
if (cursor.value.equals(v)) {
previous = cursor.nextNode;
return true;
}
previous = cursor;
cursor = cursor.nextNode;
}
return false;
}
public String toString() {
if (head == null) {
return "The list is Empty!";
}
String result = "";
Node temp = head;
while (temp != null) {
result += temp.toString() + " ";
temp = temp.nextNode;
}
return result;
}
public int size() {
return size;
}
private class Node <T> {
private T value;
private Node <T> nextNode;
public Node(T v, Node<T> n) {
value = v;
nextNode = n;
}
public String toString() {
return "" + value;
}
}
}
Here is my Double Linked Class
public class DoubelyLinkedList<E> {
private int size;
private Node<E> header;
private Node<E> trailer;
public DoubelyLinkedList() {
size = 0;
header = new Node<E>(null, null, null);
trailer = new Node<E>(null, null, header);
header.next = trailer;
}
public boolean remove(E v) {
//If the list is empty return false
if(header.next == trailer){
return false;
}
//If v is the head of the list remove and return true
Node <E> cursor = header.next;
for (int i = 0; i < size; i++) {
//Remove at Head
if(cursor.value.equals(v)){
removeAtHead();
}
cursor = cursor.next;
}
return true;
}
/*
} */
public void insertAtHead(E v) {
insertBetween(v, header, header.next);
}
public void insertAtTail(E v) {
insertBetween(v, trailer.prev, trailer);
}
private void insertBetween(E v, Node<E> first, Node<E> second) {
Node<E> newNode = new Node<>(v, second, first);
first.next = newNode;
second.prev = newNode;
size++;
}
public E removeAtHead() {
return removeBetween(header, header.next.next);
}
public E removeAtTail() {
return removeBetween(trailer.prev.prev, trailer);
}
private E removeBetween(Node<E> first, Node<E> second) {
if (header.next == trailer)// if the list is empty
{
throw new IllegalStateException("The list is empty!");
}
E result = first.next.value;
first.next = second;
second.prev = first;
size--;
return result;
}
public String toStringBackward() {
if (size == 0) {
return "The list is empty!";
}
String r = "";
Node<E> temp = trailer.prev;
while (temp != header) {
r += temp.toString() + " ";
temp = temp.prev;
}
return r;
}
public String toString() {
if (size == 0) {
return "The list is empty!";
}
String r = "";
Node<E> temp = header.next;
while (temp != trailer) {
r += temp + " ";
temp = temp.next;
}
return r;
}
private static class Node<T> {
private T value;
private Node<T> next;
private Node<T> prev;
public Node(T v, Node<T> n, Node<T> p) {
value = v;
next = n;
prev = p;
}
public String toString() {
return value.toString();
}
}
}
Here is my Driver
public class Driver {
public static void main(String[] args) {
DoubelyLinkedList<String> doubley = new DoubelyLinkedList();
SingleLinkedClass<String> single = new SingleLinkedClass();
single.insertAtHead("Bob");
single.insertAtHead("Sam");
single.insertAtHead("Terry");
single.insertAtHead("Don");
System.out.println(single);
single.remove("Bob");
System.out.println("Single Remove Head: " + single);
/*
single.remove("Don");
System.out.println("Single Remove Tail: " + single);
single.remove("Terry");
System.out.println("Single Remove Inbetween: " + single);
*/
System.out.println();
System.out.println();
doubley.insertAtHead("Bob");
doubley.insertAtHead("Sam");
doubley.insertAtHead("Terry");
doubley.insertAtHead("Don");
System.out.println(doubley);
doubley.remove("Bob");
System.out.println("Double Remove Head: " + doubley);
doubley.remove("Don");
System.out.println("Double Remove Tail: " + doubley);
/*
doubley.remove("Sam");
System.out.println("Double Remove Inbetween: " + doubley);
*/
}
}
In the removeHead moving head to its next, it might become null. Then tail was the head too. Then tail should be set to null too.
DoublyLinkedList is better English than DoubelyLinkedList.
As this is homework, I leave it by this.
Trying to write a method that removes all instances of a value from a singly linked list, but it doesn't appear to be working.
I tried to accomodate for whether or not the head contains the value, but I'm not sure whether or not this is the correct way to do so:
public void remove (int value)
{
if (head.value == value)
{
head = head.next;
count--;
}
IntegerNode temp=head;
while (temp !=null)
{
if (temp.next != null)
{
if (temp.next.value == value)
{
temp.next = temp.next.next;
count--;
}
}
temp=temp.next;
}
}
Is there something apparent wrong with my code?
Here the implementation of linked list with add and remove methods with test.
public class ListDemo {
public static void main(String[] args) {
MyList list = new MyList();
list.addToEnd(1);
list.addToEnd(2);
list.addToEnd(3);
list.removeByValue(2);
list.removeByValue(3);
}
}
class MyList {
private IntegerNode head;
private int count = 0;
public void addToEnd(int value) {
if(head == null) {
head = new IntegerNode(value);
count = 1;
head.next = null;
return;
}
IntegerNode current = head;
while (current.next != null) {
current = current.next;
}
IntegerNode node = new IntegerNode(value);
node.next = null;
count++;
current.next = node;
}
public void removeByValue(int value) {
if (count == 0) {
return;
} else if (count == 1) {
if (head.value == value) {
count = 0;
head = null;
}
} else {
IntegerNode current = this.head;
IntegerNode next = current.next;
while (next != null) {
if (next.value == value) {
if (next.next == null) {
current.next = null;
count--;
return;
} else {
current.next = next.next;
count--;
}
}
next = next.next;
}
}
}
}
class IntegerNode {
IntegerNode(int value) {
this.value = value;
}
IntegerNode next;
int value;
}
here is different ways to delete from Linked list
public Node removeAtFront()
{
Node returnedNode = null;
if(rootNode !=null)
{
if(rootNode.next !=null)
{
Node pointer = rootNode;
returnedNode = rootNode;
pointer = null;
rootNode = rootNode.next;
}
else
{
Node pointer = rootNode;
returnedNode = rootNode;
pointer = null;
rootNode = rootNode.next;
System.out.println("removing the last node");
}
}else
{
System.out.println("the linkedlist is empty");
}
return returnedNode;
}
public Node removeAtBack()
{
Node returnedNode = null;
if(rootNode != null)
{
//Remove the commented line if you wish to keep 1 node as minimum in the linked list
//if(rootNode.next !=null)
//{
Node pointer = new students();
pointer = rootNode;
while(pointer.next.next !=null)
{
pointer=pointer.next;
}
returnedNode = pointer.next.next;
pointer.next.next = null;
pointer.next = null;
//}
//else
//{
// System.out.println("cant remove the last node because its the root node");
//}
}
else
{
System.out.println("the linkedlist is empty");
}
return returnedNode;
}
public Node removeNode(String name)
{
Node returnedNode = null;
if(rootNode !=null)
{
Node pointer = new students();
Node previous = new students();
pointer = rootNode;
while(pointer !=null)
{
if(pointer.name.equals(name))
{
previous.next = pointer.next;
returnedNode = pointer;
pointer = null;
break;
}
else
{
previous = pointer;
pointer = pointer.next;
}
}
}
else
{
System.out.println("the linkedlist is empty");
}
return returnedNode;
}
public boolean isEmpty() {
return rootNode == null;
}
You need to track where you have been in the list rather than where you are going. Like this:
public void remove (int value)
{
IntegerNode current = head;
while (current !=null)
{
if (current.value == value)
{
if (head == current)
{
head = current.next;
}
else
{
head.next = current.next;
}
count--;
}
current=current.next;
}
}