This is a homework question. I have a Double Linked Node class, Circular Double Linked List class which implements Iterable, and a Iterator class that implements Iterator. I understand the concept of an iterator where an implicit cursor sits between two nodes and on a call to next() it returns the node it just jumped over. I created a test class with a new list object. I then created an iterator and called next, I received the correct No Such Element exception but when I added some nodes to the list I received a Null Pointer Exception instead of it returning the last returned node. How can I correct this?
My Node class:
public class DoubleLinkedNode<E>{
private E data;
private DoubleLinkedNode<E> next;
private DoubleLinkedNode<E> prev;
public DoubleLinkedNode(E data, DoubleLinkedNode<E> next, DoubleLinkedNode<E> prev){
this.data = data;
this.next = next;
this.prev = prev;
}
/**
* Used to construct a node that points to null for its prev and next.
* #param data Data is a generic variable to be stored in the node.
*/
public DoubleLinkedNode(E data){
this(data, null, null);
}
//getters
public E getData(){
return data;
}
public DoubleLinkedNode<E> getNext(){
return next;
}
public DoubleLinkedNode<E> getPrev(){
return prev;
}
//setters
public void setData(E data){
this.data = data;
}
public void setNext(DoubleLinkedNode<E> next){
this.next = next;
}
public void setPrev(DoubleLinkedNode<E> prev){
this.prev = prev;
}
#Override public String toString(){
if(data == null){
return null;
}
else{
return data.toString();
}
}
}
The List class with the private inner Iterator class:
import java.util.Iterator;
import java.util.ListIterator;
import java.util.NoSuchElementException;
public class CircularDoubleLinkedList<E> implements Iterable<E>{
private int size;
private DoubleLinkedNode<E> head;
public CircularDoubleLinkedList(){
this.head = null;
this.size = 0;
}
/**
* Adds an item to the end of the list.
*
* #param data The Data that is to be stored in the node.
*/
public void add(E data){
DoubleLinkedNode<E> newNode = new DoubleLinkedNode<E>(data);
if(this.head == null){
newNode.setNext(newNode);
newNode.setPrev(newNode);
this.head = newNode;
this.size++;
//if list is empty create a new node and insert
}
else{
DoubleLinkedNode<E> temp = this.head.getPrev();
this.head.getPrev().setNext(newNode);
this.head.setPrev(newNode);
newNode.setPrev(temp);
newNode.setNext(this.head);
this.size++;
}
}
/**
* Which adds an item at the specified index.
*
* #param index The index in which the new Node is added.
* #param data The data which is to be stored in the node.
*/
public void add(int index, E data){
int currIndex = 0;
DoubleLinkedNode<E> currNode = this.head;
DoubleLinkedNode<E> nextNode = this.head.getNext();
DoubleLinkedNode<E> prevNode = this.head.getPrev();
DoubleLinkedNode<E> newNode = new DoubleLinkedNode<E>(data);
if(index == 0){
prevNode.setNext(newNode);
currNode.setPrev(newNode);
newNode.setPrev(prevNode);
newNode.setNext(currNode);
this.head = newNode;
this.size++;
}
else if (index > 0){
while(currIndex != this.size){
if(currIndex != index%size){
currIndex++;
currNode = currNode.getNext();
nextNode = nextNode.getNext();
prevNode = prevNode.getNext();
}else{
newNode.setPrev(prevNode);
newNode.setNext(currNode);
prevNode.setNext(newNode);
currNode.setPrev(newNode);
currNode = newNode;
this.size++;
break;
}
}
}
else if (index < 0){
while(currIndex != -this.size){
if(currIndex != index%size){
currIndex--;
currNode = currNode.getPrev();
prevNode = prevNode.getPrev();
nextNode = nextNode.getPrev();
}else{
newNode.setNext(nextNode);
newNode.setPrev(currNode);
currNode.setNext(newNode);
nextNode.setPrev(newNode);
currNode = newNode;
this.size++;
break;
}
}
}
}
/**
* Returns the data stored at the specified index.
*
* #param index The index determines the node whose data is returned.
* #return Returns the data of the node at the index.
*/
public E get(int index){//returns the data stored at the specified index
int currIndex = 0;
DoubleLinkedNode<E> currNode = this.head;
E temp = null;
if(index == 0){//zero case
temp = currNode.getData();
}
else if(index > 0){//positive
while(currIndex != this.size){
if(currIndex != index%size){
currIndex++;
currNode = currNode.getNext();
}else{
temp = currNode.getData();
break;
}
}
}
else if(index < 0){//negative
while(currIndex != -this.size){
if(currIndex != index%size){
currIndex--;
currNode = currNode.getPrev();
}else{
temp = currNode.getData();
break;
}
}
}
return temp;
}
/**
* Which removes and returns an item from the list.
*
* #param index Removes the node at the current index.
* #return Returns the data of the removed node.
*/
public E remove(int index){//which removes and returns an item from the list
int currIndex = 0;
DoubleLinkedNode<E> currNode = this.head;
DoubleLinkedNode<E> nextNode = this.head.getNext();
DoubleLinkedNode<E> prevNode = this.head.getPrev();
E temp = null;
if(index == 0){
temp = currNode.getData();
prevNode.setNext(currNode.getNext());
nextNode.setPrev(currNode.getPrev());
this.head = nextNode;
size--;
}
else if(index > 0){//positive
while(currIndex != this.size){
if(currIndex != index%size){
currIndex++;
currNode = currNode.getNext();
nextNode = nextNode.getNext();
prevNode = prevNode.getNext();
}else{
temp = currNode.getData();
prevNode.setNext(currNode.getNext());
nextNode.setPrev(currNode.getPrev());
currNode = nextNode;
size--;
break;
}
}
}
else if(index < 0){//negative
while(currIndex != -this.size){
if(currIndex != index%size){
currIndex--;
currNode = currNode.getPrev();
prevNode = prevNode.getPrev();
nextNode = nextNode.getPrev();
}else{
temp = currNode.getData();
prevNode.setNext(currNode.getNext());
nextNode.setPrev(currNode.getPrev());
currNode = prevNode;
size--;
break;
}
}
}
return temp;
}
/**
* Returns the size.
*
* #return
*/
public int size(){
return size;
}
#Override public String toString(){
String str = "[";
int index = 0;
DoubleLinkedNode<E> curr = head;
if(size == 0){
return "There is no one here to kill.";
}else{
while (index <this.size) {
str += curr.getData();
curr = curr.getNext();
index++;
if (index<this.size) {
str += ", ";
}
}
str += "]";
}
return str;
}
#Override
public Iterator<E> iterator() {
return new CircularDoubleIterator();
}
// Iterator inner class begins
private class CircularDoubleIterator implements ListIterator<E> {
private DoubleLinkedNode<E> nextItem;//reference to next item
private int index = 0;
private DoubleLinkedNode<E> lastReturned;// the last node to be returned by prev() or next()
// reset to null after a remove() or add()
#Override
public E next() {
if(!hasNext()){
throw new NoSuchElementException("No such element.");
}
else{
nextItem = head; //edited 11Sept13
lastReturned = nextItem.getNext();
nextItem = nextItem.getNext();
head = nextItem; //edited 11Sept13
index++;
return lastReturned.getData();
}
}
#Override
public E previous() {
if(!hasPrevious()){
throw new NoSuchElementException("No such element.");
}
else{
index--;
return ;
}
}
#Override
public int nextIndex() {
return index;
}
#Override
public int previousIndex() {
return index-1;
}
#Override
public boolean hasNext() {
return size != 0;
}
#Override
public boolean hasPrevious() {
return size!= 0;
}
#Override
public void remove() {
}
#Override
public void set(E theData) {
if(lastReturned == null){
throw new IllegalStateException();
}
else{
}
}
#Override
public void add(E theData) {
if(size == 0){
}
else if(size != 0){
}
}
}
//Iterator inner class ends
}
I don't see where you assign values to private DoubleLinkedNode<E> nextItem; when you create iterator.
I cannot see the whole code. So I assume that nextItem is null or its next field is null.
Related
I'm trying to add "hello" at the index 0 but it it's added at index one, and also prints USA after that when it shouldn't. What's wrong with my add method? Is there something else that's wrong in the code that's causing this problem or is it just the add method? Any help is appreciated... The code of singlylinkedlist with the implementation is below...
class SinglyLinkedList<E> { //---------------- nested Node class
private static class Node<E> { private E element;
private Node<E> next;
public Node(E e, Node<E> n) {
element = e;
next = n; }
public E getElement() {
return element;
}
public Node<E> getNext() {
return next;
}
public void setNext(Node<E> n) {
next = n;
} }
private Node<E> head = null;
private Node<E> tail = null;
private int size = 0;
public SinglyLinkedList() { }
public int size() { return size; }
public boolean isEmpty() { return size == 0; }
public E first() {
if (isEmpty()) return null; return head.getElement();
}
public E last() {
if (isEmpty()) return null;
return tail.getElement(); }
// update methods
public void addFirst(E e) {
head = new Node<>(e, head);
if (size == 0)
tail = head;
size++;
}
public void addLast(E e) {
Node<E> newest = new Node<>(e, null);
if (isEmpty( ))
head = newest;
else
tail.setNext(newest);
tail = newest;
size++;
}
public E removeFirst() {
if (isEmpty())
return null;
E answer = head.getElement();
head = head.getNext();
size--;
if (size == 0)
tail = null;
return answer;
}
public void printLinkedList() {
Node<E> temp = head;
for(int i = 0; i< size; i++) {
System.out.println(temp.getElement());
temp = temp.next;
}
}
public void removeLast() {
tail = null;
size--;
}
public void remove(int index) {
//Node<E> newest = new Node(e, null);
Node<E> current = head;
if (index == 0) {
removeFirst();
}
else {
for (int i = 0; i<index -1; i++) {
//current = current.next;
current = current.getNext();
}
current.next = current.next.next;
}
size--;
}
public void add(int index, E e) {
Node<E> current = head;
Node newNode = new Node(e, null);
for(int i = 0; i< index; i++) {
current = current.next;
}
current.next = newNode;
newNode.next = current;
size++;
}
}
public class SinglyLinkedListTest {
public static void main(String args[]) {
SinglyLinkedList<String> list = new SinglyLinkedList();
list.addLast("USA");
list.addLast("America");
list.addLast("portugal");
System.out.println(" ");
list.printLinkedList();
//list.remove(2);
System.out.println(" ");
list.printLinkedList();
list.removeLast();
System.out.println(" ");
list.printLinkedList();
list.add(0, "hello");
System.out.println(" ");
list.printLinkedList();
}
}
There a two mistakes:
at index 0 you need to replace head
current points to newNode and newNode points to current
Fixed code:
public void add(int index, E e) {
Node<E> newNode = new Node<>(e, null);
if(index == 0) {
newNode.next = head;
head = newNode;
} else {
Node<E> current = head;
for(int i = 1; i< index; i++) {
current = current.next;
}
Node<E> tmp = current.next;
current.next = newNode;
newNode.next = tmp;
}
size++;
}
I have an assignment to complete a DoublyLinkList assignment and I am having some difficulty with two of the methods. I was given the code for MyList and MyAbstractList and was told to extend MyAbstractList with my DoublyLinkedList. I am not allowed to change MyList or MyAbstractList.
Here is the code for MyList I was provided:
public interface MyList<E extends Comparable<E>> {
/** Return true if this list contains no elements */
public boolean isEmpty();
/** Return the number of elements in this list */
public int size();
/** Add a new element at the proper point */
public void add(E e);
/** Clear the list */
public void clear();
/** Return true if this list contains the element */
public boolean contains(E e);
/** Return the element from this list at the specified index */
public E get(int index);
/** Return the first element in the list */
public E getFirst();
/** Return the last element in the list */
public E getLast();
/** Return the index of the first matching element in this list.
* Return -1 if no match. */
public int indexOf(E e);
/** Return the index of the last matching element in this list
* Return -1 if no match. */
public int lastIndexOf(E e);
/** Remove the first occurrence of the element o from this list.
* Shift any subsequent elements to the left.
* Return true if the element is removed. */
public boolean remove(E e);
/** Remove the element at the specified position in this list
* Shift any subsequent elements to the left.
* Return the element that was removed from the list. */
public boolean remove(int index);
/** Remove the first element in the list, return true if done, false if list is empty */
public boolean removeFirst();
/** Remove the Last element in the list, return true if done, false if list is empty */
public boolean removeLast();
/** Replace the element at the specified position in this list
* with the specified element and return true if done, false if index out of range. */
public boolean set(int index, E e);
}
and this was the code I was provided for MyAbstractList:
public abstract class MyAbstractList<E extends Comparable<E>> implements MyList<E> {
protected int size = 0; // The size of the list
/** Create a default list */
protected MyAbstractList() {
}
/** Create a list from an array of objects */
public MyAbstractList(E[] objects) {
for (int i = 0; i < objects.length; i++)
add(objects[i]);
}
#Override /** Return true if this list contains no elements */
public boolean isEmpty() {
return size == 0;
}
#Override /** Return the number of elements in this list */
public int size() {
return size;
}
}
Finally here is my code for MyDoublyLinkedList:
import java.util.ArrayList;
public class MyDoublyLinkedList<E extends Comparable<E>> extends MyAbstractList<E>
{
int size =0;
Node<E> head = null;
Node<E> current = null;
Node<E> tail = null;
public MyDoublyLinkedList() {
}
/** Create a list from an array of objects */
public MyDoublyLinkedList(E[] objects) {
super(objects);
}
#Override
public boolean isEmpty()
{
return size == 0;
}
#Override
public int size()
{
return size;
}
/** Add a new element at the proper point */
#Override
public void add(E e)
{
Node<E> newNode = new Node<E>(e);
if (tail == null) {
head = tail = newNode;
}
else //if (head != null)
{
tail.next = newNode;
tail = newNode;
}
size++;
}
#Override
public void clear()
{
size = 0;
head = tail = null;
}
#Override
public boolean contains(E e)
{
Node<E> current = head;
for (int i = 0; i < size; i++) {
if (current.element.equals(e))
return true;
current = current.next;
}
return false;
}
#Override
public E get(int index)
{
if (index < 0 || index > size - 1)
return null;
Node<E> current = head;
for (int i = 0; i < index; i++)
current = current.next;
return current.element;
}
#Override
public E getFirst()
{
if (size == 0) {
return null;
}
else {
return head.element;
}
}
#Override
public E getLast()
{
if (size == 0) {
return null;
}
else {
return tail.element;
}
}
#Override
public int indexOf(E e)
{
Node<E> current = head;
for (int i = 0; i < size; i++) {
if (current.element.equals(e))
return i;
current = current.next;
}
return -1;
}
#Override
public int lastIndexOf(E e)
{
int lastIndex = -1;
Node<E> current = head;
for (int i = 0; i < size; i++) {
if (current.element.equals(e))
lastIndex = i;
current = current.next;
}
return lastIndex;
}
/** Remove the first occurrence of the element o from this list.
* Shift any subsequent elements to the left.
* Return true if the element is removed. */
#Override
public boolean remove(E e)
{
int index = indexOf(e);
if (index != -1) {
return remove(index);
} else {
return false;
}
}
/** Remove the element at the specified position in this list
* Shift any subsequent elements to the left.
* Return the element that was removed from the list. */
#Override
public boolean remove(int index)
{
if (index < 0 || index >= size) {
return false;
}
else if (index == 0) {
return removeFirst();
}
else if (index == size - 1) {
return removeLast();
}
else {
Node<E> previous = head;
for (int i = 1; i < index; i++) {
previous = previous.next;
}
Node<E> current = previous.next;
previous.next = current.next;
size--;
return true;
}
}
#Override
public boolean removeFirst()
{
if (size == 0) {
return false;
}
else {
Node<E> temp = head;
head = head.next;
size--;
if (head == null) {
tail = null;
}
return true;
}
}
#Override
public boolean removeLast()
{
if (size == 0) {
return false;
}
else if (size == 1) {
Node<E> temp = head;
head = tail = null;
size = 0;
return true;
}
else {
Node<E> current = head;
for (int i = 0; i < size - 2; i++) {
current = current.next;
}
Node<E> temp = tail;
tail = current;
tail.next = null;
size--;
return true;
}
}
#Override
public boolean set(int index, E e)
{
if (index < 0 || index > size - 1)
return false;
Node<E> current = head;
for (int i = 0; i < index; i++)
current = current.next;
E temp = current.element;
current.element = e;
return true;
}
#Override
public String toString()
{
StringBuilder result = new StringBuilder("[");
Node<E> current = head;
for (int i = 0; i < size; i++) {
result.append(current.element);
current = current.next;
if (current != null) {
result.append(", "); // Separate two elements with a comma
}
else {
result.append("]"); // Insert the closing ] in the string
}
}
return result.toString();
}
public String toStringBack()
{
StringBuilder result = new StringBuilder("[");
Node<E> current = tail;
for (int i = 0; i < size; i++) {
result.append(current.element);
current = current.previous;
if (current != null) {
result.append(", "); // Separate two elements with a comma
}
else {
result.append("]"); // Insert the closing ] in the string
}
}
return result.toString();
}
public void add(int index, E e)
{
if (index ==0) {
addFirst(e);// The new node is the only node in list
}
else if(index > size)
{
addLast(e);//The index location was bigger than size
}
else
{
Node<E> current = getAtIndex(index-1);
Node<E> temp = current.next;
current.next = new Node<E>(e);
(current.next).next = temp;
size++;
}
}
public void addFirst(E e)
{
Node<E> newNode = new Node<E>(e); // Create a new node
newNode.next = head; // link the new node with the head
head = newNode; // head points to the new node
size++; // Increase list size
if (tail == null) // the new node is the only node in list
tail = head;
}
public void addLast(E e)
{
Node<E> newNode = new Node<E>(e); // Create a new for element e
if (tail == null) {
head = tail = newNode; // The new node is the only node in list
}
else {
tail.next = newNode; // Link the new with the last node
tail = tail.next; // tail now points to the last node
}
size++;
}
protected Node<E> getAtIndex(int index)
{
int count;
if (index < 0 || index > size - 1)
return null;
Node<E> temp = null;
if(index <= (size/2))
{
count = -1;
temp = head;
while(++count <= index){
temp = temp.next;
}
}
else if (index > (size/2))
{
count = size;
temp = tail;
while(--count >= index){
temp = temp.previous; //--> this is Where the null pointer exception occurs
}
}
return temp;
}
private static class Node<E>{
E element;
Node<E> next;
Node<E> previous;
public Node(E element){
this.element = element;
next = null;
previous = null;
}
}
}
When I run the add(int index, E e) Method I receive a null pointer exception in the getAtIndext() method. I also have had issues getting the add(E e) Method to add properly when I change the current location. The methods are all as I am being required to use them. The use of iterators while they would be nice are not allowed. I am using Bluj as a compiler. Please let me know what questions you have.
Thank you
EDIT: I do know what a Null Pointer Exception is, I can not figure out why this is coming back as null. The Node "current" should point to the end, then go back in the list until it reaches the indexed location. This only happens when I try to add a node in the last half of the list. The error is thrown at temp = temp.previous;
The stack trace is:
java.lang.NullPointerException at MyDoublyLinkedList.getAtIndex(MyDoublyLinkedList.java:345) at MyDoublyLinkedList.add(MyDoublyLinkedList.java:289) at TestMyDoublyLinkedList.main(TestMyDoublyLinkedList.java:50)
Edit: I figured out the issue. The add() and getAtIndex functions are running properly. When I run the test the function that is throwing a Null Pointer Exception is throwing it at position 8. It cycles through the first few nodes fine, but dies at node 8
When inserting in the add() method, you never assign previous so it is null for all nodes.
The problem I am facing is figuring out how to write a method
public SingleLinkedList copy(Node <E> node) {
}
To return a copy of the list. I have tried:
public SingleLinkedList copy(Node <E> node) {
SingleLinkedList<E> temp = new SingleLinkedList<E>();
Node<E> ref = head;
for(Node<E> n = ref ;ref!= null; n = n.next){
temp.add(n, ref.data);
ref = ref.next;
}
return temp;
}
I created a new list called temp, changed head to ref, iterate through the list and add it to the new list and return the new list, but there's an error with temp.add(n, ref.data).
What am I possibly doing wrong?
class SingleLinkedList<E> {
private static class Node<E> {
private E data;//removed final * private final E data
private Node<E> next;
private Node(E item) {
data = item;
}
}
private Node<E> head;
private int size;
/* Insert item at index, returns true if add is successful. */
public boolean add(int index, E item) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("" + index);
}
if (index == 0) { // adding to the front
Node<E> t = head;
head = new Node<>(item);
head.next = t;
} else { // adding anywhere other than front
Node<E> left = getNode(index - 1);
Node<E> node = new Node(item);
Node<E> right = left.next;
left.next = node;
node.next = right;
}
size++;
return true;
}
/* Add item at end of list, returns true if successful. */
public boolean add(E item) {
return add(size, item);
}
/* Return item at index */
public E get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("" + index);
}
return getNode(index).data;
}
/* Return the number of items */
public int size() {
return size;
}
/* Returns a string representation of the list */
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[ ");
for (Node<E> n = head; n != null; n = n.next) {
sb.append(n.data);
sb.append(" ");
}
sb.append("]");
return sb.toString();
}
/* Return the node at location index */
private Node<E> getNode(int index) {
Node<E> n = head;
for (int i = 0; i < index; i++)
n = n.next;
return n;
}
The problem is you need to pass the position as an int. I also removed the Node n because you do not need it anyways.
I think this should work.
public SingleLinkedList copy() {
SingleLinkedList<E> temp = new SingleLinkedList<E>();
int i = 0;
for(Node<E> ref = head ;ref!= null; ref = ref.next){
temp.add(i++, ref.data);
}
return temp;
}
EDIT: I forgot to drop the parameter you do not need it at all.
I am trying to learn data structure, but I ran into the dreaded NullPointerException and I am not sure how to fix it.
My SinglyLinkedList<E> class implements an interface, LinkedList, where I redefined some methods like, add(), get(), contains(), and more.
The NullPointerException happens when I use the clear() method. It points at the method removeLast() under nodeBefore.setNext(null). It also points to the clear() method under remove(head.getElement()).
Also, if there is anything I can improve upon in my code please let me know.
public class SinglyLinkedList<E> implements LinkedList<E> {
private class Node<E> {
public Node<E> next;
public E element;
public Node(E element) {
this.element = element;
}
public Node (E element, Node<E> next) {
this.element = element;
this.next = next;
}
public E getElement() {
return element;
}
public Node<E> getNext() {
return next;
}
public void setElement(E element) {
this.element = element;
}
public void setNext(Node<E> next) {
this.next = next;
}
public String toString() {
return ("[" + element + "] ");
}
}
public Node<E> head;
public Node<E> tail;
public int total;
public SinglyLinkedList() {
this.head = null;
this.tail = null;
this.total = 0;
}
public E get(int index) {
if (index < 0 || index > size()) {
return null;
}
if (index == 0) {
return head.getElement();
}
Node<E> singly = head.getNext();
for (int i = 1; i < index; i ++) {
if (singly.getNext() == null) {
return null;
}
singly = singly.getNext();
}
System.out.println("\n" + singly.getElement());
return singly.getElement();
}
public void add(E element) {
Node<E> singlyAdd = new Node<E>(element);
if (tail == null) {
head = singlyAdd;
tail = singlyAdd;
} else {
tail.setNext(singlyAdd);
tail = singlyAdd;
}
total++;
}
public void display() {
if (head == null) {
System.out.println("empty list");
} else {
Node<E> current = head;
while (current != null) {
System.out.print(current.toString());
current = current.getNext();
}
}
}
public boolean contains(E data) {
if (head == null) {
return false;
}
if (head.getElement() == data) {
System.out.println(head);
return true;
}
while (head.getNext() != null) {
head = head.getNext();
if (head.getElement() == data) {
System.out.println(head);
return true;
}
}
return false;
}
private Node<E> removeFirst() {
if (head == null) {
System.out.println("We cant delete an empty list");
}
Node<E> singly = head;
head = head.getNext();
singly.setNext(null);
total--;
return singly;
}
private Node<E> removeLast() {
Node<E> nodeBefore;
Node<E> nodeToRemove;
if (size() == 0) {
System.out.println("Empty list");
}
nodeBefore = head;
for (int i = 0; i < size() - 2; i++) {
nodeBefore = nodeBefore.getNext();
}
nodeToRemove = tail;
nodeBefore.setNext(null);
tail = nodeBefore;
total--;
return nodeToRemove;
}
public E remove(int index) {
E hold = get(index);
if (index < 0 || index >= size()) {
return null;
} else if (index == 0) {
removeFirst();
return hold;
} else {
Node<E> current = head;
for (int i = 1; i < index; i++) {
current = current.getNext();
}
current.setNext(current.getNext().getNext());
total--;
return hold;
}
}
public int size() {
return getTotal();
}
public boolean remove(E data) {
Node<E> nodeBefore, currentNode;
if (size() == 0) {
System.out.println("Empty list");
}
currentNode = head;
if (currentNode.getElement() == data) {
removeFirst();
}
currentNode = tail;
if (currentNode.getElement() == data) {
removeLast();
}
if (size() - 2 > 0) {
nodeBefore = head;
currentNode = head.getNext();
for (int i = 0; i < size() - 2; i++) {
if (currentNode.getElement() == data) {
nodeBefore.setNext(currentNode.getNext());
total--;
break;
}
nodeBefore = currentNode;
currentNode = currentNode.getNext();
}
}
return true;
}
public void clear() {
while (head.getNext() != null) {
remove(head.getElement());
}
remove(head.getElement());
}
private int getTotal() {
return total;
}
}
For your clear method, I don't see that you do any per element cleanup, and the return type is void, so all you want is an empty list. The easiest way is to simply clear everything, like in the constructor:
public void clear() {
this.head = null;
this.tail = null;
this.total = 0;
}
Another comment:
in contains, you do
while (head.getNext() != null) {
head = head.getNext();
if (head.getElement() == data) {
System.out.println(head);
return true;
}
}
which may have two problems (where the first applies to the entire class),
you compare with == data which compares references, where you probably want to compare values with .equals(data)
Edit: I.e. n.getElement().equals(data) instead of n.getElement() == data.
(Or, if n and data may be null, something like (data != null ? data.equals(n.getElement()) : data == n.getElement())
you use the attribute head as the scan variable which modifies the state of the list. Do you really want that?
The problem arises when you delete the last element within clear: remove(head.getElement());. For some reason, you first remove the head and then the tail. But when calling removeLast, you use the head (which is already null). Within removeLast this is the line, which causes the NullPointerException: nodeBefore.setNext(null);.
My advice would be to write the clear() method as #bali182 has suggested:
public void clear() {
this.head = null;
this.tail = head;
this.total = 0;
}
One advice: if you are writing methods to search or delete entries, you should never use == when dealing with objects (or even better: don't use == at all when dealing with objects). You may want to read this thread.
From within clear method, you are calling remove(head.getElement()); meaning you are trying to call LinkedList's remove method. And since you are overriding each functionality and so is add, you don't maintain internal state of LinkedList and hence you get exception. Code in remove is:
public boolean remove(Object o) {
if (o==null) {
for (Entry<E> e = header.next; e != header; e = e.next) {
if (e.element==null) {
So here since you are not using functionality of LinkedList, header would be null and doing header.next would return NullPointerException.
I implemented doubly linked lists using nodes in Java. My code for the Node and linked list classes are below. Any suggestions for improving the design and/or running times of the operations?
public class Node implements Comparable<Node>{
Node next;
Node previous;
Object element;
int index;
public Node(Object element){
this.element = element;
this.next = null;
this.previous = null;
}
public Node(Object element, Node next, Node previous){
this.element = element;
this.next = next;
this.previous = previous;
}
public Node(Object element, Node next, Node previous, int index){
this.element = element;
this.next = next;
this.previous = previous;
this.index = index;
}
//Getter Method
public Node get_next(){
return this.next;
}
//For comparable class
public int compareTo(Node x){
if (this.element.equals(x.element)){
return 0;
}
else
return 1;
}
public boolean compare_index(int index){
if (this.index == index){
return true;
}
else
return false;
}
}
public class Mylinkedlists{
Node first_node;
Node last_node;
int size = 0;
//Constructors
public Mylinkedlists(Object element){
Node temp = new Node(element, last_node,first_node,0);
first_node = new Node (null,temp,null);
last_node = new Node(null,null,temp);
size+=1;
}
public Mylinkedlists(){
first_node = new Node (null,last_node,null);
last_node = new Node(null,null,first_node);
}
//Returns size of Node
public int size(){
return size;
}
//Adds element to end of linked list
public void add(Object element){
Node to_add = new Node(element);
Node temp = last_node.previous;
size+=1;
//Pointer changes
last_node.previous.next = to_add;
last_node.previous = to_add;
to_add.previous = temp;
to_add.next = last_node;
to_add.index = size-1;
}
//Inserts Element after node
public void insert(Object add_after, Object element_to_add) throws NotFoundException{
Node current = first_node.next;
Node insert_after = new Node(add_after);
Node to_add = new Node(element_to_add);
//find the node
while (current.compareTo(insert_after) != 0){
current = current.next;
}
//Inserts element after node
if (current.compareTo(insert_after) == 0){
Node temp = current.next;
current.next.previous = to_add;
to_add.next = temp;
current.next = to_add;
to_add.previous = current;
size+=1;
}
else
throw new NotFoundException("Element not in list");
}
//Removes element from linked list
public void remove(Object element) throws NotFoundException{
boolean stop = false;
Node search_for = new Node(element);
Node current = first_node.next;
for (int i = 0; i < size && !stop; i ++){
//Compares nodes
if (current.compareTo(search_for) == 1){
current.next.previous = current.previous;
current.previous.next = current.next;
current.next = null;
current.previous = null;
size-=1;
stop = true;
}
else
current = current.next;
}
//If element not in list
if (stop == false && current.next == null)
throw new NotFoundException("Element not in list");
}
//Removes element from end of linked list
public void remove_From_End(){
last_node.previous.next = null;
Node temp = last_node.previous.previous;
last_node.previous.previous = null;
last_node.previous = temp;
last_node.previous.next = last_node;
size -= 1;
}
//Returns true if list contains element, else false
public boolean contains(Object element){
boolean contains = false;
Node current = first_node.next;
Node with_element = new Node(element);
while (current.next != null){
if (current.compareTo(with_element) == 0)
return true;
else
current = current.next;
}
return contains;
}
public Object get(int index) throws NotFoundException{
if (index < 0 || index > (size-1))
throw new NotFoundException("Index out of range");
Node current = first_node;
for (int i = 0; i <= index; i++){
current = current.next;
}
return current.element;
}
public String toString(){
String temp = "";
Node temp2 = first_node;
for (int i = 0 ; i < size; i++){
temp2 = temp2.next;
temp += String.valueOf(temp2.element) + " ";
}
return temp;
}
}
For example, I access the elements of the Node class directly using dot(.) notation. Are getter and setter methods the only alternative? Moreover, is there any other implementation of the get method that would take less than O(n) time?
It is impossible for access to a linked list to take less than O(n). You will need to traverse through the array to access indivividual elements. There are faster ways to access individual elements, but that would require changing your data structure. The easiest data structure that I can think of would be an array. But then your insert and remove would be O(n).
So, in choosing your data structure, the question becomes what will you be doing more of insert and remove, or get?