0

Okay, so I am a intro programmer to java and we were assigned a project to create a functioning linked list. I am posting my DLinkedlist file to show how I created my linked list. Finally I will show the tester that is being used to make sure it is functioning properly. The exception is fine, that is what is wanted by the instructor. The problem is the "While has next" and "While has previous" outputs. Much thanks!

package project5;
import java.util.NoSuchElementException;
public class DLinkedList {
private Node first;
private Node last;
public DLinkedList() {
 first = null;
 last = null;
}
/**
 * Adds an element to the head of the list
 * @param data - the object to store at the head of the list
 */
public void addFirst(Object data){
 Node newNode = new Node();
 newNode.data = data; // No setter necessary
 if (first != null){
 newNode.next = first;
 }else{
 last = newNode;
 }
 first = newNode;
}
/**
 * Gets what is stored at the beginning of the list
 * @return - the data stored at the head of the list
 */
public Object getFirst(){
 /*
 This is the syntax for getting the "data attribute" of the object called "first"
 We can do this because "data" is piublic and thus we do not need to call a getter method
 */
 if (first == null){
 throw new NoSuchElementException();
 }
 return first.data;
}
/**
 * Removes the head of the list
 * @return - returns data that was stored in the same node removed
 */
public Object removeFirst(){
 if (first == null){
 throw new NoSuchElementException();
 }
 Object temp = first.data;
 first = first.next;
 return temp;
}
/**
 * Adds an element to the tail of the list
 * @param data - the object to store at the tail of the list
 */
public void addLast(Object data){
 Node newNode = new Node();
 newNode.data = data;
 if(first == null){
 addFirst(data);
 }else{
 if (last != null){
 newNode.previous = last;
 last.next = newNode;
 }
 last = newNode;
 }
}
/**
 * Gets what is stored at the end of the list
 * @return - the data stored at the tail of the list
 */
public Object getLast(){
 /*
 Ths s
 */
 if (last == null){
 throw new NoSuchElementException();
 }
 return last.data;
}
/**
 * Removes the last item in the list
 * @return
 */
public Object removeLast(){
 if (last == null){
 throw new NoSuchElementException();
 }
 Object temp = last.data;
 last = last.previous;
 return temp;
}
/**
 * Checks if the Linked List contains an object
 * @param other
 * @return
 */
public boolean contains(Object other){
 Node temp = first;
 while (temp.next != null){
 if(temp.data == other){
 return true;
 }else{
 temp = temp.next;
 }
 }
 return false;
}
/**
 * Note: We return ListIterator because it is a PUBLIC interface that can be used outside fo the LinkedList class,
 * whereas LinkedListIterator only exists inside LinkedList
 * @return
 */
public ListIterator listIterator(){
 return new LinkedListIterator();
}
class LinkedListIterator implements ListIterator{
 private DLinkedList.Node position;
 private DLinkedList.Node previous;
 private DLinkedList.Node next;
 private boolean isAfterNext;
 private boolean isAfterPrevious;
 public LinkedListIterator(){
 position = null;
 previous = null;
 next = null;
 isAfterNext = false;
 isAfterPrevious = false;
 }
 @Override
 public Object next() {
 if (!hasNext()){
 throw new NoSuchElementException();
 }
 // Updating previous to be at the current pos
 previous = position;
 // Iterator is at the beginning of the lsit
 if (position == null){
 position = first;
 }
 else{
 position = position.next;
 }
 isAfterNext = true;
 return position.data;
 }
 @Override
 public boolean hasNext() {
 if (position == null){
 // Beginning of the list
 return first != null;
 }
 else{
 return position.next != null;
 }
 }
 @Override
 public void add(Object data) {
 if (!isAfterNext){
 throw new IllegalStateException();
 }
 if (position == first){
 addFirst(data);
 }
 else{
 Node newNode = new Node();
 newNode.data = data;
 newNode.next = position.next;
 newNode.previous = position;
 position.next = newNode;
 position = newNode;
 }
 }
 @Override
 public Object remove() {
 if (!isAfterNext){
 throw new IllegalStateException();
 }
 Object temp;
 if (position == first){
 temp = removeFirst();
 }
 else{
 temp = position.data;
 previous.next = position.next;
 }
 position = previous;
 isAfterNext = false;
 return temp;
 }
 @Override
 public Object previous() {
 boolean hasBeenCalled = false;
 if (!hasPrevious()){
 throw new NoSuchElementException();
 }
 // Updating next to be at the current pos
 next = position;
 // Iterator is at the end of the list
 if (position == null){
 position = last;
 }
 else{
 position = position.previous;
 }
 isAfterPrevious = true;
 return position.next.data;
 }
 @Override
 public boolean hasPrevious() {
 if (position == null){
 // End of the list
 return first != null;
 }
 else{
 return position.previous != null;
 }
 }
 @Override
 public void set(Object element) {
 position.data = element;
 }
}
/*
Node is an inner class, which means access to it is restruced to members of its outer class, i.e. LinkedList
 */
class Node{
 /*
 These variables don't need setters or getters because they are public, and thus can be accessed/modified by any
 member of the outer class, i.e. LinkedList
 */
 public Object data;
 public Node next;
 public Node previous;
 }
}

Tester shown with expected vs actual output!

package project5;
import project5.DLinkedList;
import project5.ListIterator;
public class DLinkedListTester {
public static void main(String[] args) {
 DLinkedList ages = new DLinkedList();
 for(int i = 1; i <= 15; i++) {
 ages.addFirst(i);
 }
 for(int i = 16; i <= 30; i++) {
 ages.addLast(i);
 }
 System.out.println("Remove First Expected: 15");
 System.out.println("Output: "+ages.removeFirst() + "\n");
 System.out.println("Remove Last Expected: 30");
 System.out.println("Output: "+ages.removeLast() + "\n");
 System.out.println("Get First Expected: 14");
 System.out.println("Output: "+ages.getFirst() + "\n");
 System.out.println("Get Last Expected: 29");
 System.out.println("Output: "+ages.getLast() + "\n");
 System.out.println("Contains 10 Expected: true");
 System.out.println("Output: " + ages.contains(10) + "\n");
 System.out.println("Contains 100 Expected: false");
 System.out.println("Output: " + ages.contains("100") + "\n");
 ListIterator iter = ages.listIterator();
 System.out.print("While has next Expected: 14 13 12 11 10 9 8 7 6 5 4 3 2 1 16 17 18 19 20 21 22 23 24 25 26 27 28 29 \nOutput: ");
 while(iter.hasNext()) {
 System.out.print(iter.next() + " ");
 }
 System.out.println("\n");
 System.out.print("While has previous Expected: 29 28 27 26 25 24 23 22 21 20 19 18 17 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 \nOutput: ");
 while(iter.hasPrevious()) {
 System.out.print(iter.previous() + " ");
 }
 iter = ages.listIterator();
 iter.next(); //14 | 13 12 11 10 ...
 iter.next(); //14 13 | 12 11 10 ...
 iter.add("12.5"); //14 13 12.5 | 12 11 10 ...
 iter.next(); //14 13 12.5 12 | 11 10 ...
 System.out.println("\n\nRemove Expected: 12");
 System.out.println("Output: " + iter.remove() + "\n");
 iter.previous(); //14 13 | 12.5 11 10 ... 
 iter.previous(); //14 | 13 12.5 11 10 ...
 iter.remove(); //14 | 12.5 11 10 ...
 while(iter.hasNext()) {
 iter.next();
 }
 iter.previous();
 iter.set("100");
 System.out.print("\nWhile has next Expected: 14 12.5 11 10 9 8 7 6 5 4 3 2 1 16 17 18 19 20 21 22 23 24 25 26 27 28 100 \nOutput: ");
 iter = ages.listIterator();
 while(iter.hasNext()) {
 System.out.print(iter.next() + " ");
 }
 }
}

Console Output!

Remove First Expected: 15
Output: 15
Remove Last Expected: 30
Output: 30
Get First Expected: 14
Output: 14
Get Last Expected: 29
Output: 29
Contains 10 Expected: true
Output: true
Contains 100 Expected: false
Output: false
While has next Expected: 14 13 12 11 10 9 8 7 6 5 4 3 2 1 16 17 18 19 20 21 
22 23 24 25 26 27 28 29 
Output: 14 13 12 11 10 9 8 7 6 5 4 3 2 1 16 17 18 19 20 21 22 23 24 25 26 27 
28 29 30 
While has previous Expected: 29 28 27 26 25 24 23 22 21 20 19 18 17 16 1 2 3 
4 5 6 7 8 9 10 11 12 13 14 
Output: 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 
Remove Expected: 12
Output: 12
Exception in thread "main" java.util.NoSuchElementException
 at project5.DLinkedList$LinkedListIterator.previous(DLinkedList.java:224)
 at project5.DLinkedListTester.main(DLinkedListTester.java:59)
4
  • Please provide a MINIMAL, complete, and verifiable example. You've dumped a lot of code here and most of it is unnecessary to what I assume your problem to be (issue with iterators). Commented Dec 11, 2018 at 6:18
  • I'm sorry, I am not sure what to guess what the issue would be. I wanted to provide details. Commented Dec 11, 2018 at 6:22
  • If you can isolate the parts of the code that actually matter for your problem, that will make your question much easier to read. I'd start by removing the interface from your question since you've (I assume) implemented it in your class and since it doesn't provide much information as far as your issue is concerned. Commented Dec 11, 2018 at 6:23
  • @Cameron Wilson Your question title & content are totally mismatched. Please format your question concisely & properly. Don't make your question too verbose. Commented Dec 11, 2018 at 6:23

1 Answer 1

1

If you carefully look at your code and the way your linked list is populated, you would notice that (right after the population) the elements from 15 (first element) up to 1 are singly-linked while next elements from 16 up to 30 are doubly-linked (there's a double-link between 1 and 16 as well).

Regarding "while has next":
Whenever you remove the last element, you simply update last pointer to the previous element, but the last element still remains in the linked list, hence you get 30 at the end of value list. iterator's loop stops at values prev=29 and position=30

Regarding "while has previous":
Because the previous pointers are all null starting from element 1 and all way up to the first, you update position by position = position.previous; so it starts pointing at 29, then you output position.next which is 30, then traverse up one by one and naturally stop at position=1 then you output position.next which is 16 and stop, because the previous pointer of 1 does not point at 2

So,
1.You have to modify addFirst() in such a way that the previous pointer of a first node would point to the new one:

public void addFirst(Object data){
 Node newNode = new Node();
 newNode.data = data; // No setter necessary
 if (first != null){
 newNode.next = first; 
 first.previous = newNode; //<---added
 }else{
 last = newNode;
 }
 first = newNode;
}

2.You have to modify removeLast() in such a way that the removed element no longer stays in the list:

public Object removeLast(){
 if (last == null){
 throw new NoSuchElementException();
 }
 Node temp = last;
 last = last.previous;
 last.next = null;
 temp.previous = null;
 return temp.data;
}
answered Dec 11, 2018 at 6:30
Sign up to request clarification or add additional context in comments.

2 Comments

@CameronWilson see the answer above. modify those two methods and run your program again
AWESOME ! that makes sense I see now ! I have one more problem then, can someone explain why I am not outputting the last has next line of code ?? It has the elements 14 12.5 11 10 ... etc. It is towards the bottom of my post.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.