I have a LinkedList class that implements iterable interface, in the LinkedList class i have an inner node class. I have another TestLinkedList class that runs JUnit 4. The test class will check all of my functions in the linkedlist class.
Here is my LinkedListClass:
public class LinkedList<T> implements Iterable<T>
{
public class Node
{
private T value;
private Node next;
public Node(Node next, T value)
{
this.next = next;
this.value = value;
}
/**
* Returns the next node in the linked list.
*
* #return The next node in the linked list.
*/
public Node getNext()
{
return this.next;
}
/**
* Set the next node in the linked list.
*
* #param next
* The node to be added to the LinkedList.
*/
public void setNext(Node next)
{
this.next = next;
}
/**
* Return the value contained in the node.
*
* #return the value contained in the node.
*/
public T getValue()
{
return this.value;
}
/**
* Set the node with the value given.
*
* #param value
* The value to be placed in the node.
*/
public void setValue(T value)
{
this.value = value;
}
public String toString()
{
return "Node " + this.value;
}
}
public Node front;
public LinkedList()
{
front = null;
}
/**
* Return the number of elements in the LinkedList
*
* #return The size of the LinkedList
*/
public int getSize()
{
Node current = front;
int count = 0;
while (current != null)
{
count++;
current = current.getNext();
}
return count;
}
/**
* Return true if the LinkedList is empty, false otherwise
*
* #return true if the LinkedList is empty, false otherwise
*/
public boolean isEmpty()
{
return front == null;
}
/**
* Insert a node at the front of the linked list. The first variable should now point to this node. Wrap it in a
* node and add it to the list. Do not add the Node if it already exists in the list.
*
* #param node
* The node to be inserted into the linked list.
* #return true if inserted, false if already in list and cannot be inserted.
*/
public boolean insertFront(T element)
{
Node current = front;
boolean isExist = false;
while (current != null)
{
if (current.getValue().equals(element))
{
isExist = true;
}
current = current.getNext();
}
if (isExist == true)
{
return false;
}
else
{
front = new Node(front, element);
return true;
}
}
/**
* Insert a node at the back of the linked list. Wrap it in a node and add it to the list. Do not add the Node if it
* already exists in the list.
*
* #param node
* The node to be inserted into the linked list.
* #return true if inserted, false if already in list and cannot be inserted.
*/
public boolean insertBack(T element)
{
if (front == null)
{
insertFront(element);
return true;
}
else
{
Node current = front;
Node temp = current;
while (current!= null && !current.getValue().equals(element))
{
current = current.getNext();
}
if (current != null)
{
return false;
}
else
{
while(temp.getNext() != null)
{
temp = temp.getNext();
}
temp.setNext(new Node(null, element));
return true;
}
}
}
/**
* Insert the given node after the currentNode given. Wrap it in a node and add it in a position after the node
* specified by the variable {#code currentNode}. Throws a NodeNotFoundException if it can't found the node given.
* Do not add the Node if it already exists in the list.
*
* #param currentNode
* The node to look for to add the given node behind.
* #param node
* The element to be inserted into the linked list.
* #throws NodeNotFoundException
* Thrown if the element given is not found
* #return true if inserted, false if already in list and cannot be inserted.
*/
public boolean insertAfter(T currentElement, T element) throws NodeNotFoundException
{
Node current = front;
Node check = current;
while (current != null && !current.getValue().equals(currentElement))
{
current = current.getNext();
}
if (current == null)
{
throw new NodeNotFoundException("" + currentElement);
}
else
{
while(check != null && !check.getValue().equals(element))
{
check = check.getNext();
}
if (check != null)
{
return false;
}
else
{
current.setNext(new Node(current, element));
return true;
}
}
}
/**
* Insert the given node before the currentNode given. Wrap it in a node and add it in a position after the node
* specified by the variable {#code currentNode}. Throws a NodeNotFoundException if it can't found the node given.
* Do not add the Node if it already exists in the list.
*
* #param currentNode
* The node to look for to add the given node in front of.
* #param node
* The element to be inserted into the linked list.
*
* #throws NodeNotFoundException
* Thrown if the element given is not found
* #return true if inserted, false if already in list and cannot be inserted.
*/
public boolean insertBefore(T currentElement, T element) throws NodeNotFoundException
{
if (front == null)
{
throw new NodeNotFoundException("" + currentElement);
}
if (front.getValue().equals(currentElement))
{
insertFront(element);
return true;
}
Node previous = null;
Node current = front;
Node check = current;
while (current != null && !current.getValue().equals(currentElement))
{
previous = current;
current = current.getNext();
}
if (current == null)
{
throw new NodeNotFoundException("" + currentElement);
}
else
{
while (check != null && !check.getValue().equals(element))
{
check = check.getNext();
}
if (check != null)
{
return false;
}
previous.setNext(new Node(current, element));
return true;
}
}
/**
* Remove the node matches the given element. Return the element that is removed. Throws NodeNotFoundException if
* the element is not found.
*
* #param element
* The element to find and remove.
* #return Return the node that contains the element that was removed.
* #throws NodeNotFoundException
* Thrown if the element to be found can't be found.
*/
public T remove(T element) throws NodeNotFoundException
{
if(front == null)
{
throw new NodeNotFoundException(element.toString());
}
if( front.getValue().equals(element) )
{
front = front.getNext();
return element;
}
Node current = front;
Node previous = null;
while(current != null && !current.getValue().equals(element) )
{
previous = current;
current = current.getNext();
}
if(current == null)
{
throw new NodeNotFoundException(element.toString());
}
previous.setNext(current.getNext());
return element;
}
/**
* Remove all nodes in the LinkedList, return all nodes in an ArrayList.
*
*
* #return Returns all nodes in an ArrayList.
*/
public ArrayList<T> removeAll() throws NodeNotFoundException
{
Node current = front;
ArrayList<T> arrayList = new ArrayList<T>();
while (current != null)
{
arrayList.add(current.getValue());
current = current.getNext();
}
front = null;
return arrayList;
}
/**
* Return true if the element passed in is in the linked list.
*
* #param element
* The element to check for.
* #return true if the element exists in the linked list, false otherwise.
*/
public boolean contains(T element)
{
Node current = front;
while (current != null)
{
if (current.value.equals(element))
{
return true;
}
current = current.getNext();
}
return false;
}
/**
* Find an element and return it if it is found, otherwise return null
*
* #param element
* The element to look for.
* #return The element if found, null if not.
*/
public T findElement(T element)
{
Node check = front;
while (check != null && !check.getValue().equals(element))
{
check = check.getNext();
}
if (check == null)
{
return null;
}
else
{
return check.getValue();
}
}
/**
* Find an element and return it if it is found, otherwise return null
*
* #param element
* The element to look for.
* #return The element if found, null if not.
*/
public Node findNode(T element)
{
if(contains(element) == false)
{
return null;
}
else
{
Node check = front;
while (check != null && !check.getValue().equals(element))
{
check = check.getNext();
}
return check;
}
}
/**
* Converts the LinkedList to an ArrayList.
*
* #return An ArrayList containing all elements that are contained within the linked list.
*/
public ArrayList<T> convert()
{
Node current = front;
ArrayList<T> arrayList = new ArrayList<T>();
while (current != null)
{
arrayList.add(current.getValue());
current = current.getNext();
}
return arrayList;
}
/**
* Return the linked list as a string in the format element -> element -> element. For example
* "first -> second -> third"
*
* #return This linked list in the form of a string.
*/
#Override
public String toString()
{
Node current = front;
String s = "";
while (current.getNext() != null)
{
s += current.getValue() + "->";
current = current.getNext();
}
s += "" + current.getValue();
return s;
}
/*
* (non-Javadoc)
*
* #see java.lang.Iterable#iterator()
*/
#Override
public Iterator<T> iterator()
{
return new LinkedListIterator<T>(new LinkedList<T>());
}
}
This is my LinkedListIterator class:
public class LinkedListIterator<T> implements Iterator<T>
{
LinkedList<T>.Node previous;
LinkedList<T>.Node current;
public LinkedListIterator(LinkedList<T> list)
{
current = list.front;
}
/*
* (non-Javadoc)
*
* #see java.util.Iterator#hasNext()
*/
#Override
public boolean hasNext()
{
return current != null;
}
/*
* (non-Javadoc)
*
* #see java.util.Iterator#next()
*/
#Override
public T next()
{
if (!hasNext())
{
return null;
}
T temp = current.getValue();
previous = current;
current = current.getNext();
return temp;
}
/*
* (non-Javadoc)
*
* #see java.util.Iterator#remove()
*/
#Override
public void remove()
{
previous.setNext(current.getNext());
}
}
Here is my TestLinkedList class:
public class TestLinkedList
{
private static String FIRST = "First";
private static String SECOND = "Second";
private static String THIRD = "Third";
private static String FOURTH = "Fourth";
private static String MISSING = "Missing";
private static String TEST_STRING = "First->Second->Third->Fourth";
private static String TEST_ARRAY = "[First,Second,Third,Fourth]";
private LinkedList<String> testList;
#Before
public void setUp() throws NodeNotFoundException
{
testList = new LinkedList<String>();
}
#Test
public void testNextAndHasNext() throws NodeNotFoundException
{
insertAll(testList);
assertTrue("Next/HasNext failed", compareListToStrings(testList, FIRST, SECOND, THIRD, FOURTH));
}
#Test
public void testIsEmpty() throws NodeNotFoundException
{
insertAll(testList);
assertFalse("isEmpty Failed", testList.isEmpty());
removeViaIterator(testList);
assertTrue("isEmpty Failed after emptying", testList.isEmpty());
}
#Test
public void testIteratorRemove() throws NodeNotFoundException
{
insertAll(testList);
removeViaIterator(testList);
Iterator<String> iter = testList.iterator();
assertFalse("Iterator remove failed", iter.hasNext());
}
#Test
public void testInsertFrontAndBack()
{
assertTrue("insertFront failed on first insert", testList.insertFront(FIRST));
assertTrue("insertFront failed, list has too many elements", compareListToStrings(testList, FIRST));
assertFalse("insertFront failed, same element added to list", testList.insertFront(FIRST));
assertTrue("insertBack failed when inserting element not in list", testList.insertBack(FOURTH));
assertTrue("insertBack failed, list has wrong elements", compareListToStrings(testList, FIRST, FOURTH));
assertFalse("insertBack failed, same element already added to list", testList.insertBack(FOURTH));
}
#Test(expected = NodeNotFoundException.class)
public void testNodeNotFound() throws NodeNotFoundException
{
testList.insertBefore(MISSING, MISSING);
}
#Test
public void testInsertBeforeAndAfter() throws NodeNotFoundException
{
testList.insertFront(FOURTH);
testList.insertFront(FIRST);
assertTrue("insertBefore failed", testList.insertBefore(FOURTH, THIRD));
assertTrue("insertBefore failed, list does not have right elements",
compareListToStrings(testList, FIRST, THIRD, FOURTH));
assertFalse("insertBeforeFailed on inserting duplicate elements", testList.insertBefore(FOURTH, THIRD));
assertTrue("insertAfter failed", testList.insertAfter(FIRST, SECOND));
assertTrue("insertAfter failed, list does not have right elements",
compareListToStrings(testList, FIRST, SECOND, THIRD, FOURTH));
assertFalse("insertAfter failed on inserting duplicate elements", testList.insertAfter(FIRST, SECOND));
}
#Test
public void testToStringAndToArray()
{
testList.insertFront(FOURTH);
testList.insertFront(THIRD);
testList.insertFront(SECOND);
testList.insertFront(FIRST);
String listString = testList.toString();
assertTrue("toString failed", listString.replaceAll("\\s+", "").equals(TEST_STRING));
String arrayString = testList.convert().toString();
assertTrue("convert failed", arrayString.replaceAll("\\s+", "").equals(TEST_ARRAY));
}
#Test
public void testContains()
{
testList.insertFront(FOURTH);
testList.insertFront(THIRD);
testList.insertFront(SECOND);
testList.insertFront(FIRST);
assertTrue("Contains failed", testList.contains(FIRST));
}
#Test
public void testFind()
{
testList.insertFront(FOURTH);
testList.insertFront(THIRD);
testList.insertFront(SECOND);
testList.insertFront(FIRST);
String element = testList.findElement(SECOND);
assertNotNull("find failed, element null", element);
assertEquals(SECOND, element);
assertTrue("Find failed", findNode(testList, testList.findNode(SECOND)));
}
#Test
public void testRemove() throws NodeNotFoundException
{
testList.insertFront(FOURTH);
testList.insertFront(THIRD);
testList.insertFront(SECOND);
testList.insertFront(FIRST);
String second = testList.remove(SECOND);
assertNull("Found Second in list after removal", testList.findNode(SECOND));
assertEquals(SECOND, second);
}
#Test
public void testRemoveAll() throws NodeNotFoundException
{
testList.insertFront(FOURTH);
testList.insertFront(THIRD);
testList.insertFront(SECOND);
testList.insertFront(FIRST);
ArrayList<String> control = testList.convert();
ArrayList<String> result = testList.removeAll();
Iterator<String> iter = testList.iterator();
assertEquals(control, result);
assertFalse("RemoveAll Failed", iter.hasNext());
}
#Test
public void testSize()
{
assertEquals(0, testList.getSize());
testList.insertFront(FOURTH);
testList.insertFront(THIRD);
testList.insertFront(SECOND);
testList.insertFront(FIRST);
assertEquals(4, testList.getSize());
}
private static <T> boolean compareListToStrings(LinkedList<T> list, T... values)
{
int index = 0;
Iterator<T> iter = list.iterator();
while (iter.hasNext())
{
if (!values[index].equals(iter.next()))
{
return false;
}
index++;
}
return true;
}
private static <T> boolean findNode(LinkedList<T> list, LinkedList<T>.Node n)
{
Iterator<T> iter = list.iterator();
while (iter.hasNext())
{
if (n.getValue().equals(iter.next()))
{
return true;
}
}
return false;
}
private static void insertAll(LinkedList<String> list) throws NodeNotFoundException
{
list.removeAll();
list.insertFront(FOURTH);
list.insertFront(THIRD);
list.insertFront(SECOND);
list.insertFront(FIRST);
}
private static <T> void removeViaIterator(LinkedList<T> list) throws NodeNotFoundException
{
Iterator<T> iter = list.iterator();
while (iter.hasNext())
{
iter.next();
iter.remove();
}
}
}
the test class has 12 tests, and among them are the testIsEmpty and testFind.
When i ran the test, I failed these two tests.
i failed the testIsEmpty because of the last assert:
assertTrue("isEmpty Failed after emptying", testList.isEmpty());
The testFind failed because of this assert:
assertTrue("Find failed", findNode(testList, testList.findNode(SECOND)));
in the TestIsEmpty, I was thinking that I implemented the remove() function in the iterator class wrong, but I had no idea why. The testFind I looked at the function findNode() and I was pretty sure that there was nothing wrong with it.
It would be great if someone can check my code.
It seems when you are defining the iterator() in LinkedList you are creating a new LinkedList object instead of using the list you want to iterate on. So when you call Iterator iter = list.iterator() in removeViaIterator() method it is not returning any data and the while loop is not getting executed in the method.
Problems with findNode (actually, the iterator)
Sambaran spotted this one while I was typing...
LinkedList.iterator creates a new LinkedList every time it's called, and passes that to the LinkedListIterator constructor:
return new LinkedListIterator<T>(new LinkedList<T>());
The LinkedListIterator will always report (correctly) that the LinkedList is empty. That line should instead be:
return new LinkedListIterator<T>(this);
Problems with isEmpty (also the iterator)
The test is correct --- the list is not empty. LinkedListIterator.remove will never remove the first Node, so TestLinkedList.removeViaIterator will never completely empty a list.
Consider a LinkedListIterator traversing a LinkedList of only one Node: current points to the one and only Node, and previous points (by default) to null. After the iterator's next method is called once, current will point to the end-of-list null, while previous will point to the one and only Node... and it's now too late to remove the once-current Node.
current should not start at front, but in some illegal "pre-front" state; it should advance to front the first time next is called. Consider initializing it with a bogus Node that exists "before" the real list:
public class LinkedListIterator<T> implements Iterator<T>
{
final LinkedList<T> list;
LinkedList<T>.Node previous;
LinkedList<T>.Node current;
boolean canRemove;
public LinkedListIterator(LinkedList<T> list) {
// Required by remove.
this.list = list;
// Required by remove.
this.canRemove = false;
// No change, just making it explicit.
this.previous = null;
// Bogus "pre-front" Node, for before first call to next.
this.current = this.list.new Node(this.list.front, null);
}
// etc...
}
I added the list field so remove can handle the special case of removing front --- it has to update LinkedList.front instead of previous.next.
The canRemove is there to solve several other problems...
Problems with the Iterator contract
Your LinkedListIterator.next method should throw a NoSuchElementException when there is no next element. It should not return null, especially when null is a legal element value.
The remove method should raise an IllegalStateException in two situations:
[...] if the next method has not yet been called, or the remove method has already been called after the last call to the next method
That's from the Iterator interface's docs. You should (re-)read them carefully, because it's very easy to write an "Iteratorish" that works just well enough to make debugging everything else a nightmare.
The canRemove field can handle all of these cases. Initialize it to false. It is set to true by the next method (even if already true --- next doesn't care), and set to false again by the remove method. The only code that reads this is the remove method:
#Override
public void remove() {
if (!this.canRemove) {
throw new IllegalStateException("Helpful error message.");
}
// Remove current Node.
this.canRemove = false;
return;
}
Other Observations
Your JavaDocs are often outright wrong. For example, many of them claim the user can insert a Node into the list, when really the user inserts a type-T element. findNode, ironically, has the opposite problem: claiming that it returns an element, when it really returns a Node. (It doesn't help that there's a completely different findNode method in your test class.) I stopped reading your comments because they were so often misleading.
Your LinkedList can store null elements. This is OK, if awkward. What's not OK is that you often do something like if (someNode.getValue().equals(someElement)) { ... }, which will throw a NullPointerException if that node is storing a null.
findElement indicates success by returning the element found, and failure by returning null. But null is a legal element value, so findElement(null) will always return null. Does that mean you found it, or you didn't? Consider throwing a NodeNotFoundException (or ElementNotFoundException?) to indicate failure, like you do elsewhere. (As an aside, how is findElement different from contains?)
You often iterate through the whole list when you don't have to... and you duplicate much of the Iterator's code to do so. So use the Iterator! (...once it's fixed.)
You can just maintain a private int size field for use with getSize (and isEmpty), instead of counting all the elements in your list.
LinkedList.front should be private (with all the edits that implies).
That whole "Do not add the Node if it already exists in the list." thing is... not how lists usually behave. It's much more like a set, and a linked list is a terribly inefficient way to make a set.
Don't Repeat Yourself! Count the places you start at LinkedList.front and walk down the linked Nodes. Why not just call findNode or contains? Count the places you compare two Node elements, or (slightly different) determine if a could-be-null Node reference contains a known element. Replace that code with a private method or two, then use them. (That method would then handle the null elements I mentioned above, so you wouldn't have "if-null-else" sprinkled all over your code.)
Related
Basically i'm trying to write a print statement that will allow me to print the elements per line as a println as the output when i run the driver.java. And for the life of me i cannot figure out how to do it. Any help will be appreciated.
here is the driver.java
public class Driver {
public static void main(String args[]){
LList<String> s_list = new LList<String>();
s_list.insert("New York, 8.4M");
s_list.insert("Los Angeles 3.8M");
s_list.insert("Chicago, 2.7M");
s_list.insert("Houston, 2.1M");
s_list.insert("Philadelphia, 1.55M");
s_list.insert("Phoenix, 1.51M");
s_list.append("San Antonio, 1.4M");
s_list.append("San Diego, 1.35M");
s_list.append("Dallas, 1.25M");
s_list.append("San Jose, 0.998M");
s_list.append("Austin, 0.88M");
s_list.append("Indianapolis, 0.84M");
s_list.append("Jacksonville, 0.84M");
s_list.append("San Francisco, 0.83M");
s_list.append("Columbus, 0.82M");
s_list.append("Charlotte, 0.79M");
s_list.print();
s_list.moveToPos(3);
s_list.remove();
s_list.print();
s_list.moveToEnd();
s_list.remove();
s_list.print();
s_list.moveToStart();
s_list.remove();
s_list.remove();
s_list.print();
s_list.clear();
s_list.print();
}
}
and I have a java file named LList.java
where I am trying to write a print method where it will print() function that prints the contents of each element of your list; print one element per line.
public void print {
}
So, How will i print the elements in "s_list" line per line as output.
Any help is appreciated.
UPDATE: I am going to post Llist.java,list.java & link.java here
Llist.java
/** Linked list implementation */
class LList<E> implements List<E> {
private Link<E> head; // Pointer to list header
private Link<E> tail; // Pointer to last element
protected Link<E> curr; // Access to current element
private int cnt; // Size of list
/** Constructors */
LList(int size) { this(); } // Constructor -- Ignore size
LList() {
curr = tail = head = new Link<E>(null); // Create header
cnt = 0;
}
/** Remove all elements */
public void clear() {
head.setNext(null); // Drop access to links
curr = tail = head = new Link<E>(null); // Create header
cnt = 0;
}
/** Insert "it" at current position */
public void insert(E it) {
curr.setNext(new Link<E>(it, curr.next()));
if (tail == curr) tail = curr.next(); // New tail
cnt++;
}
/** Append "it" to list */
public void append(E it) {
tail = tail.setNext(new Link<E>(it, null));
cnt++;
}
/** Remove and return current element */
public E remove() {
if (curr.next() == null) return null; // Nothing to remove
E it = curr.next().element(); // Remember value
if (tail == curr.next()) tail = curr; // Removed last
curr.setNext(curr.next().next()); // Remove from list
cnt--; // Decrement count
return it; // Return value
}
/** Set curr at list start */
public void moveToStart()
{ curr = head; }
/** Set curr at list end */
public void moveToEnd()
{ curr = tail; }
/** Move curr one step left; no change if now at front */
public void prev() {
if (curr == head) return; // No previous element
Link<E> temp = head;
// March down list until we find the previous element
while (temp.next() != curr) temp = temp.next();
curr = temp;
}
/** Move curr one step right; no change if now at end */
public void next()
{ if (curr != tail) curr = curr.next(); }
/** #return List length */
public int length() { return cnt; }
/** #return The position of the current element */
public int currPos() {
Link<E> temp = head;
int i;
for (i=0; curr != temp; i++)
temp = temp.next();
return i;
}
/** Move down list to "pos" position */
public void moveToPos(int pos) {
assert (pos>=0) && (pos<=cnt) : "Position out of range";
curr = head;
for(int i=0; i<pos; i++) curr = curr.next();
}
/** #return Current element value */
public E getValue() {
if(curr.next() == null) return null;
return curr.next().element();
}
public void print()
{
}
}
List.java
/** List ADT */
public interface List<E> {
/** Remove all contents from the list, so it is once again
empty. Client is responsible for reclaiming storage
used by the list elements. */
public void clear();
/** Insert an element at the current location. The client
must ensure that the list�s capacity is not exceeded.
#param item The element to be inserted. */
public void insert(E item);
/** Append an element at the end of the list. The client
must ensure that the list�s capacity is not exceeded.
#param item The element to be appended. */
public void append(E item);
/** Remove and return the current element.
#return The element that was removed. */
public E remove();
/** Set the current position to the start of the list */
public void moveToStart();
/** Set the current position to the end of the list */
public void moveToEnd();
/** Move the current position one step left. No change
if already at beginning. */
public void prev();
/** Move the current position one step right. No change
if already at end. */
public void next();
/** #return The number of elements in the list. */
public int length();
/** #return The position of the current element. */
public int currPos();
/** Set current position.
#param pos The position to make current. */
public void moveToPos(int pos);
/** #return The current element. */
public E getValue();
}
Link.java
/** Singly linked list node */
class Link<E> {
private E element; // Value for this node
private Link<E> next; // Pointer to next node in list
// Constructors
Link(E it, Link<E> nextval)
{ element = it; next = nextval; }
Link(Link<E> nextval) { next = nextval; }
Link<E> next() { return next; } // Return next field
Link<E> setNext(Link<E> nextval) // Set next field
{ return next = nextval; } // Return element field
E element() { return element; } // Set element field
E setElement(E it) { return element = it; }
}
We will need to see inside the class of LList.java... but for now i am going to assume LList extends List [or ArrayList, etc..]
public void print
{
for(int i = 0; i < this.size(); i++) //this really depends on how you store your list
System.out.println(this.get(i));
}
This all depends on how your LList.java looks though... [this.size()] refers to the List or ArrayList class [if you extended it...].
If you are not extending List or something along those lines, you could always do:
public void print
{
for(int i = 0; i < storingArray.size(); /*or .length*/ i++)
System.out.println(storingArray.get(i)); /*or storingArray[i]*/
}
But as always, you could take the easy way and just do:
list.foreach(System.out::println); //must have Java 8.
Revised Answer based on your comments:
public void print() {
Link<E> currentNode = head; //Sets starting node to first node in list
while (currentNode != tail) { //Checks if current node is equal to last node
System.out.println(currentNode.element()); //Prints currentNodes's element
currentNode = currentNode.next(); //Sets currentNode to next node in list
}
System.out.println(tail.element()); //Prints last node in list
}
Note: Some of your comments in you Link<E>code don't match what your functions are actually doing.
I am having trouble implementing my linkedlist. When I run the code it just doesn't produce anything and keeps running.
UPDATE: I edited the toString to look like this:
LinearNode<T> current = head;
String result = "";
while (current != null) {
result = result + (current.getElement()).toString() + "\n";
current = current.next;
}
return result;
Now it works and prints so the error must be in the iterator.
Here is LinkedList class:
import java.util.*;
import java.util.Iterator;
public class LinkedList10Handout<T> implements ListADT<T>
{
protected int count;
protected LinearNode<T> head, tail, current, previous;
//===========================================================
// Creates an empty list.
//===========================================================
public LinkedList10Handout()
{
count = 0;
head = tail = null;
current = null;
} // constructor List
/**************************************************************
// Precondition: head is the head reference of a linked list.
// The list might be empty or it might be non-empty.
// PostCondition: One node has been added to the list.
//**************************************************************/
public void InsertFirst(T addData)//*********************************
{
LinearNode<T> newnode = new LinearNode<T>(addData, null);
if (isEmpty())
{
head = newnode;
tail = newnode;
}
else
{
newnode.next = head;
head = newnode;
}
if (current == head.next)
previous = head;
count++;
// LIST REQUIREMENTS:
// if the list was initially empty, put tail on the list
//if current was initially at the first node, we must now put previous behind it
}
/**************************************************************
// this method calls insertAfter method after it finds the node it wants to insert a node after
/**************************************************************/
public boolean Insert(T target, T addData)//*************************
{
LinearNode<T> find = find(target);
boolean found = false;
if (find != null)
{
found = true;
insertAfter(addData);
}
// calls find
// if target is found
//the method calls insertafter(addData) WHICH DOES THE ACTUAL INSERT
return found; // this is just here to allow it to compile
}
/*****************************************************************
// inserts a node at the end of the tail
// CHECKS IF THE LIST IS EMPTY FIRST AND CALLS INSERTFIRST
// ELSE INSERTS ON THE END OF THE LIST
/******************************************************************/
public void insertTail(T target )//******************
{
if (isEmpty())
InsertFirst(target);
else
{
LinearNode<T> newnode = new LinearNode<T> (target, null);
tail.next = newnode;
tail = newnode;
}
count++;
// INSERT NODE ON THE TAIL
}
//===========================================================
// Precondition: The List is not empty
// Removes the first element in the list and returns a reference
// to it. Throws an EmptyListException if the list is empty.
//===========================================================
public T removeFirst() throws EmptyCollectionException //*************************
{
LinearNode<T> removed = head;
if (isEmpty())
throw new EmptyCollectionException("List");
else
head = head.next;
// delete the first node
// return the data;
count--;
return removed.getElement(); // this is to get it to compile - change it
} // method removeFirst
/**************************************************************
*Inserts node with newData after the node current points to. The current
*node is the same AFTER THE NODE IS INSERTED
*Should not be used with an empty list. Should not be
*used when the current node IS NULL.
/*******Before insertAfter is called current must be pointing to A node on the list
**************************************************************/
public void insertAfter(T newData)//*****************
{
LinearNode<T> newnode = new LinearNode<T>(newData, current.next);
current.next = newnode;
if (current == tail)
tail.next = newnode;
count++;
}// close method
/*********************************************************
Finds the first node containing the target data, and returns a
reference to that node. If key is not in the list, null is returned.
*********************************************************/
public LinearNode<T> find(T target) // WE DID THIS IN CLASS
{
if (!isEmpty())
{
for (current = head; current.getElement() != target; current = current.next)
// set up a for loop with current initialed to point to what head is pointing to.
{
previous = previous.next;
return current;
}
// inside the loop compare the element current is presently pointing to, to target
// if they are equal return current.element
// advance previous so that it follows current
}
return null;
} // close method
//===========================================================
// Precondition: Throws an EmptyListException if the list is empty.
// Throws a NoSuchElementException if the specified element is not found on the list.
// PostCondition:Removes the first instance of the specified element from the
// list if it is found in the list and returns a reference to it.
// SEVERAL SITUATIONS MUST BE HANDLED AS LISTED BELOW
//===========================================================
public T remove (T target) throws EmptyCollectionException, ElementNotFoundException //**************
{
if (isEmpty())
throw new EmptyCollectionException ("List");
LinearNode<T> find = find(target);
if (find == null)
throw new ElementNotFoundException ("List");
LinearNode<T> removed = new LinearNode<T> (target, null);
// MAKE SURE TARGET IS ON THE LIST
// conditions you have to address:
//(1) if there is only one node on the list
if (size() == 1)
head = tail = null;
else
if (find == head)
removeFirst();
else
if (find == tail)
removeLast();
else
{
previous.next = current.next;
current = current.next;
}
//(2) if (current points to head node and there is more than one node on the list
// (3) else if current equals tail - we are at the last node - HINT - USE PREVIOUS
//(4)IF NONE OF THE ABOVE IS TRUE we are somewhere in the middle of the list
// where current is pointing to node to be deleted
// and previous is right behind it - delete THAT node
count--;
// return the removed element
return removed.getElement();// this is just to get it to compile
} // method remove
//===========================================================
// Removes the last element in the list and returns a reference
// to it. Throws an EmptyListException if the list is empty.
// CALLS FIND TO LOCATE CURRENT ON THE TAIL NODE
// DETERMINES FIRST IF THE THERE IS ONLY ONE NODE AND THEN DELETES THAT
//===========================================================
public T removeLast() throws EmptyCollectionException //*******************************
{
// remove last node
if (isEmpty())
throw new EmptyCollectionException("List");
find(tail.getElement());
previous.next = current.next;
current = current.next;
count--;
return current.getElement();// was result
} // method removeLast
//===========================================================
// Finds the first instance of the specified element from the
// list if it is found in the list and returns true.
// Returns false otherwise. Calls the find method to find target
//===========================================================
public boolean contains (T targetElement) throws EmptyCollectionException //****************
{
if (isEmpty())
throw new EmptyCollectionException ("List");
boolean found = false;
LinearNode<T> find = find(targetElement);
if (find != null)
found = true;
return found;
} // method contains
//===========================================================
// Returns true if the list is empty and false otherwise
//===========================================================
public boolean isEmpty()
{
return (count == 0);
} // method isEmpty
//===========================================================
// Returns the number of elements in the list.
//===========================================================
public int size() //*******************
{
// put in code
return count; // CHANGE THIS< IT IS TO GET IT TO COMPILE
} // method size
//===========================================================
// Returns ...
//===========================================================
public Iterator<T> iterator()
{
return new LinkedIterator<T>(head, count);
} // method elements
//===========================================================
// Returns a string representation of the list.
//===========================================================
public String toString() //*******************************
{
String result = "";
Iterator<T> iter = iterator();
while (iter.hasNext())
{
result += iter + "\n";
// traverse the list and accumulate the elements in result as you did in DatingService with hobbies
}
return result;
} // method toString
//===========================================================
// Returns the first element of the list.
//===========================================================
public T first() //***************************
{
return head.getElement(); // this is to get it to compile - change it
} // method firstElement
//===========================================================
// Returns the last element of the list.
//===========================================================
public T last()//********************
{
// put in code
return tail.getElement(); // this is to get it to compile - change it
} // method lastElement
} // class LinkedList
class EmptyCollectionException extends RuntimeException
{
//-----------------------------------------------------------------
// Sets up this exception with an appropriate message.
//-----------------------------------------------------------------
public EmptyCollectionException (String collection)
{
super ("The " + collection + " is empty.");
}
}
class LinkedIterator<T> implements Iterator
{
private int count; // the number of elements in the collection
private LinearNode<T> current; // the current position
//-------------------------------------------------------------
// Sets up this iterator using the specified items.
//-------------------------------------------------------------
public LinkedIterator (LinearNode<T> collection, int size)
{
current = collection;
count = size;
}
//-------------------------------------------------------------
// Returns true if this iterator has at least one more element
// to deliver in the iteraion.
//-------------------------------------------------------------
public boolean hasNext()
{
return (current!= null);
}
//-------------------------------------------------------------
// Returns the next element in the iteration. If there are no
// more elements in this itertion, a NoSuchElementException is
// thrown.
//-------------------------------------------------------------
public T next() //*********************************************
{
if (! hasNext())
throw new NoSuchElementException();
// put in code
return current.next.getElement(); // this is to get it to compile - change it
}
//-------------------------------------------------------------
// The remove operation is not supported.
//-------------------------------------------------------------
public void remove() throws UnsupportedOperationException
{
throw new UnsupportedOperationException();
}
}
class ElementNotFoundException extends RuntimeException
{
//-----------------------------------------------------------------
// Sets up this exception with an appropriate message.
//-----------------------------------------------------------------
public ElementNotFoundException (String collection)
{
super ("The target element is not in this " + collection);
}
}
interface ListADT<T>
{
// Removes and returns the first element from this list
public T removeFirst ();
// Removes and returns the specified element from this list
public T remove (T element);
// Returns a reference to the first element on this list
public T first ();
// Returns a reference to the last element on this list
public T last ();
// Returns true if this list contains the specified target element
public boolean contains (T target);
// Returns true if this list contains no elements
public boolean isEmpty();
// Returns the number of elements in this list
public int size();
// Returns an iterator for the elements in this list
public Iterator<T> iterator();
// Returns a string representation of this list
public String toString();
}
//************************************************************
// LinearNode.java
//
// Represents a node in a linked list.
//************************************************************
// YOU MUST PUT IN MORE SETTERS and GETTERS
class LinearNode<T>
{
public LinearNode<T> next;
private T element;
//---------------------------------------------------------
// Creates an empty node.
//---------------------------------------------------------
public LinearNode()
{
next = null;
element = null;
}
//---------------------------------------------------------
// Creates a node storing the specified element.
//---------------------------------------------------------
public LinearNode (T elem)
{
element = elem;
}
//---------------------------------------------------------
// Creates a node storing the specified element and link
//---------------------------------------------------------
public LinearNode (T elem, LinearNode<T> next)
{
element = elem;
this.next = next;
}
// put in setter and getters for next and element
//---------------------------------------------------------
// Returns the element stored in this node.
//---------------------------------------------------------
public T getElement()
{
return element;
}
//---------------------------------------------------------
// Set the element stored in this node.
//---------------------------------------------------------
public void setElement (T data)
{
element = data;
}
//---------------------------------------------------------
// Returns the next node.
//---------------------------------------------------------
public LinearNode<T> next()
{
return next;
}
//---------------------------------------------------------
// Sets the next node.
//---------------------------------------------------------
public void next (LinearNode<T> node)
{
next = node;
}
}
Here is the tester class:
public class ProjectTest10
{
public static void main(String args[])
{
String B = "B";
String E = "E";
String J = "J";
LinkedList10Handout list = new LinkedList10Handout();
// Code a linked list as pictured in the project specification which contains String B, E and J and perform the following operations.
// After each operation print out the list:
// do the appropriate System.out printlns for each operation
// 1. insert B into the list
LinearNode NodeB = new LinearNode (B);
list.InsertFirst(NodeB.getElement());
System.out.println("This is a list with B " + list);
System.out.println();
}}
There is more to tester class but doing just this stops it. The problem is at insertFirst, I believe since when I delete that line it prints out the line without the node obviously.
in your LinkedList10Handout, check your toString() function..
I think you want something like:
while (iter.hasNext())
{
result += iter.next() + "\n";
}
but, your iterator() function also has a problem..
you need to define your iterator like:
new LinkedIterator<T>(beforeHead, count);
instead of:
new LinkedIterator<T>(head, count);
to do this, you'll need to modify your code a bit.. good luck =)
UPDATE: just make an additional root node that will always exist (even though the list is empty) as the start point of the iterator..
ADDITION:
okay, here's an example:
import java.util.*;
import java.util.Iterator;
public class LinkedList10Handout<T> implements ListADT<T> {
protected int count;
protected LinearNode<T> rootNode;
protected LinearNode<T> head, tail, current, previous;
//===========================================================
// Creates an empty list.
//===========================================================
public LinkedList10Handout() {
rootNode = new LinearNode();
count = 0;
head = tail = null;
current = null;
} // constructor List
/**
* ************************************************************
* // Precondition: head is the head reference of a linked list. // The list
* might be empty or it might be non-empty. // PostCondition: One node has
* been added to the list.
//*************************************************************
*/
public void InsertFirst(T addData)//*********************************
{
LinearNode<T> newnode = new LinearNode<T>(addData, null);
if (isEmpty()) {
head = newnode;
rootNode.next = head;
tail = newnode;
} else {
newnode.next = head;
head = newnode;
}
if (current == head.next) {
previous = head;
}
count++;
// LIST REQUIREMENTS:
// if the list was initially empty, put tail on the list
//if current was initially at the first node, we must now put previous behind it
}
/**
* ************************************************************
* // this method calls insertAfter method after it finds the node it wants
* to insert a node after
/*************************************************************
*/
public boolean Insert(T target, T addData)//*************************
{
LinearNode<T> find = find(target);
boolean found = false;
if (find != null) {
found = true;
insertAfter(addData);
}
// calls find
// if target is found
//the method calls insertafter(addData) WHICH DOES THE ACTUAL INSERT
return found; // this is just here to allow it to compile
}
/**
* ***************************************************************
* // inserts a node at the end of the tail // CHECKS IF THE LIST IS EMPTY
* FIRST AND CALLS INSERTFIRST // ELSE INSERTS ON THE END OF THE LIST
/*****************************************************************
*/
public void insertTail(T target)//******************
{
if (isEmpty()) {
InsertFirst(target);
} else {
LinearNode<T> newnode = new LinearNode<T>(target, null);
tail.next = newnode;
tail = newnode;
}
count++;
// INSERT NODE ON THE TAIL
}
//===========================================================
// Precondition: The List is not empty
// Removes the first element in the list and returns a reference
// to it. Throws an EmptyListException if the list is empty.
//===========================================================
public T removeFirst() throws EmptyCollectionException //*************************
{
LinearNode<T> removed = head;
if (isEmpty()) {
throw new EmptyCollectionException("List");
} else {
head = head.next;
}
// delete the first node
// return the data;
count--;
return removed.getElement(); // this is to get it to compile - change it
} // method removeFirst
/**
* ************************************************************
* Inserts node with newData after the node current points to. The current
* node is the same AFTER THE NODE IS INSERTED Should not be used with an
* empty list. Should not be used when the current node IS NULL.
* /*******Before insertAfter is called current must be pointing to A node
* on the list
*************************************************************
*/
public void insertAfter(T newData)//*****************
{
LinearNode<T> newnode = new LinearNode<T>(newData, current.next);
current.next = newnode;
if (current == tail) {
tail.next = newnode;
}
count++;
}// close method
/**
* *******************************************************
* Finds the first node containing the target data, and returns a reference
* to that node. If key is not in the list, null is returned.
********************************************************
*/
public LinearNode<T> find(T target) // WE DID THIS IN CLASS
{
if (!isEmpty()) {
for (current = head; current.getElement() != target; current = current.next) // set up a for loop with current initialed to point to what head is pointing to.
{
previous = previous.next;
return current;
}
// inside the loop compare the element current is presently pointing to, to target
// if they are equal return current.element
// advance previous so that it follows current
}
return null;
} // close method
//===========================================================
// Precondition: Throws an EmptyListException if the list is empty.
// Throws a NoSuchElementException if the specified element is not found on the list.
// PostCondition:Removes the first instance of the specified element from the
// list if it is found in the list and returns a reference to it.
// SEVERAL SITUATIONS MUST BE HANDLED AS LISTED BELOW
//===========================================================
public T remove(T target) throws EmptyCollectionException, ElementNotFoundException //**************
{
if (isEmpty()) {
throw new EmptyCollectionException("List");
}
LinearNode<T> find = find(target);
if (find == null) {
throw new ElementNotFoundException("List");
}
LinearNode<T> removed = new LinearNode<T>(target, null);
// MAKE SURE TARGET IS ON THE LIST
// conditions you have to address:
//(1) if there is only one node on the list
if (size() == 1) {
head = tail = null;
} else if (find == head) {
removeFirst();
} else if (find == tail) {
removeLast();
} else {
previous.next = current.next;
current = current.next;
}
//(2) if (current points to head node and there is more than one node on the list
// (3) else if current equals tail - we are at the last node - HINT - USE PREVIOUS
//(4)IF NONE OF THE ABOVE IS TRUE we are somewhere in the middle of the list
// where current is pointing to node to be deleted
// and previous is right behind it - delete THAT node
count--;
// return the removed element
return removed.getElement();// this is just to get it to compile
} // method remove
//===========================================================
// Removes the last element in the list and returns a reference
// to it. Throws an EmptyListException if the list is empty.
// CALLS FIND TO LOCATE CURRENT ON THE TAIL NODE
// DETERMINES FIRST IF THE THERE IS ONLY ONE NODE AND THEN DELETES THAT
//===========================================================
public T removeLast() throws EmptyCollectionException //*******************************
{
// remove last node
if (isEmpty()) {
throw new EmptyCollectionException("List");
}
find(tail.getElement());
previous.next = current.next;
current = current.next;
count--;
return current.getElement();// was result
} // method removeLast
//===========================================================
// Finds the first instance of the specified element from the
// list if it is found in the list and returns true.
// Returns false otherwise. Calls the find method to find target
//===========================================================
public boolean contains(T targetElement) throws EmptyCollectionException //****************
{
if (isEmpty()) {
throw new EmptyCollectionException("List");
}
boolean found = false;
LinearNode<T> find = find(targetElement);
if (find != null) {
found = true;
}
return found;
} // method contains
//===========================================================
// Returns true if the list is empty and false otherwise
//===========================================================
public boolean isEmpty() {
return (count == 0);
} // method isEmpty
//===========================================================
// Returns the number of elements in the list.
//===========================================================
public int size() //*******************
{
// put in code
return count; // CHANGE THIS< IT IS TO GET IT TO COMPILE
} // method size
//===========================================================
// Returns ...
//===========================================================
public Iterator<T> iterator() {
return new LinkedIterator<T>(rootNode, count);
} // method elements
//===========================================================
// Returns a string representation of the list.
//===========================================================
public String toString() //*******************************
{
String result = "";
Iterator<T> iter = iterator();
while (iter.hasNext()) {
result += iter.next().toString() + "\n";
// traverse the list and accumulate the elements in result as you did in DatingService with hobbies
}
return result;
} // method toString
//===========================================================
// Returns the first element of the list.
//===========================================================
public T first() //***************************
{
return head.getElement(); // this is to get it to compile - change it
} // method firstElement
//===========================================================
// Returns the last element of the list.
//===========================================================
public T last()//********************
{
// put in code
return tail.getElement(); // this is to get it to compile - change it
} // method lastElement
} // class LinkedList
class EmptyCollectionException extends RuntimeException {
//-----------------------------------------------------------------
// Sets up this exception with an appropriate message.
//-----------------------------------------------------------------
public EmptyCollectionException(String collection) {
super("The " + collection + " is empty.");
}
}
class LinkedIterator<T> implements Iterator {
private int count; // the number of elements in the collection
private LinearNode<T> current; // the current position
//-------------------------------------------------------------
// Sets up this iterator using the specified items.
//-------------------------------------------------------------
public LinkedIterator(LinearNode<T> collection, int size) {
current = collection;
count = size;
}
//-------------------------------------------------------------
// Returns true if this iterator has at least one more element
// to deliver in the iteraion.
//-------------------------------------------------------------
public boolean hasNext() {
return (current.next != null);
}
//-------------------------------------------------------------
// Returns the next element in the iteration. If there are no
// more elements in this itertion, a NoSuchElementException is
// thrown.
//-------------------------------------------------------------
public T next() //*********************************************
{
if (!hasNext()) {
throw new NoSuchElementException();
}
current = current.next;
// put in code
return current.getElement(); // this is to get it to compile - change it
}
//-------------------------------------------------------------
// The remove operation is not supported.
//-------------------------------------------------------------
public void remove() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
}
class ElementNotFoundException extends RuntimeException {
//-----------------------------------------------------------------
// Sets up this exception with an appropriate message.
//-----------------------------------------------------------------
public ElementNotFoundException(String collection) {
super("The target element is not in this " + collection);
}
}
interface ListADT<T> {
// Removes and returns the first element from this list
public T removeFirst();
// Removes and returns the specified element from this list
public T remove(T element);
// Returns a reference to the first element on this list
public T first();
// Returns a reference to the last element on this list
public T last();
// Returns true if this list contains the specified target element
public boolean contains(T target);
// Returns true if this list contains no elements
public boolean isEmpty();
// Returns the number of elements in this list
public int size();
// Returns an iterator for the elements in this list
public Iterator<T> iterator();
// Returns a string representation of this list
public String toString();
}
//************************************************************
// LinearNode.java
//
// Represents a node in a linked list.
//************************************************************
// YOU MUST PUT IN MORE SETTERS and GETTERS
class LinearNode<T> {
public LinearNode<T> next;
private T element;
//---------------------------------------------------------
// Creates an empty node.
//---------------------------------------------------------
public LinearNode() {
next = null;
element = null;
}
//---------------------------------------------------------
// Creates a node storing the specified element.
//---------------------------------------------------------
public LinearNode(T elem) {
element = elem;
}
//---------------------------------------------------------
// Creates a node storing the specified element and link
//---------------------------------------------------------
public LinearNode(T elem, LinearNode<T> next) {
element = elem;
this.next = next;
}
// put in setter and getters for next and element
//---------------------------------------------------------
// Returns the element stored in this node.
//---------------------------------------------------------
public T getElement() {
return element;
}
//---------------------------------------------------------
// Set the element stored in this node.
//---------------------------------------------------------
public void setElement(T data) {
element = data;
}
//---------------------------------------------------------
// Returns the next node.
//---------------------------------------------------------
public LinearNode<T> next() {
return next;
}
//---------------------------------------------------------
// Sets the next node.
//---------------------------------------------------------
public void next(LinearNode<T> node) {
next = node;
}
}
list.InsertFirst(NodeB.getElement());
Are you trying to insert the Node itself or the Node.getElement?
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.
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);
Been working on an implementation for Linked list Queue and Stack classes for an assignment. I've tested both of these and they appear to be working, but I'm worried that some parts of the implementation can be done better than I currently have set up, and I don't wanna get points taken off for inefficient code.
Here's the classes I have set up:
Node
public class Node {
Node next;
Car car;
/**
* A node object, used for the creation of LinkedLists.
* #param car
*/
public Node(Car car)
{
next = null;
this.car = car;
}
}
Stack
public class LStack {
Node head = null;
/**
* Adds a car object to the list
* #param car = the car object to be added
*/
public void push(Car car)
{
Node oldHead = head;
head = new Node(car);
head.next = oldHead;
}
/**
* Removes the top car from the list
* #return the car at the top of the list
*/
public Car pop()
{
Car headCar = head.car;
head = head.next;
return headCar;
}
/**
* Checks if the list is empty
* #return whether or not the list is empty
*/
public boolean isEmpty()
{
return (head == null);
}
/**
*
* #return the size of the list
*/
public int size()
{
Node nextNode = head;
int count = 0;
while (nextNode != null)
{
count++;
nextNode = nextNode.next;
}
return count;
}
/**
* Displays the list of car license plate information
*/
public void display()
{
Node nextNode = head;
while (nextNode != null)
{
System.out.print(nextNode.car.getLicense() + "|");
nextNode = nextNode.next;
}
System.out.println();
}
/**
*
*/
public void reverseStack()
{
// not implemented yet
}
}
Queue
public class LQueue {
Node head = null;
/**
* Adds a car object to the list
*
* #param car
* = the car object to be added
*/
public void insert(Car car) {
Node current = head;
if (current != null) {
while (current.next != null) {
current = current.next;
}
current.next = new Node(car);
}
else
{
head = new Node(car);
}
}
/**
* Removes the top car from the list
*
* #return the car at the top of the list
*/
public Car remove() {
Car headCar = head.car;
head = head.next;
return headCar;
}
/**
* Checks if the list is empty
*
* #return whether or not the list is empty
*/
public boolean isEmpty() {
return (head == null);
}
/**
*
* #return the size of the list
*/
public int size() {
Node nextNode = head;
int count = 0;
while (nextNode != null) {
count++;
nextNode = nextNode.next;
}
return count;
}
/**
* Displays the list of car license plate information
*/
public void display() {
Node nextNode = head;
while (nextNode != null) {
System.out.print(nextNode.car.getLicense() + "|");
nextNode = nextNode.next;
}
System.out.println();
}
/**
*
*/
public void reverseQueue() {
}
}
and the Car class isn't really important, it just stores license plate information in a string.
Mostly I'm worried about the ones I have set up with the While loops, I'm not sure if there's a more memory efficient way of implementing those. Is there a more standardized way of setting these up that I may have missed?
One thing that I would change is that I'd make LQueue keep references to both the head and the tail of the queue. This way you'd be able to insert() in constant time, without having to iterate over all existing elements.
Also, both size() methods can be made to run in constant time if you so wished: keep track of the current size in a member variable, increment on insert() and decrement on remove().
The only two things I can think of are:
Keep track of the number of elements in the list with an int that increments on add and decrements on remove. This would make the size() method instant. All you would have to do is return that int value.
For the queue, keep track of the tail with a Node reference much like you do the head. That way you don't have to iterate through the list to find the end of the list. The tail would just always be the last added Node. This would allow you to not have to iterate through the list every time you want to add something; instead you could just add it to the end of that tail.