For computer Science I'm coding a program that keeps the "tails" end of head, a Node so that I can add and remove from the Node/LinkedList. This isn't entirely difficult, but I've run into an issue that makes me cry. I am running into java heap space ( Out of Memory ).
Here is my code:
import java.util.NoSuchElementException;
/**
A linked list is a sequence of nodes with efficient
element insertion and removal. This class
contains a subset of the methods of the standard
java.util.LinkedList class.
*/
public class LinkedList
{
private Node head;
private int currentSize;
private Node tails;
/**
Constructs an empty linked list.
*/
public LinkedList()
{
head = null;
tails = null;
currentSize = 0;
}
/**
Adds an element to the front of the linked list.
#param element the element to add
*/
public void addFirst(Object element)
{
Node newNode = new Node();
if(head == null){
tails = newNode;
}
newNode.data = element;
currentSize++;
newNode.next = head;
head = newNode;
}
/**
Removes the head element in the linked list.
#return the removed element
*/
public Object removeFirst(){
if (head == null)
throw new NoSuchElementException();
Object temp = head.data;
head = head.next;
if(tails.next == null)
tails.next = head;
currentSize--;
return temp;
}
/**
Returns the head element in the linked list.
#return the head element in the linked list
*/
public Object getFirst()
{
if (head == null)
throw new NoSuchElementException();
return head.data;
}
/**
Returns the element at a given position in the linked list.
#param index the element position
#return the element at the given position
*/
Object get(int index)
{
if (index < 0)
throw new NoSuchElementException();
Node current = head;
int i = 0;
while (current != null && i < index)
{
current = current.next;
i++;
}
if (current == null)
throw new NoSuchElementException();
return current.data;
}
/**
Computes the size of the linked list
#return the number of elements in the list
*/
public int size()
{
//to be completed for lab 7.1 #2
return currentSize; // rewrite this, just makes it compile
}
/**
Reverses all elements in a linked list.
*/
public void reverse(){
Node currentNode, nextNode, loopNode;
if(head==null)
return;
currentNode=head;
nextNode= head.next;
loopNode = null;
while(nextNode != null){
currentNode.next = loopNode;
loopNode= currentNode;
currentNode=nextNode;
nextNode =nextNode.next;
}
head = currentNode;
head.next = loopNode;
}
/**
Adds an element to the end of the linked list.
#param element the element to add
*/
public void add(Object element){
Node current = new Node();
current.data = element;
if(tails.next == null)
tails.next = current;
tails = head;
currentSize ++;
}
/**
Returns an iterator for iterating through this list.
Allows the use of the iterator outside of this class.
#return an iterator for iterating through this list
*/
public ListIterator listIterator()
{
return new LinkedListIterator();
}
/**
Returns a string representation of this list in brackets
separated by commas.
#return a string of list elements.
*/
public String toString()
{
StringBuilder temp = new StringBuilder();
ListIterator it = listIterator();
while(it.hasNext()){
temp.append(it.next());
if(it.hasNext())
temp.append(", ");
}
return temp.toString();
}
private static class Node
{
private Object data;
private Node next;
}
private class LinkedListIterator implements ListIterator
{
private Node position;
private Node previous;
/**
Constructs an iterator that points to the front
of the linked list.
*/
public LinkedListIterator()
{
position = null;
previous = null;
}
/**
Moves the iterator past the next element.
#return the traversed element
*/
public Object next()
{
if (!hasNext())
throw new NoSuchElementException();
previous = position; // Remember for remove
if (position == null)
position = head;
else
position = position.next;
return position.data;
}
/**
Tests if there is an element after the iterator
position.
#return true if there is an element after the iterator
position
*/
public boolean hasNext()
{
if (position == null)
return head != null;
else
return position.next != null;
}
/**
Adds an element before the iterator position
and moves the iterator past the inserted element.
#param element the element to add
*/
public void add(Object element)
{
if (position == null)
{
addFirst(element);
position = head;
tails = head;
}
else{
Node newNode = new Node();
newNode.data = element;
newNode.next = position.next;
position.next = newNode;
position = newNode;
previous = position;
tails = newNode;
}
currentSize ++;
}
/**
Removes the last traversed element. This method may
only be called after a call to the next() method.
*/
public void remove()
{
if (previous == position)
throw new IllegalStateException();
if (position == head)
{
removeFirst();
currentSize --;
tails = previous;
}
else
{
previous.next = position.next;
currentSize --;
tails = previous;
}
position = previous;
}
/**
Sets the last traversed element to a different
data.
#param element the element to set
*/
public void set(Object element)
{
if (position == null)
throw new NoSuchElementException();
position.data = element;
}
}
}
The error is at removeFirst().
Any help?
Edits:
I'm attempting to store the last referenced node so I can play with it else where.
Usually that error implies infinite recursion. I suggest you look at the following code section.
while(it.hasNext()){
temp.append(it.next());
if(it.hasNext())
temp.append(", ");
}
Your code is quite bloated. Take a look at this:
How do I create a Linked List Data Structure in Java?
If you wan't extra marks try and add generics:
http://docs.oracle.com/javase/tutorial/java/generics/
Related
I am new in java. I have been trying to do some tests while teaching myself the language. Now I am on a linked list implementation. I chucked the code from test samples online. There are two files, LinkedList and LinkedListIterator. I am alright understanding the implementation. However, I would like to add to methods to the LinkedList class. One method (getString()) will be used to display a concatenation of all the string variables in the linkedlist. The second method getSize() will be used to display the size of the list. I have trouble getting the current instance of the linkedlist so I can iterate and get the strings and size. Can someone please assist? Help will be really appreciated.
The two files are as below:
import java.util.NoSuchElementException;
public class LinkedList
{
//nested class to represent a node
private class Node
{
public Object data;
public Node next;
}
//only instance variable that points to the first node.
private Node first;
// Constructs an empty linked list.
public LinkedList()
{
first = null;
}
// Returns the first element in the linked list.
public Object getFirst()
{
if (first == null)
{
NoSuchElementException ex
= new NoSuchElementException();
throw ex;
}
else
return first.data;
}
// Removes the first element in the linked list.
public Object removeFirst()
{
if (first == null)
{
NoSuchElementException ex = new NoSuchElementException();
throw ex;
}
else
{
Object element = first.data;
first = first.next; //change the reference since it's removed.
return element;
}
}
// Adds an element to the front of the linked list.
public void addFirst(Object element)
{
//create a new node
Node newNode = new Node();
newNode.data = element;
newNode.next = first;
//change the first reference to the new node.
first = newNode;
}
// Returns an iterator for iterating through this list.
public ListIterator listIterator()
{
return new LinkedListIterator();
}
public String toString(){
}
public int getSize(){
return this.size();
}
//nested class to define its iterator
private class LinkedListIterator implements ListIterator
{
private Node position; //current position
private Node previous; //it is used for remove() method
// Constructs an iterator that points to the front
// of the linked list.
public LinkedListIterator()
{
position = null;
previous = null;
}
// Tests if there is an element after the iterator position.
public boolean hasNext()
{
if (position == null) //not traversed yet
{
if (first != null)
return true;
else
return false;
}
else
{
if (position.next != null)
return true;
else
return false;
}
}
// Moves the iterator past the next element, and returns
// the traversed element's data.
public Object next()
{
if (!hasNext())
{
NoSuchElementException ex = new NoSuchElementException();
throw ex;
}
else
{
previous = position; // Remember for remove
if (position == null)
position = first;
else
position = position.next;
return position.data;
}
}
// Adds an element before the iterator position
// and moves the iterator past the inserted element.
public void add(Object element)
{
if (position == null) //never traversed yet
{
addFirst(element);
position = first;
}
else
{
//making a new node to add
Node newNode = new Node();
newNode.data = element;
newNode.next = position.next;
//change the link to insert the new node
position.next = newNode;
//move the position forward to the new node
position = newNode;
}
//this means that we cannot call remove() right after add()
previous = position;
}
// Removes the last traversed element. This method may
// only be called after a call to the next() method.
public void remove()
{
if (previous == position) //not after next() is called
{
IllegalStateException ex = new IllegalStateException();
throw ex;
}
else
{
if (position == first)
{
removeFirst();
}
else
{
previous.next = position.next; //removing
}
//stepping back
//this also means that remove() cannot be called twice in a row.
position = previous;
}
}
// Sets the last traversed element to a different value.
public void set(Object element)
{
if (position == null)
{
NoSuchElementException ex = new NoSuchElementException();
throw ex;
}
else
position.data = element;
}
} //end of LinkedListIterator class
}
LinkedListIterator class:
public interface ListIterator
{
//Move Moves the iterator past the next element.
Object next();
// Tests if there is an element after the iterator position.
boolean hasNext();
// Adds an element before the iterator position
// and moves the iterator past the inserted element.
void add(Object element);
// Removes the last traversed element. This method may
// only be called after a call to the next() method.
void remove();
// Sets the last traversed element to a different value.
void set(Object element);
}
Error when I try the implmentation of getSize():
Exception in thread "main" java.lang.StackOverflowError
at assignment10.LinkedList.size(LinkedList.java:84)
at assignment10.LinkedList.size(LinkedList.java:84)
at assignment10.LinkedList.size(LinkedList.java:84)
at assignment10.LinkedList.size(LinkedList.java:84)
The getSize() could be
public int getSize(){
int size = 0;
ListIterator iterator = listIterator();
while(iterator.hasNext()) {
iterator.next();
size++;
}
return size;
}
But it is not efficient to iterate over list each time to knowe it's size. The better solution is to store size as class variable and increase or decrease in methods modifying list.
The idea of toString() method is the same, iterate over the list and append each item to the result string
public String toString(){
StringBuilder sb = new StringBuilder();
ListIterator iterator = listIterator();
while(iterator.hasNext()) {
sb.append(String.valueOf(iterator.next())).append(",");
}
return sb.toString;
}
I'm creating a Stack Data Structure and am implementing it using a Linked List. I am using 3 java files - stack.java, stacktest.java and linkedList.java. The linked list works fine when I test it but the stack test is giving me the following errors
Is Empty?: true
Is Empty?: false
Exception in thread "main" java.lang.NullPointerException
at Stack.Peek(Stack.java:56)
at StackTest.main(StackTest.java:12)
Here is my stack.java file
import java.util.EmptyStackException;
public class Stack{
linkedList list;
int count;
public Stack()
{
list = new linkedList();
count = 0;
}
/**
* Adds a node to the head of the list
* #param c character to add
*/
public void Push(char c)
{
if(list.isEmpty())
{// If the list is empty
list.addFirst(c); // Add first
count++;
}
else
{
list.addAtEnd(c); // To the end (tail acts as head)
count++;
}
}
/**
* Removes a node from the head of the list
* #return char removed node
*/
public char Pop() throws EmptyStackException
{
if (!isEmpty())
{
return list.removeLast();
}
else
{
throw new EmptyStackException();
}
}
/**
* Returns the char from the head of the list
* #return char from top of the list
*/
public char Peek() throws EmptyStackException
{
if (!isEmpty())
{
return list.getTail().ch;
}
else
{
throw new EmptyStackException();
}
}
/**
* Is the list empty?
* #return true=yes false=no
*/
public boolean isEmpty()
{
return list.isEmpty();
}
/**
* Counts number of nodes within the list
* #return int # nodes in list
*/
public int getCount()
{
int counter = 0;
Node temp = list.getHead(); // Get head pointer.
while(temp.next != null) // Iterate until tail is reached.
counter++; // Increment counter on each node
return counter;
}
public void printStack()
{
list.printList();
}
}
My stacktest.java
import java.io.IOException;
public class StackTest {
public static void main(String args[]) throws IOException
{
Stack stackList = new Stack();
System.out.println("Is Empty?: " + stackList.isEmpty());
stackList.Push('A');
System.out.println("Is Empty?: " + stackList.isEmpty());
stackList.Pop();
stackList.Peek();
stackList.isEmpty();
stackList.getCount();
stackList.printStack();
}
}
And my linkedList.java
class Node
{
protected char ch;
protected Node next;
protected Node previous;
/**
* Construct a node with the given character value
* #param c - The character
*/
public Node (char c)
{
this.ch = c;
this.next = null;
this.previous = null;
}
}
public class linkedList
{ /** A reference to the head of the list */
protected Node head;
protected Node tail;
/**
* Construct a new empty list
*/
public linkedList()
{
head=null;
tail=null;
}
public Node getHead()
{
return head;
}
public Node getTail()
{
return tail;
}
/**
*Set c as first node in the list
*#param c The character to be inserted
*/
public void addFirst(char c)
{
Node newNode = new Node(c);
head=newNode; // Adding new element.
tail=newNode; // Head and tail will be the same.
}
/**
*Add a character to the end of the list
*#param c The character to be inserted
*/
public void addAtEnd(char c)
{
Node nod = new Node(c);
Node temp = head;
while (temp.next != null) // cycle until at end of list.
temp = temp.next;
temp.next=nod; // last element is new node.
nod.previous=temp; // linking last node with rest of list.
tail=nod; // new node is the tail.
}
/**
*Add a character in alphabetical order into the list
*#param c The character to be inserted
*/
public void addInOrder(char c)
{
Node n= new Node(c);
if(isEmpty())
{
addFirst(c);
}
else
{
Node pre=head;
Node succ= head.next;
if (n.ch < pre.ch)
{
n.next =head;// join node n to the list at the head.
head = n;// head is reading from n.
}
else
{
while(succ!=null && n.ch > succ.ch)
{ // find the position to insert the node
pre = succ;
succ = pre.next;
} //rearrange pointers
n.next = succ;
pre.next = n;
}
}
}
/**
*Test to see if this list is empty
*#returns true or false
*/
public boolean isEmpty()
{
return (head == null && tail == null);
}
/**
*removes a node from the head of the list
*#returns c The character from the removed node
*/
public char removeFirst()
{
if(!isEmpty())
{
// a temporary pointer to enable return of the char being removed
Node temp = head;
head = head.next; // move head pointer along the list
return temp.ch;
}
else
{
System.out.println("List is empty");
return '?'; //to indicate that the list is empty
}
}
/**
* removes a node from the tail of the list
* #return c The character from the removed node
*/
public char removeLast()
{
Node t = getTail(); // Retrieve tail
tail = t.previous; // Set tail to previous node
return t.ch; // return character
}
/**
*prints the characters in the list
*/
public void printList()
{
Node temp=head;
while(temp!=tail.next)
{
System.out.print(temp.ch + " ");
temp=temp.next;
}
System.out.println(); // After print, goes to new line.
}
}
I understand that I am using a variable which is null but can someone explain to me where I am going wrong
When you call addFirst(), it sets both the head and the tail to the new node. However, when you removeLast(), it only changes tail to null and leaves head set to the node you popped.
Then, when you call isEmpty(), since head is not null, it doesn't recognize that the list is empty and returns false.
You need to modify removeLast() to check whether you're removing the only element in the list, and update the head accordingly.
Once you have popped out your only element of the stack, the inner list is empty. Therefore list.getTail() will return null, and you cannot peek into your stack anymore.
In StackTest.java you are inserting one element into the stack, then popping it and then trying to peek into the stack. Your pop function is using removeLast method of linkedList.java. While you are correctly pointing the tail to tail.previous, you need to also check if the result of this leads to tail becoming null (which means you have removed the last element in your linked list). You should check for this in removeLast and make head = tail if this is the case:
public char removeLast()
{
Node t = getTail(); // Retrieve tail
tail = t.previous; // Set tail to previous node
if(tail == null){
head = tail;
}
return t.ch; // return character
}
This way isEmpty() method will always return true if you have popped out the last element in the list. You will have to make a similar change to removeFirst() as follows:
public char removeFirst()
{
if(!isEmpty())
{
// a temporary pointer to enable return of the char being removed
Node temp = head;
head = head.next; // move head pointer along the list
if(head == null){
tail = head;
}
return temp.ch;
}
else
{
System.out.println("List is empty");
return '?'; //to indicate that the list is empty
}
}
After this change your peek() method will now throw an EmptyStackException (which is desirable) instead of a NPE when you try to peek into an empty stack.
Might I also suggest that you don't need to traverse the whole list to add at the end of the list (on addAtEnd()). Since you already have the tail you can just append to the end of the tail pointer.
This is a LinkedList that have methods to modify the list. One of the things I have to do is:
Change the LinkedList class into a generic collection similar to the java.util.ArrayList class.
I don't know how to do that?
import java.util.NoSuchElementException;
/**
A linked list is a sequence of nodes with efficient
element insertion and removal. This class
contains a subset of the methods of the standard
java.util.LinkedList class.
*/
public class LinkedList<E>
{
int currentSize =0;
private Node head;
private Node tail;
/**
Constructs an empty linked list.
*/
public LinkedList()
{
head = null;
tail = null;
}
/**
Adds an element to the front of the linked list.
#param element the element to add
*/
public void addFirst(Object element)
{
Node newNode = new Node();
newNode.data = element;
newNode.next = head;
currentSize++;
head = newNode;
tail = head;
while( tail.next != null)
{
tail = tail.next;
}
}
/**
Removes the head element in the linked list.
#return the removed element
*/
public Object removeFirst()
{
if (head == null)
throw new NoSuchElementException();
Object temp = head.data;
head = head.next;
currentSize--;
return temp;
}
/**
Returns the head element in the linked list.
#return the head element in the linked list
*/
public Object getFirst()
{
if (head == null)
throw new NoSuchElementException();
return head.data;
}
/**
Returns the element at a given position in the linked list.
#param index the element position
#return the element at the given position
*/
Object get(int index)
{
if (index < 0)
throw new NoSuchElementException();
Node current = head;
int i = 0;
while (current != null && i < index)
{
current = current.next;
i++;
}
if (current == null)
throw new NoSuchElementException();
return current.data;
}
/**
Computes the size of the linked list
#return the number of elements in the list
*/
public int size()
{
//to be completed for lab 7.1 #2
return currentSize; // rewrite this, just makes it compile
}
/**
Reverses all elements in a linked list.
*/
public void reverse()
{
//to be completed for lab 7.1 #1
if(head == null)
throw new NoSuchElementException();
tail = head;
Node current = head;
Node nextt= head.next;
Node nul= null;
while(nextt!= null)
{
current.next = nul;
nul = current;
current = nextt;
nextt = nextt.next;
}
head = current;
head.next = nul;
}
/**
Adds an element to the end of the linked list.
#param element the element to add
*/
public void add(Object element)
{
if(head==null)
addFirst(element);
else
{
Node newNode = new Node();
newNode.data = element;
newNode.next = null;
tail.next = newNode;
tail = newNode;
currentSize++;
}
//to be completed for lab 7.1 #3
}
/**
Returns an iterator for iterating through this list.
Allows the use of the iterator outside of this class.
#return an iterator for iterating through this list
*/
public ListIterator listIterator()
{
return new LinkedListIterator();
}
/**
Returns a string representation of this list in brackets
separated by commas.
#return a string of list elements.
*/
public String toString()
{
StringBuilder temp = new StringBuilder();
ListIterator it = listIterator();
while(it.hasNext()){
temp.append(it.next());
if(it.hasNext())
temp.append(", ");
}
return temp.toString();
}
private static class Node
{
private Object data;
private Node next;
}
private class LinkedListIterator implements ListIterator
{
private Node position;
private Node previous;
/**
Constructs an iterator that points to the front
of the linked list.
*/
public LinkedListIterator()
{
position = null;
previous = null;
}
/**
Moves the iterator past the next element.
#return the traversed element
*/
public Object next()
{
if (!hasNext())
throw new NoSuchElementException();
previous = position; // Remember for remove
if (position == null)
position = head;
else
position = position.next;
return position.data;
}
/**
Tests if there is an element after the iterator
position.
#return true if there is an element after the iterator
position
*/
public boolean hasNext()
{
if (position == null)
return head != null;
else
return position.next != null;
}
/**
Adds an element before the iterator position
and moves the iterator past the inserted element.
#param element the element to add
*/
public void add(Object element)
{
if (position == null)
{
addFirst(element);
position = head;
}
else
{
Node newNode = new Node();
newNode.data = element;
newNode.next = position.next;
position.next = newNode;
position = newNode;
previous = position;
tail=head;
while( tail.next != null)
{
tail = tail.next;
}
currentSize++;
}
}
/**
Removes the last traversed element. This method may
only be called after a call to the next() method.
*/
public void remove()
{
if (previous == position)
throw new IllegalStateException();
if (position == head)
{
removeFirst();
}
else
{
previous.next = position.next;
tail=head;
while(tail.next != null)
{
tail = tail.next;
}
currentSize--;
}
position = previous;
}
/**
Sets the last traversed element to a different
data.
#param element the element to set
*/
public void set(Object element)
{
if (position == null)
throw new NoSuchElementException();
position.data = element;
}
}
}
They are both collections.
I believe you have to replace all instances of Object with E so that the java class can take the generic type it is declared with in the < >.
I understand the concept of LinkedList, and single/doubly linked list. I, however don't understand how to implement it to my code?
I have to convert this singly list to a doubly linked list:
public class MyLinkedList<E> extends MyAbstractList<E> {
private Node<E> head, tail;
/** Create a default list */
public MyLinkedList() {
}
/** Create a list from an array of objects */
public MyLinkedList(E[] objects) {
super(objects);
}
/** Return the head element in the list */
public E getFirst() {
if (size == 0) {
return null;
}
else {
return head.element;
}
}
/** Return the last element in the list */
public E getLast() {
if (size == 0) {
return null;
}
else {
return tail.element;
}
}
/** Add an element to the beginning of the list */
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;
}
/** Add an element to the end of the list */
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++; // Increase size
}
#Override /** Add a new element at the specified index
* in this list. The index of the head element is 0 */
public void add(int index, E e) {
if (index == 0) {
addFirst(e);
}
else if (index >= size) {
addLast(e);
}
else {
Node<E> current = head;
for (int i = 1; i < index; i++) {
current = current.next;
}
Node<E> temp = current.next;
current.next = new Node<E>(e);
(current.next).next = temp;
size++;
}
}
/** Remove the head node and
* return the object that is contained in the removed node. */
public E removeFirst() {
if (size == 0) {
return null;
}
else {
Node<E> temp = head;
head = head.next;
size--;
if (head == null) {
tail = null;
}
return temp.element;
}
}
/** Remove the last node and
* return the object that is contained in the removed node. */
public E removeLast() {
if (size == 0) {
return null;
}
else if (size == 1) {
Node<E> temp = head;
head = tail = null;
size = 0;
return temp.element;
}
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 temp.element;
}
}
#Override /** Remove the element at the specified position in this
* list. Return the element that was removed from the list. */
public E remove(int index) {
if (index < 0 || index >= size) {
return null;
}
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 current.element;
}
}
#Override /** Override toString() to return elements in the list */
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();
}
#Override /** Clear the list */
public void clear() {
size = 0;
head = tail = null;
}
#Override /** Return true if this list contains the element e */
public boolean contains(E e) {
System.out.println("Implementation left as an exercise");
return true;
}
#Override /** Return the element at the specified index */
public E get(int index) {
System.out.println("Implementation left as an exercise");
return null;
}
#Override /** Return the index of the head matching element in
* this list. Return -1 if no match. */
public int indexOf(E e) {
System.out.println("Implementation left as an exercise");
return 0;
}
#Override /** Return the index of the last matching element in
* this list. Return -1 if no match. */
public int lastIndexOf(E e) {
System.out.println("Implementation left as an exercise");
return 0;
}
#Override /** Replace the element at the specified position
* in this list with the specified element. */
public E set(int index, E e) {
System.out.println("Implementation left as an exercise");
return null;
}
#Override /** Override iterator() defined in Iterable */
public java.util.Iterator<E> iterator() {
return new LinkedListIterator();
}
private void checkIndex(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException
("Index: " + index + ", Size: " + size);
}
private class LinkedListIterator
implements java.util.Iterator<E> {
private Node<E> current = head; // Current index
#Override
public boolean hasNext() {
return (current != null);
}
#Override
public E next() {
E e = current.element;
current = current.next;
return e;
}
#Override
public void remove() {
System.out.println("Implementation left as an exercise");
}
}
private static class Node<E> {
E element;
Node<E> next;
public Node(E element) {
this.element = element;
}
}
}
So I understand to add a previous pointer, I have to do this:
private static class Node<E> {
E element;
Node<E> next;
Node<E> previous;
public Node(E element) {
this.element = element;
}
Now, I am confused - how do I actually implement the necessary methods for the doubly linked list? I am not asking for someone to do the entire assignment, but can someone show me an example of a worked out method?
I also couldn't understand, how does the program know I am referencing the previous element when I do Node<E> previous?
I also dont understand, just because I do "Node previous", how does the program know I am referencing the previous element?
The program doesn't know that you are referencing the previous element. You, the programmer, need to maintain (keep up-to-date and correct) that reference.
Every node will also have a reference to the previous node as it has reference to the next node.
Change the data structure of Node to add an extra Node reference to previous node. So now when someone calls the add(E e) method you will add that element at the tail and set the previous reference of e (which will be the new tail node) to the older tail node (which was the tail before add was called).
So in this way you are managing two references to previous and next nodes.
Also add a new method to your double link list class pervious() and related ones.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I am working on some code in Java that is supposed to implement the well-known
Josephus problem using a Circular Linked List. Here is some information on the Josephus
problem: http://en.wikipedia.org/wiki/Josephus_problem
I have a Student class and Driver class that have been given to me to create my Josephus class.
Here is the Student class: http://pastebin.com/4YgSA7CM
Here is the Driver class: http://pastebin.com/Nb08Dtqk
Neither of these classes can be modified.
I had to start from scratch and make a Josephus class that uses a Circular Linked List that effectively uses the Josephus problem.
Here is my completed Josephus class with no compiler errors:
/** Implementation of Josephus problem. The Josephus problem
is named after the historian Flavius Josephus. For more
information on this problem visit:
http://en.wikipedia.org/wiki/Josephus_problem
*/
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.ArrayList;
public class Josephus <E> {
private Node<E> head;
private int count; // number of elements in the list
/** Constructs an empty Josephus circle */
// Complexity O(1)
public Josephus() {
head = null;
count = 0;
}
/** Constructs an Josephus circle by adding the
elements from an arraylist
#param array The ArrayList of items of type E
*/
// Complexity: O(n)
public Josephus(ArrayList<E> array) {
head = null;
for (int i = 0; i < array.size(); i++)
add(array.get(i));
}
/** Inserts the specified element in the list at the
last position
#param dataItem the element to add
*/
// Complexity O(1)
#SuppressWarnings({ "unchecked" })
public void add(E dataItem) {
Node <E> node = new Node <E> (dataItem, null, null);
if (count == 0) // list is empty
head = node.previous= node ;
else
head.previous.next = node;
node.previous = head.previous;
head.previous = node;
count++;
}
// To be completed by the student
/** Inserts the specified element in the list at the
end. This method has the same behavior as add(E)
#param dataItem the element to add at the end
*/
// Complexity O(1)
public void addLast(E dataItem) {
add(dataItem);
}
/** Inserts the element at the beginning of the list
#param dataItem The element to be added
*/
// Complexity O(1)
public void addFirst(E dataItem) {
Node<E> node = new Node <E>(dataItem, null, null);
// To be completed by the student
if (head == null) // list is empty
head = head.previous = node;
else {
node.next = head;
head.previous = node;
head = node;
}
count++;
}
/** removes the element from the beginning of the list
#return The element that was remvoed
#throws NoSuchElementException if the list is empty
*/
// Complexity O(1)
public E removeFirst() {
// To be completed by the student
if (head != null) {
E item = head.data;
if (head == head.previous) // list has only one element
head = head.previous = null;
else { // list has more than 1 element
head = head.next;
head.previous = null;
}
count--;
return item;
}
else throw new NoSuchElementException();
}
/** removes the element from the end of the list
#return The element that was remvoed
#throws NoSuchElementException if the list is empty
*/
// Complexity O(1)
public E removeLast() {
// to be completed by the student
if (head.previous != null) {
E item = head.previous.data;
if (head == head.previous) // list has only one item
head = head.previous = null;
else { // list has more than one element
head.previous = (head.previous).previous;
head.previous.next = null;
}
count--;
return item;
}
else throw new NoSuchElementException();
}
/** returns a reference to the element at
position index
#param index The index of the element being sought
#return A reference to the element at position index
#throws IndexOutOfBoundsException if index is out of range
*/
// Complexity O(n)
public E get(int index) {
if ((index < 0) || (index >= count))
throw new IndexOutOfBoundsException(Integer.toString(index));
Node<E> temp = head;
for (int i = 0; i < index; i++)
temp = temp.next;
return temp.data;
}
/** Sets the element at position index to reference
anEntry.
#param index The position of the element that is to
be set
#param anEntry The new value at position index
#return the element that was previously at position index
#throws IndexOutOfBoundsException if index is out of range
*/
// Complexity O(n)
public E set(int index, E anEntry) {
if ((index < 0) || (index >= count))
throw new IndexOutOfBoundsException(Integer.toString(index));
Node<E> temp = head;
for (int i = 0; i < index; i++)
temp = temp.next;
E result = temp.data;
temp.data = anEntry;
return result;
}
/** Inserts the specified element in the list at a
given index
#param index The position at which the new element
has to be inserted
#param anEntry The element to add
#throws IndexOutOfBoundsException if index is out of range
*/
// Complexity O(n)
public void add(int index, E anEntry) {
// To be completed by the student
if ((index < 0) || (index > count))
throw new IndexOutOfBoundsException(Integer.toString(index));
if (index == 0) addFirst(anEntry);
else if (index == count) addLast(anEntry);
else {
Node <E> node = head;
int i = 0;
while(node!=null && i<index){
i++;
node = node.next;
}
Node<E> newNode = new Node <E> (anEntry, node, node.next);
node.next.previous = newNode;
node.next = newNode;
count++;
}
}
/** searches for target and returns the position of the
first occurrence, or -1 if it is not in the list
#param target The element we are searching for
#return The position of target if found; -1 if not found
*/
// Complexity O(n)
public int indexOf(E target) {
Node<E> temp = head;
for (int i = 0; i < count; i++) {
if (temp.data.equals(target)) return i;
temp = temp.next;
}
return -1;
}
/** removes the element at position index
#param index The index of the element to be removed
#return The element that was removed
#throws IndexOutOfBoundsException if index is invalid
*/
// Complexity O(n)
public E remove(int index) {
// to be completed by the student
if ((index < 0) || (index >= count))
throw new IndexOutOfBoundsException(Integer.toString(index));
Node<E> temp = head;
for(int i =0;i<index; i++)
temp = temp.next;
E result = temp.data;
temp.next = temp.previous;
return result;
}
/** sets the start position for the Josephus game
#param index The starting position
#throws IndexOutOfBoundsException if index is invalid
*/
// Complexity O(n)
public void setStartPosition(int index) {
if ((index < 0) || (index >= count))
throw new IndexOutOfBoundsException(Integer.toString(index));
for (int i = 0; i < index; i++)
head = head.next;
}
/* This private utility method is used in startJosephus
method.
Complexity O(1)
*/
private void removeAfter(Node<E> node) {
node.next = node.next.next;
node.next.previous = node;
count--;
}
/** simulates the Josephus game by killing every other person
until the winner is the only one left.
#return The survivor of the game
*/
public E startJosephus() {
E item =head.data;
if(head.next != null){
if(head == head.previous)
return item;
else
while(count>1);
removeAfter(head);
head =head.next;
}
return item;
}
/** Returns a list-iterator of the elements in this list
(in proper sequence), starting at the beginning
of the list.
*/
public ListIterator <E> iterator() {
return new myIterator();
}
/** #return The number of elements in the list
*/
public int size() {
return count;
}
// this is an inner clss implementing the ListIterator
// interface.
// visit http://docs.oracle.com/javase/1.4.2/docs/api/java/util/ListIterator.html
// for a complete list of methods in ListIterator
private class myIterator implements ListIterator <E> {
private Node<E> forward = head;
private Node<E> backward = head;
private boolean firstTime = true;
/** checks if a current item E is the last
in the collection
*/
public boolean hasNext() {
return (forward != null);
}
/** returns the next item in the collection if
there is one. If there is no more items
throws NoSuchElementException
*/
public E next() {
if (forward == null) throw
new NoSuchElementException();
else {
E item = forward.data;
forward = forward.next;
if (forward == head) forward = null;
return item;
}
}
/** checks if a current item is the first
in the collection
*/
public boolean hasPrevious() {
return (backward != null);
}
/** returns the previous item in the collection if
there is one. If there is no more items
throws NoSuchElementException
*/
public E previous() {
if (backward == null) throw
new NoSuchElementException();
else {
if (firstTime) {
backward = backward.previous;
firstTime = false;
}
E item = backward.data;
backward = backward.previous;
if (backward == head.previous) backward = null;
return item;
}
}
/* this operation is not supported */
public void add(E obj) {
throw new UnsupportedOperationException();
}
/* this operation is not supported */
public void set(E obj) {
throw new UnsupportedOperationException();
}
/* this operation is not supported */
public int previousIndex() {
throw new UnsupportedOperationException();
}
/* this operation is not supported */
public int nextIndex() {
throw new UnsupportedOperationException();
}
/* this operation is not supported */
public void remove() {
throw new UnsupportedOperationException();
}
}
private static class Node <E> {
private E data;
private Node<E> next;
private Node<E> previous;
/** constructor Creates an empty node with both next and
previous fields set to be null
#param dataItem - item to be inserted
*/
private Node(E dataItem) {
data= dataItem;
previous = next = null;
}
/** creates a new node that references another node
#param dataItem The data stored
#param previousNodeRef The node previous to this node
#param nextNodeRef The node next to this node
*/
private Node(E dataItem, Node<E> previousNodeRef, Node <E> nextNodeRef ) {
data = dataItem;
previous = previousNodeRef;
next = nextNodeRef;
}
}
}
My startJosephus method is the main problem I believe. Not completely sure though. Here is the startJosephus method specifically within that above code:
/** simulates the Josephus game by killing every other person
until the winner is the only one left.
#return The survivor of the game
*/
public E startJosephus() {
E item =head.data;
if(head.next != null){
if(head == head.previous)
return item;
else
while(count>1);
removeAfter(head);
head =head.next;
}
return item;
}
Here is what is running when I run my Josephus class: http://pastebin.com/5GnChgYd
Here is what the output is supposed to produce: http://pastebin.com/Qr5dCZJp
Also, here are the two input files used to produce this output:
StudentList1.txt: http://pastebin.com/ysjevQ8u
StudentList2.txt: http://pastebin.com/r2YeppNm
Based on the output I am getting and the output I am supposed to be getting, it appears the Josephus problem is not starting and simulating the killing spree. However, I do not know what is wrong with my code. My code cannot have a tail since it is a Circular Linked List. Any idea as to what I am doing wrong here? Sorry for all the Pastebin links, it just seemed like a better way to organize all of the code I am presenting here. Hope to hear your thoughts.
EDIT:
There are 21 persons in this list
The game starts with McElroy,Breanna at starting position
The killing spree begins......
The sole survivor at the end of this gruesome game is McElroy,Breanna
Exception in thread "main" java.lang.NullPointerException
at Josephus$Node.access$5(Josephus.java:383)
at Josephus.add(Josephus.java:49)
at Josephus.addLast(Josephus.java:66)
at Driver.main(Driver.java:96)
This is the new runtime errors I am getting after I fixed my problem with the infinite loop. Any suggestions???? What is with all of these Null Pointer Exceptions
if(head.next != null) {
if (head == head.previous)
return item;
else
while(count>1);
removeAfter(head);
head =head.next;
This piece of code will loop forever in all cases except when head.next is null or head == head.previous, which will always be true at the start of the game. Therefore, your program loops forever for anything but the trivial initial conditions. Obviously, you intended to write
if(head.next != null) {
if (head == head.previous)
return item;
else
while(count>1) {
removeAfter(head);
head =head.next;
}
I think you have an endless loop:
while (count > 1);