NPE in 'MyLinkedList' methods - java

I'm having some trouble with NPE's in a MyLinkedList class that extends AbstractList. I start with these constructors:
The constructor for the private Node class:
public Node(T nodeData, Node<T> nodePrev, Node<T> nodeNext)
{
this.data = nodeData;
this.prev = nodePrev;
this.next = nodeNext;
}
The constructor for the MyLinkedList class
MyLinkedList()
{
this.head = new Node<T>(null, null, null);
this.tail = new Node<T>(null, null, null);
this.size = 0;
}
MyLinkedList(Node<T> head, Node<T> tail, int size)
{
this.head = head;
this.tail = tail;
this.size = size;
}
and here I try to return the node at an index with this method:
private Node<T> getNth(int index)
{
Node<T> temp;
if(index < 0 || index > size)
throw new IndexOutOfBoundsException();
if(index < this.size() / 2)
{
temp = this.head;
for(int i = 0; i < index; i++)
{
temp = temp.getNext();
}
}
else
{
temp = this.tail;
for(int i = this.size(); i > index; i--)
{
temp = temp.getPrev();
}
}
return temp;
}
I think the main problem has something to do with initializing the head and tail as null, but I'm not sure if this is the problem and if it is, how to fix it. Is there a better way to initialize these Nodes to avoid NPE's?

You're initializing both the head and the tail of the list with this:
MyLinkedList()
{
this.head = new Node<T>(null, null, null);
this.tail = new Node<T>(null, null, null);
this.size = 0;
}
This seems to be the main source of your NPE's, because your iteration doesn't do any kind of checks. In particular, your method will fail in border conditions (since you already check for lengths before even trying to iterate).
By adding some checks you can avoid those exceptions:
private Node<T> getNth(int index)
{
Node<T> temp = null; //Always try to initialize your variables if you're going
//to return them.
if(index < 0 || index > size)
throw new IndexOutOfBoundsException();
if(index < this.size() / 2)
{
temp = this.head;
for(int i = 0; i < index; i++)
{
if(temp.getNext() != null)
temp = temp.getNext();
else
break;//Break the iteration if there is not a next node
}
}
else
{
temp = this.tail;
for(int i = this.size(); i > index; i--)
{
if(temp.getPrev() != null)
temp = temp.getPrev();
else
break;
}
}
return temp;
}
You can throw some kind of exception instead of breaking the iterations if you want.

Related

Java dynamic queue with implemented array returns unexpected null

So I'm doing a Java dynamic queue with implemented array, and when the array are doubling in size, and the values from the previous array have been copied over, and additional values added, the program returns null on the first additional value.
It is supposed to return 10.
Console returns following:
...
9
Queue is full. Allocating bigger array.
Queue length is now doubled, and nodes copied
10
...
14
Start dequeue.
0
...
9
null
11
...
Main class:
public class Main{
public static void main(String[] args) throws Exception{
int maxsize = 10;
Array queue = new Array(maxsize);
for(int i=0; i<15; i++) {
queue.enQueue(i);
}
System.out.println("Start dequeue.");
for(int i=0; i<15; i++) {
System.out.println(queue.deQueue());
}
}
}
Array Class:
public class Array {
private Node[] queue;
private Integer head; // index of the current front item, if one exists
private Integer tail; // index of next item to be added
private int maxSize;
private int size = 0;
public Array(int maxSize) {
this.maxSize = maxSize;
queue = new Node[maxSize+1];
for(int i = 0; i <= maxSize; i++) {
queue[i] = new Node(null);
}
head = tail = 0;
}
public void enQueue(Integer data){
Node node = new Node(data);
// If it's the first node, put in queue[0], increase tail.
if(head == tail && size == 0) {
queue[tail] = node;
tail++;
size++;
System.out.println(data);
// If Queue is full, create array twice the size and copy elements.
}else if(size == maxSize) {
System.out.println("Queue is full. Allocating bigger array.");
int newMaxSize = maxSize * 2;
// Skapa och initialisera ny Array.
Node[] newQueue = new Node[newMaxSize + 1];
for(int i = 0; i <= newMaxSize; i++) {
newQueue[i] = new Node(null);
}
// Kopiera över element mellan head -> maxSize.
for(int i = head; i <= maxSize; i++) {
int j = 0;
newQueue[j] = queue[i];
j++;
}
// Kopiera över element mellan queue[0] -> tail.
for(int i=0; i<=tail; i++) {
if(queue[i] != null) {
newQueue[i] = queue[i];
}
}
tail = maxSize + 1;
maxSize = newMaxSize;
queue = newQueue;
head = 0;
queue[tail] = node;
size++;
System.out.println("Queue length is now doubled, and nodes copied");
System.out.println(data);
return;
// If Queue is not full, check if tail point outside of maxSize.
}else {
// If tail is outside, move tail to queue[0].
if(tail == maxSize + 1) {
tail = 0;
queue[tail] = node;
tail++;
size++;
}else {
queue[tail] = node;
tail++;
size++;
}
System.out.println(data);
}
}
public Integer deQueue() {
if(head != tail) {
if(head == maxSize) {
Integer nodeData = queue[head].getData();
queue[head] = null;
head = 0;
size--;
return nodeData;
} else {
Integer nodeData = queue[head].getData();
queue[head] = null;
head++;
size--;
return nodeData;
}
} else {
// If queue is empty, notify user.
System.out.println("Queue is empty.");
return null;
}
}
}
Node class:
public class Node {
private Integer data;
public Node(Integer data) {
this.data = data;
}
public Integer getData() {
return this.data;
}
}
I'm stuck by staring at the code for too long, not able to find the issue.
Help would be appreciated!

Java LinkedList implementation insert method 0th index insertion handling

I have implemented the following java implementation of a linked list
public class LinkedListFromScratch {
private Node head;
private static int size;
public LinkedListFromScratch() {
this.head = null;
this.size = 0;
}
public boolean isEmpty() {
return head == null;
}
public static int getSize() {return size;}
void addToTail(int data) {
Node newNode = new Node(data);
//if list is empty, make new node the head.
if (isEmpty()) {
this.head = newNode;
size++;
return;
}
Node itterHead = head;
while (itterHead.next != null) {
itterHead = itterHead.next;
}
itterHead.next = newNode;
size++;
}
void addAtIndex(int index, int data) {
if(index < 0 || index > this.size )
throw new IllegalArgumentException("Index you entered is out of bounds");
Node newNode = new Node (data);
if(isEmpty()) {
this.head = newNode;
size++;
return;
}
//locate the obj at index and one before it
//newnode.next = obj
//prevnode.next = newnode
Node current = this.head;
Node previous = null;
for ( int i = 0; i < index; i++){
previous = current;
current = current.next;
}
previous.next = newNode;
newNode.next = current;
size++;
}
void printList() {
if (isEmpty())
System.out.print("[]");
Node itterHead = this.head;
System.out.print("[ ");
while (itterHead != null) {
System.out.print(itterHead.d + " ");
itterHead = itterHead.next;
}
System.out.print("]");
System.out.println();
}
class Node {
int d;
Node next;
Node(int d) {
this.d = d;
this.next = null;
}
}
}
The issue here is with the addAtIndex (int index, int data) method. When I try to insert a value at index zero, it throws a null pointer exception. It makes sense because the for loop never gets executed and "previous" will always be null in the index = 0 scenario. The insertion works fine for index > 0. what is the best way to handle this case?
you need to check if the index is zero, this means you have new head to the list
add this code before the for-loop
if (index == 0){
newNode.next = head;
head = newNode;
size++;
return;
}

Add(index, element) method

I am implementing a method add(int index, E element) that is supposed to insert the specified element at the specified index in a list and shift the element currently at that position and any subsequent elements to the right. Does anyone know why my method does not work when my code is:
newNode.setNext(temp.getNext());
newNode.setPrev(temp);
newNode.getNext().setPrev(newNode);
temp.setNext(newNode);
at the end of the method but works when I have only
newNode.setNext(temp.getNext());
temp.setNext(newNode);
My code:
public class DoubleLinkedList<E> implements IDoubleLinkedList<E> {
DLLNode head;
DLLNode tail;
int size = 0;
#Override
public void add(int index, E element) throws IndexOutOfBoundsException {
if (index > size) {
throw new IndexOutOfBoundsException();
}
if (index < 0) {
throw new IndexOutOfBoundsException();
}
if (head == null) {
head = new DLLNode(element);
tail = head;
}
else if (index == 0) {
DLLNode temp = new DLLNode(element);
temp.setNext(head);
head = temp;
} else {
DLLNode temp = head;
for (int i = 1; i < index; i++) {
temp = temp.getNext();
}
DLLNode newNode = new DLLNode(element);
newNode.setNext(temp.getNext());
newNode.setPrev(temp);
newNode.getNext().setPrev(newNode);
temp.setNext(newNode);
}
size ++;
}
Node class for my DoublyLinkedlist:
public class DLLNode<E> {
private DLLNode<E> next;
private DLLNode<E> prev;
private E element;
public DLLNode(E element){
this.element=element;
prev=null;
next=null;
}
public DLLNode(E element, DLLNode prev, DLLNode next) {
this.element=element;
this.prev=prev;
this.next=next;
}
public E getData(){
return element;
}
public void setData(E element){
this.element=element;
}
public DLLNode getPrev(){
return prev;
}
public DLLNode getNext(){
return next;
}
public void setPrev(DLLNode where){
prev=where;
}
public void setNext(DLLNode where){
next=where;
}}
It doesn't work for three reasons that I can see:
In the if (index == 0) block, you never set the prev value of the head node.
In the else block, you never check if you're at the end of the list, so you'll get a NullPointerException if you are.
In both if (index == 0) block and else block, you don't set tail if the new node is the last node.
On a side note: You're using raw generics all over. Never use DLLNode without a < immediately after it. Basically, change all DLLNode to DLLNode<E>.
Here's how you test your own code.
Add this method to DLLNode:
void verifyIntegrity() {
if (this.prev != null && this.prev.next != this)
throw new AssertionError("prev.next is corrupt");
if (this.next != null && this.next.prev != this)
throw new AssertionError("next.prev is corrupt");
}
Add this method to DoubleLinkedList:
void verifyIntegrity() {
int count = 0;
DLLNode<E> last = this.head;
for (DLLNode<E> node = this.head; node != null; count++, last = node, node = node.getNext())
node.verifyIntegrity();
if (this.tail != last)
throw new AssertionError("tail is corrupt");
if (this.size != count)
throw new AssertionError("size is corrupt");
}
Now test you code like this:
DoubleLinkedList<Integer> listHead = new DoubleLinkedList<>();
DoubleLinkedList<Integer> listTail = new DoubleLinkedList<>();
DoubleLinkedList<Integer> listMid = new DoubleLinkedList<>();
listHead.verifyIntegrity();
listTail.verifyIntegrity();
listMid.verifyIntegrity();
for (int i = 0; i < 10; i++) {
listHead.add(0, i);
listTail.add(i, i);
listMid.add(i / 2, i);
listHead.verifyIntegrity();
listTail.verifyIntegrity();
listMid.verifyIntegrity();
}

How to write a remove method with Cyclic Doubly-Linked-List with Generic Nodes in Java

I am implementing a cyclic DoublyLinkedList data structure. Like a singly
linked list, nodes in a doubly linked list have a reference to the next node, but unlike a singly linked list, nodes in a doubly linked list also have a reference to the previous node. Additionally, because the list is "cyclic", the "next" reference in the last node in the list points to the first node in the list, and the "prev" reference in the first node in the list points to the last node in the list.
I am having trouble with my remove method with some size usage. It's the message I'm getting when I run my tests.
Here's my code:
public class DoublyLinkedList<E>
{
private Node first;
private int size;
#SuppressWarnings("unchecked")
public void add(E value)
{
if (first == null)
{
first = new Node(value, null, null);
first.next = first;
first.prev = first;
}
else
{
first.prev.next = new Node(value, first, first.prev);
first.prev = first.prev.next;
}
size++;
}
private class Node<E>
{
private E data;
private Node next;
private Node prev;
public Node(E data, Node next, Node prev)
{
this.data = data;
this.next = next;
this.prev = prev;
}
}
#SuppressWarnings("unchecked")
public void add(int index, E value)
{
if (first.data == null)
{
throw new IndexOutOfBoundsException();
} else if (index == 0)
{
first = new Node(value, first.next, first.prev);
}
else
{
Node current = first;
for (int i = 0; i < index - 1; i++)
{
current = current.next;
}
current.next = new Node(value, current.next, current.prev);
}
}
Here is the method I need help with.
The remove method should remove the element at the specified index in the list. Be sure to address the case in which the list is empty and/or the removed element is the first in the list. If the index parameter is invalid, an IndexOutOfBoundsException should be thrown.
#SuppressWarnings("unchecked")
public void remove(int index)
{
if (first.data == null)
{
throw new IndexOutOfBoundsException();
}
else if (index == 0)
{
first = first.next;
}
else
{
Node current = first.next;
for (int i = 0; i < index - 1; i++)
{
current = current.next;
}--size;
current.next = current.next.next;
}
}
Here is the rest of the code. The get method is incorrect, but I asked that in a different question.
public E get(int index)
{
if(index >= size)
{
}
return null;
//return first.data;
}
#SuppressWarnings("unchecked")
public int indexOf(E value)
{
int index = 0;
Node current = first;
while (current != current.next)
{
if (current.data.equals(value))
{
return index;
}
index++;
current = current.next;
}
return index;
}
public boolean isEmpty()
{
if (size == 0)
{
return true;
}
else
{
return false;
}
}
public int size()
{
return size;
}
This was not easy at all, however I did find the answer to my question. This is a cyclic doubly linked list. Here it is:
#SuppressWarnings("unchecked")
public void remove(int index)
{
if(index < 0 || index > size)
{
throw new IndexOutOfBoundsException();
}
Node n = first;
for(int i = 0; i < index; i++)
{
n = n.next;
}
// n points to node to remove
n.prev.next = n.next;
n.next.prev = n.prev;
if (index == 0)
{
if(size == 1)
{
first = null;
}
else
{
first = first.next;
}
}
size--;
}

Reverse generic LinkedList by using swap method

public class SimpleLinkedList<E> {
public Node<E> head;
public int size;
public void add(E e) {
++this.size;
if (null == head) {
this.head = new Node();
head.val = e;
} else {
Node<E> newNode = new Node();
newNode.val = e;
newNode.next = head;
this.head = newNode;
}
}
public void swap(E val1, E val2) {
if (val1.equals(val2)) {
return;
}
Node prevX = null, curr1 = head;
while (curr1 != null && !curr1.val.equals(val1)) {
prevX = curr1;
curr1 = curr1.next;
}
Node prevY = null, curr2 = head;
while (curr2 != null && !curr2.val.equals(val2)) {
prevY = curr2;
curr2 = curr2.next;
}
if (curr1 == null || curr2 == null) {
return;
}
if (prevX == null) {
head = curr2;
} else {
prevX.next = curr2;
}
if (prevY == null) {
head = curr1;
} else {
prevY.next = curr1;
}
Node temp = curr1.next;
curr1.next = curr2.next;
curr2.next = temp;
}
public void reverse() {
Node<E> prev = null;
Node<E> current = head;
Node<E> next = null;
while (current != null) {
next = current.next;
current.next = prev;
prev = current;
current = next;
}
head = prev;
}
public static class Node<E> {
public Node<E> next;
public E val;
}
}
public class SimpleLinkedListTest {
#Test
public void testReverseMethod() {
SimpleLinkedList<Integer> myList = new SimpleLinkedList<>();
for (int i = 0; i < 10; i++) {
myList.add(i);
}
SimpleLinkedList<Integer> expectedList = new SimpleLinkedList<>();
for (int i = 9; i > -1; i--) {
expectedList.add(i);
}
myList.reverse();
assertTrue(AssertCustom.assertSLLEquals(expectedList, myList));
}
}
What would be the most optimal way to reverse generic LinkedList by using the swap method?
before reverse method :
(head=[9])->[8]->[7]->[6]->[5]->[4]->[3]->[2]->[1]->[0]-> null
after reverse() method :
(head=[0])->[1]->[2]->[3]->[4]->[5]->[6]->[7]->[8]->[9]-> null
What you need to do is divide the list in half. If the list size is odd the one in the middle will remain in place. Then swap elements on either side in a mirror like fashion. This should be more efficient than O(n^2)
reverse(){
Node current = this.head;
int half = this.size/2;
int midElement = this.size % 2 == 0 ? 0: half + 1;
Stack<Node<E>> stack = new Stack<Node<E>>();
for(int i = 0; i < this.size; i++){
if (i < = half)
stack.push(current);
else{
if (i == midElement)
continue;
else
swap(stack.pop(), current);
current = current.next;
}
}
swap(Node<E> v, Node<E> v1){
E tmp = v.value;
v.value = v1.value;
v1.value = tmp;
}
This is a little bit of pseudo java. It is missing still the checks for size = 0 or size = 1 when it should return immediately. One for loop. Time Complexity O(n). There is also the need to check when size = 2, swap(...) is to be invoked directly.
Based on the #efekctive 's idea, there a solution. The complexity is a little bit worse than O^2 but no need changes in the swap method, no need in usage of another collection. The code below passes the unit test, however, be careful to use it there could be a bug related to size/2 operation. Hope this help.
public void reverse() {
Node<E> current = head;
SimpleLinkedList<E> firstHalf = new SimpleLinkedList<>();
SimpleLinkedList<E> secondHalf = new SimpleLinkedList<>();
for (int i = 0; i < size; i++) {
if (i >= size / 2) {
firstHalf.add(current.val);
} else {
secondHalf.add(current.val);
}
current = current.next;
}
SimpleLinkedList<E> secondHalfReverse = new SimpleLinkedList<>();
for (int i = 0; i < secondHalf.size(); i++) {
secondHalfReverse.add(secondHalf.get(i));
}
for (int i = 0; i < size / 2; i++) {
if (secondHalfReverse.get(i) == firstHalf.get(i)) {
break;
}
swap(secondHalfReverse.get(i), firstHalf.get(i));
}
}

Categories

Resources