Initializing linked list - java

When I run my driver class, my list wont initialize. This is what should be necessary to start the list.
public class SortedListReferenceBased implements ListInterface {
private Node head;
private int numItems; // number of items in list
public SortedListReferenceBased()
// creates an empty list
{
head = new Node(null);
numItems = 0;
} // end default constructor
public boolean isEmpty()
// Determines whether a list is empty
{
return true;
} // end isEmpty
public int size()
// Returns the number of items that are in a list
{
return numItems;
} // end size
public void removeAll()
// Removes all the items in the list
{
head = null;
numItems = 0;
} // end removeAll
public Object get(int index) throws ListIndexOutOfBoundsException
// Retrieves the item at position index of a sorted list, if 0 <= index <
// size().
// The list is left unchanged by this operation.
// Throws an exception when index is out of range.
{
if (index < 0 || index >= numItems) {
throw new ListIndexOutOfBoundsException(index + " is an invalid index");
}
return new Object();
}
public void add(Object item) throws ListException
// Inserts item into its proper position in a sorted list
// Throws an exception if the item connot be placed on the list
{
try {
Node newNode = new Node(item);
if (head != null) {
int i = locateIndexToAdd(item);
if (i >= -1 && i <= numItems) {
add(i, item);
}
} else {
head = new Node(newNode);
Node curr = head.getNext();
curr.setNext(null);
numItems++;
}
} catch (Exception e) {
throw new ListException("Add to List failed: " + e.toString());
}
}
}

The problem seems to be this part of your add method:
head = new Node(newNode);
Node curr = head.getNext();
curr.setNext(null);
numItems++;
I assume the next variable in Node gets initialized with null so head.getNext() returns null for curr. When you then call curr.setNext(null) you get a NullPointerException. Since this add the first entry in your list you want to set the next for your first element to null.
Also you do not have to wrap newNode in a Node since its already a node.
head = newNode;
head.setNext(null);
numItems++;
But since you initialize it with null anyway you don't have to do anything.
head = newNode;
numItems++;

Related

Is there a way to make this main class reverse method more efficient? Possibly requiring only one loop?

//code inside a reverse method that has the list object
//passed as a parameter from main method
int size = list.size();
//create temporary list object to hold contents of original list in reverse
MyListReferenceBased temp = new MyListReferenceBased();
for (int i = 0; i < size; i++)
{
//list add method requires which index your adding to, and object
//get method just gets the object at the specified index in list
temp.add(i, list.get((size-i)-1));
//remove method just removes object at specified index
list.remove((size-i)-1);
}
//now that original list is empty, put the contents back in
for (int i = 0; i<size; i++)
{
list.add(i, temp.get(i));
}
temp.removeAll();
//end result: original list is now reversed
//and temporary array is all empty
System.out.println("List has been Reversed.");
//is there a way to get rid of the 2nd loop?? Not possible to just assign?
So this code is in a reverse method inside the main class for reversing a linked list. Well reversing a list in general, since the user of the main class isn't suppose to interact with the linked list directly but just has access to the linked list methods (Didn't do reverse inside linked list class on purpose). Rather in the main/driver class, I'm reversing the list by first creating a second/temporary linked list, adding over each of the elements from the original list (in reverse) into the new list. And then since I need the contents to be in the original list and only need the temporary list during the duration of this method, I copy over the elements back into the old list.
The list object is instantiated as local in the main method of this main class and then calls the reverse method, passing the list object as a parameter. Instead of having the second loop, isn't there a way to just assign the temporary list object to the original list? I was able to do this when I the underlying implementation of the list was using arrays, but not sure how to it with linked lists.
Or any other efficient work around? Remember this is specifically for reversing a linked list without directly being inside the linked list class.
///FULL CODE IF NEEDED://
public class MyListReferenceBased implements ListInterface {
private Node head;
public MyListReferenceBased()
{
head = null;
}
public boolean isEmpty() {
return head == null;
}
// dont use find()
public int size() {
int size = 0;
Node curr = head;
while (curr != null) {
curr = curr.getNext();
size++;
}
return size;
}
private Node find (int index)
{
Node curr = head;
for (int skip = 0; skip < index; skip++)
{
curr = curr.getNext();
} // end for
return curr;
} // end find
public void add(int index, Object item)
throws ListIndexOutOfBoundsException
{
if (index >= 0 && index < size() + 1)
{
if (index == 0)
{
// insert the new node containing item at
// beginning of list
Node newNode = new Node(item, head);
head = newNode;
}
else
{
Node prev = find(index-1);
Node newNode = new Node(item, prev.getNext());
prev.setNext(newNode);
} // end if
}
else
{
throw new ListIndexOutOfBoundsException(
"List index out of bounds exception on add");
} // end if
} // end add
public Object get(int index)
throws ListIndexOutOfBoundsException
{
if (index >= 0 && index < size())
{
Node curr = find(index);
Object dataItem = curr.getItem();
return dataItem;
}
else
{
throw new ListIndexOutOfBoundsException(
"List index out of bounds exception on get");
} // end if
} // end get
public void remove(int index)
throws ListIndexOutOfBoundsException
{
if (index >= 0 && index < size())
{
if (index == 0)
{
head = head.getNext();
}
else
{
Node prev = find(index-1);
Node curr = prev.getNext();
prev.setNext(curr.getNext());
} // end if
}
else
{
throw new ListIndexOutOfBoundsException(
"List index out of bounds exception on remove");
} // end if
} // end remove
public void removeAll() {
head = null;
}
public String toString() {
String x = "";
Node curr = head;
int size = size();
for (int i = 0; i < size ; i++) {
// curr.getNext();
x += curr.getItem() + " ";
curr = curr.getNext();
}
return x;
}
}
///NODE CLASS///
public class Node
{
private Object item;
private Node next;
public Node(Object newItem)
{
item = newItem;
next = null;
} // end constructor
public Node(Object newItem, Node nextNode)
{
item = newItem;
next = nextNode;
} // end constructor
public void setItem(Object newItem)
{
item = newItem;
} // end setItem
public Object getItem()
{
return item;
} // end getItem
public void setNext(Node nextNode)
{
next = nextNode;
} // end setNext
public Node getNext()
{
return next;
} // end getNext
} // end class Node
Here's recursive implementation.
Base case: the tail becomes a new head, i.e. index argument is equal to size (or greater, which would be the case if the given list is empty).
Recursive case:
obtain the next that should be swapped using get(), indices of nodes to swap start from size - 2 (because it would be redundant to remove and immediately add the tail-node) and move towards 0;
invoke remove() to delete the current node;
add the new node to the tail using add();
invoke reverse() recursively passing index incremented by 1.
That's how it might look like:
public static void reverse(MyListReferenceBased list) {
reverse(list, 1, list.size()); // initial index is 1 (if the first call would with the index 0 the list would not change its state after the first execution of `reverse()` because we would be dialing with tail node which would stay on the same place)
}
public static void reverse(MyListReferenceBased list, int index, int size) {
if (index >= size) return; // Base case - tail becomes a head (we don't need to touch the tail)
// recursive case
Object valueToRemove = list.get(size - 1 - index);
list.remove(size - 1 - index);
list.add(size - 1, valueToRemove);
reverse(list, index + 1, size);
}
A link to Online Demo
Well, prepend one node after the other to an initially empty list:
/** Prepend the elements of <code>suffix</code> to <code>suffix</code>,
* in reverse order.
* #param emptied gets, well, <i>emptied</i>
* #param suffix
* #return <code>suffix</code> with the elements of
* <code>emptied</code> prepended in reverse order */
static ListInterface
prependReversed(ListInterface emptied, ListInterface suffix) {
while (!emptied.isEmpty()) {
suffix.add(0, emptied.get(0));
emptied.remove(0);
}
return suffix;
}
/** Reverse a List.
* #param emptied the list to reverse; will be empty on return
* #return a <code>MyListReferenceBased</code> containing
the elements of <code>emptied</code> in reverse order */
static MyListReferenceBased reverse_(ListInterface emptied) {
return prependReversed(emptied, new MyListReferenceBased());
}
/** Reverse a MyListReferenceBased in place (sort of).
* Argument is emptied temporarily and restored on return.
* #param toReverse the list to reverse; will be restored on return
* #return a <code>MyListReferenceBased</code> with
the elements of <code>toReverse</code> in reverse order */
public static MyListReferenceBased reverse(ListInterface toReverse) {
MyListReferenceBased
reversed = new MyListReferenceBased(),
saved = new MyListReferenceBased();
// an O(1) toReverse.clone() or saved.addAll(toReverse) would come in handy
while (!toReverse.isEmpty()) {
Object item = toReverse.get(0);
reversed.add(0, item);
saved.add(0, item);
toReverse.remove(0);
}
prependReversed(saved, toReverse);
return reversed;
}
True non-mutating variant (in O(1) timeā€¦) left as an exercise.

get LinkedList instance in java

I am new in java. I have been trying to do some tests while teaching myself the language. Now I am on a linked list implementation. I chucked the code from test samples online. There are two files, LinkedList and LinkedListIterator. I am alright understanding the implementation. However, I would like to add to methods to the LinkedList class. One method (getString()) will be used to display a concatenation of all the string variables in the linkedlist. The second method getSize() will be used to display the size of the list. I have trouble getting the current instance of the linkedlist so I can iterate and get the strings and size. Can someone please assist? Help will be really appreciated.
The two files are as below:
import java.util.NoSuchElementException;
public class LinkedList
{
//nested class to represent a node
private class Node
{
public Object data;
public Node next;
}
//only instance variable that points to the first node.
private Node first;
// Constructs an empty linked list.
public LinkedList()
{
first = null;
}
// Returns the first element in the linked list.
public Object getFirst()
{
if (first == null)
{
NoSuchElementException ex
= new NoSuchElementException();
throw ex;
}
else
return first.data;
}
// Removes the first element in the linked list.
public Object removeFirst()
{
if (first == null)
{
NoSuchElementException ex = new NoSuchElementException();
throw ex;
}
else
{
Object element = first.data;
first = first.next; //change the reference since it's removed.
return element;
}
}
// Adds an element to the front of the linked list.
public void addFirst(Object element)
{
//create a new node
Node newNode = new Node();
newNode.data = element;
newNode.next = first;
//change the first reference to the new node.
first = newNode;
}
// Returns an iterator for iterating through this list.
public ListIterator listIterator()
{
return new LinkedListIterator();
}
public String toString(){
}
public int getSize(){
return this.size();
}
//nested class to define its iterator
private class LinkedListIterator implements ListIterator
{
private Node position; //current position
private Node previous; //it is used for remove() method
// Constructs an iterator that points to the front
// of the linked list.
public LinkedListIterator()
{
position = null;
previous = null;
}
// Tests if there is an element after the iterator position.
public boolean hasNext()
{
if (position == null) //not traversed yet
{
if (first != null)
return true;
else
return false;
}
else
{
if (position.next != null)
return true;
else
return false;
}
}
// Moves the iterator past the next element, and returns
// the traversed element's data.
public Object next()
{
if (!hasNext())
{
NoSuchElementException ex = new NoSuchElementException();
throw ex;
}
else
{
previous = position; // Remember for remove
if (position == null)
position = first;
else
position = position.next;
return position.data;
}
}
// Adds an element before the iterator position
// and moves the iterator past the inserted element.
public void add(Object element)
{
if (position == null) //never traversed yet
{
addFirst(element);
position = first;
}
else
{
//making a new node to add
Node newNode = new Node();
newNode.data = element;
newNode.next = position.next;
//change the link to insert the new node
position.next = newNode;
//move the position forward to the new node
position = newNode;
}
//this means that we cannot call remove() right after add()
previous = position;
}
// Removes the last traversed element. This method may
// only be called after a call to the next() method.
public void remove()
{
if (previous == position) //not after next() is called
{
IllegalStateException ex = new IllegalStateException();
throw ex;
}
else
{
if (position == first)
{
removeFirst();
}
else
{
previous.next = position.next; //removing
}
//stepping back
//this also means that remove() cannot be called twice in a row.
position = previous;
}
}
// Sets the last traversed element to a different value.
public void set(Object element)
{
if (position == null)
{
NoSuchElementException ex = new NoSuchElementException();
throw ex;
}
else
position.data = element;
}
} //end of LinkedListIterator class
}
LinkedListIterator class:
public interface ListIterator
{
//Move Moves the iterator past the next element.
Object next();
// Tests if there is an element after the iterator position.
boolean hasNext();
// Adds an element before the iterator position
// and moves the iterator past the inserted element.
void add(Object element);
// Removes the last traversed element. This method may
// only be called after a call to the next() method.
void remove();
// Sets the last traversed element to a different value.
void set(Object element);
}
Error when I try the implmentation of getSize():
Exception in thread "main" java.lang.StackOverflowError
at assignment10.LinkedList.size(LinkedList.java:84)
at assignment10.LinkedList.size(LinkedList.java:84)
at assignment10.LinkedList.size(LinkedList.java:84)
at assignment10.LinkedList.size(LinkedList.java:84)
The getSize() could be
public int getSize(){
int size = 0;
ListIterator iterator = listIterator();
while(iterator.hasNext()) {
iterator.next();
size++;
}
return size;
}
But it is not efficient to iterate over list each time to knowe it's size. The better solution is to store size as class variable and increase or decrease in methods modifying list.
The idea of toString() method is the same, iterate over the list and append each item to the result string
public String toString(){
StringBuilder sb = new StringBuilder();
ListIterator iterator = listIterator();
while(iterator.hasNext()) {
sb.append(String.valueOf(iterator.next())).append(",");
}
return sb.toString;
}

Custom LinkedList: remove method does not work as expected

I'm implementing the remove() method of a custom LinkedList class, but it does not remove any items from the list, and I can't figure out why.
Here's how I do it:
public void remove(int position) {
if (position < 0 || position >= size) {
throw new IndexOutOfBoundsException(
"position should be beween 0 and size - 1");
}
Cell current = top;
for (int i = 0; i < position; i++) {
current = current.next;
}
current = current.next.next;
size--;
}
This method tries to remove an item between 2 nodes (removing first node and last node cases are ignored).
This is the test case I am executing, and after trying to remove the element with index 2, it still prints the hole list:
CustomList<String> list = new CustomList<String>();
list.add("Hello");
list.add("morena");
list.add("What");
list.add("Miranda");
list.add("Aston");
list.remove(2);
list.printAll();
For completion, here's the full implementation of the list:
public class CustomList<T> {
private class Cell {
T data;
Cell next;
public Cell(T data) {
this.data = data;
}
}
private Cell top;
private int size;
public void add(T data) {
addAtEndInOn(data);
size++;
}
/**
* adds an item at the end of the list in O(n) by iterating the whole list
* before adding the node
*/
private void addAtEndInOn(T data) {
if (top == null) {
top = new Cell(data);
} else {
Cell current = top;
while (current.next != null) {
current = current.next;
}
current.next = new Cell(data);
}
}
public void remove(int position) {
if (position < 0 || position >= size) {
throw new IllegalArgumentException(
"position should be a positive number");
}
Cell current = top;
for (int i = 0; i < position; i++) {
current = current.next;
}
current = current.next.next;
size--;
}
public void printAll() {
Cell current = top;
while (current != null) {
System.out.println(current.data);
current = current.next;
}
}
}
current = current.next.next changes nothing in your list.
In order to remove an element, you need to write :
current.next = current.next.next;
This would remove the element that is next to the current element. It that's not the element you meant to remove, you should change the for loop so that it stops when current is the element before the one you want to remove.
Make sure to test that current.next is not null, to avoid NullPointerException.
You have to break the link, not just change the position of current. The link is represented by current.next

List Manipulation with references

So for my assignment we are to implement some referenced based list manipulation methods in a class and then add to a list and demonstrate the methods using a driver file.
I have provided the entire program for download which includes a pdf that explains the assignment. Our professor uploaded a completed driver file and mine is exactly the same as his but I am getting some run-time errors, first is when calling add() for the third time I get a NullPointerException, if I comment out the rest of the add() calls, size() will not return the same size as getSize() and getSizeRecursive().
Please Help me. Link to download: https://www.dropbox.com/s/qe771q3156h9nwx/ListReferenceBased.rar
// ****************************************************
// Reference-based implementation of ADT list.
// ****************************************************
public class ListReferenceBased implements ListInterface {
// reference to linked list of items
private Node head;
private int numItems; // number of items in list
public ListReferenceBased() {
numItems = 0;
head = null;
} // end default constructor
public boolean isEmpty() {
return numItems == 0;
} // end isEmpty
public int size() {
return numItems;
} // end size
private Node find(int index) {
// --------------------------------------------------
// Locates a specified node in a linked list.
// Precondition: index is the array index of the desired node.
// Assumes that 0 <= index < numItems
// Postcondition: Returns a reference to the desired node.
// --------------------------------------------------
Node curr = head;
for (int skip = 0; skip < index; skip++) {
curr = curr.getNext();
} // end for
return curr;
} // end find
public Object get(int index)
throws ListIndexOutOfBoundsException {
if (index >= 0 && index < numItems) {
// get reference to node, then data in node
Node curr = find(index);
Object dataItem = curr.getItem();
return dataItem;
}
else {
throw new ListIndexOutOfBoundsException(
"List index out of bounds on get");
} // end if
} // end get
public void add(int index, Object item)
throws ListIndexOutOfBoundsException {
if (index >= 0 && index <= numItems) {
if (index == 0) {
// insert the new node containing item at
// beginning of list
Node newNode = new Node(item, head);
head = newNode;
}
else {
Node prev = find(index-1);
// insert the new node containing item after
// the node that prev references
Node newNode = new Node(item, prev.getNext());
prev.setNext(newNode);
} // end if
numItems++;
}
else {
throw new ListIndexOutOfBoundsException(
"List index out of bounds on add");
} // end if
} // end add
public void remove(int index)
throws ListIndexOutOfBoundsException {
if (index >= 0 && index < numItems) {
if (index == 0) {
// delete the first node from the list
head = head.getNext();
}
else {
Node prev = find(index-1);
// delete the node after the node that prev
// references, save reference to node
Node curr = prev.getNext();
prev.setNext(curr.getNext());
} // end if
numItems--;
} // end if
else {
throw new ListIndexOutOfBoundsException(
"List index out of bounds on remove");
} // end if
} // end remove
public void removeAll() {
// setting head to null causes list to be
// unreachable and thus marked for garbage
// collection
head = null;
numItems = 0;
} // end removeAll
// TO IMPLEMENT
public String toString(){
Node curr = head;
String str = new String("");
while(curr != null){
str += curr.getItem() + ", ";
curr = curr.getNext();
}
return str;
}
// TO IMPLEMENT
public void reverse(){
Node prev = null;
Node curr = head;
while(curr != null){
Node next = curr.getNext();
curr.setNext(prev);
prev = curr;
curr = next;
}
head = prev;
}
// TO IMPLEMENT
// This is a helper method, so try to define your own method
// that this helper will call.
public void reverseRecursive(){
Node prev = null;
Node curr = head;
reverseRecursiveHelper(prev, curr);
head = prev;
}
public Object reverseRecursiveHelper(Node prev, Node curr){
if(curr == null)
return null;
else {
Node next = curr.getNext();
curr.setNext(prev);
prev = curr;
curr = next;
return reverseRecursiveHelper(prev, curr);
}
}
// TO IMPLEMENT
public int getSize()
// --------------------------------------------------
// Returns the number of items in a linked list.
// Precondition: head points to the first element
// in a list of type node.
// Postcondition: The number of items in the list
// is returned.
// --------------------------------------------------
{
int count = 0;
Node curr = head;
while(curr != null){
curr = curr.getNext();
count++;
}
return count;
}
// TO IMPLEMENT
public int getSize(Node cur)
// --------------------------------------------------
// Returns the number of items in a linked list.
// The initial call should have the beginning of the list
// as it's input argument, i.e. listCount(head);
// Precondition: cur points to a list of type node
// Postcondition: The number of items in the list
// is returned.
// --------------------------------------------------
{
if(cur != null)
return 1 + getSize(cur.getNext());
else //base case
return 0;
}
// TO IMPLEMENT
public int getSizeRecursive()
{
return getSize(head);
}
// TO IMPLEMENT
public Node findMToLast(int m){
Node current = head;
if(current == null)
return null;
for(int i = 0; i < m; i++)
if(current.getNext() != null)
current = current.getNext();
else
return null;
Node mBehind = head;
while (current.getNext() != null){
current = current.getNext();
mBehind = mBehind.getNext();
}
return mBehind;
}
} // end ListReferenceBased
Driver:
// ********************************************************
// Test Reference-based implementation of the ADT list.
// *********************************************************
public class TestListReferenceBased {
static public void main(String[] args)
{
ListReferenceBased aList = new ListReferenceBased();
aList.add(0, new Integer(1));
aList.add(1, new Integer(2));
aList.add(2, new Integer(3));
aList.add(3, new Integer(4));
aList.add(4, new Integer(5));
aList.add(5, new Integer(6));
System.out.println("size() and get(i): ");
for (int i = 0; i < aList.size(); i++)
System.out.println(aList.get(i) + " ");
System.out.println();
System.out.println("Size with size() = " + aList.size());
System.out.println("Size with getSize() = " + aList.getSize());
System.out.println("Size with getSizeRecursive() = " + aList.getSizeRecursive());
System.out.println("Initial List = " + aList);
aList.reverse(); // iterative version
System.out.println("Reverse with reverse() = " + aList);
System.out.println("====================================");
aList.reverseRecursive(); // recursive version
System.out.println("Reverse with reverseRecursive() = " + aList);
int offset = 3;
Node node = aList.findMToLast(offset);
if (node != null)
System.out.println(offset + "-th node to the last node contains " + node.getItem() + ".");
else
System.out.println("Offset(=" + offset + ") to the last node is greater than list size(=" + aList.size() + ").");
} // end main
} // end TestListReferenceBased
Stack trace is:
Exception in thread "main" java.lang.NullPointerException at
ListReferenceBased.add(ListReferenceBased.java:63) at
TestListReferenceBased.main(TestListReferenceBased.java:14)

java list shift items by rearranging links

I'm working with a linked list in java and I need to take a list of x objects and move the odd positioned objects to the end of the list.
I have to do it by using linking, no new nodes, no list.data exchanges.
I feel like I have a decent handle when I'm moving stuff from one list to another, but traversing and appending with references to only one list is really tough.
Here's the actual question ---
Write a method shift that rearranges the elements of a list of integers by moving to the end of the list all values that are in odd-numbered positions and otherwise preserving list order. For example, suppose a variable list stores the following values:
[0, 1, 2, 3, 4, 5, 6, 7]
The call of list.shift(); should rearrange the list to be:
[0, 2, 4, 6, 1, 3, 5, 7]
you must solve this problem by rearranging the links of the list.
below is the class that I need to write the method before (with the aforementioned restrictions.
I can't really come up with a plan of attack.
// A LinkedIntList object can be used to store a list of integers.
public class LinkedIntList {
private ListNode front; // node holding first value in list (null if empty)
private String name = "front"; // string to print for front of list
// Constructs an empty list.
public LinkedIntList() {
front = null;
}
// Constructs a list containing the given elements.
// For quick initialization via Practice-It test cases.
public LinkedIntList(int... elements) {
this("front", elements);
}
public LinkedIntList(String name, int... elements) {
this.name = name;
if (elements.length > 0) {
front = new ListNode(elements[0]);
ListNode current = front;
for (int i = 1; i < elements.length; i++) {
current.next = new ListNode(elements[i]);
current = current.next;
}
}
}
// Constructs a list containing the given front node.
// For quick initialization via Practice-It ListNode test cases.
private LinkedIntList(String name, ListNode front) {
this.name = name;
this.front = front;
}
// Appends the given value to the end of the list.
public void add(int value) {
if (front == null) {
front = new ListNode(value, front);
} else {
ListNode current = front;
while (current.next != null) {
current = current.next;
}
current.next = new ListNode(value);
}
}
// Inserts the given value at the given index in the list.
// Precondition: 0 <= index <= size
public void add(int index, int value) {
if (index == 0) {
front = new ListNode(value, front);
} else {
ListNode current = front;
for (int i = 0; i < index - 1; i++) {
current = current.next;
}
current.next = new ListNode(value, current.next);
}
}
public boolean equals(Object o) {
if (o instanceof LinkedIntList) {
LinkedIntList other = (LinkedIntList) o;
return toString().equals(other.toString()); // hackish
} else {
return false;
}
}
// Returns the integer at the given index in the list.
// Precondition: 0 <= index < size
public int get(int index) {
ListNode current = front;
for (int i = 0; i < index; i++) {
current = current.next;
}
return current.data;
}
// Removes the value at the given index from the list.
// Precondition: 0 <= index < size
public void remove(int index) {
if (index == 0) {
front = front.next;
} else {
ListNode current = front;
for (int i = 0; i < index - 1; i++) {
current = current.next;
}
current.next = current.next.next;
}
}
// Returns the number of elements in the list.
public int size() {
int count = 0;
ListNode current = front;
while (current != null) {
count++;
current = current.next;
}
return count;
}
// Returns a text representation of the list, giving
// indications as to the nodes and link structure of the list.
// Detects student bugs where the student has inserted a cycle
// into the list.
public String toFormattedString() {
ListNode.clearCycleData();
String result = this.name;
ListNode current = front;
boolean cycle = false;
while (current != null) {
result += " -> [" + current.data + "]";
if (current.cycle) {
result += " (cycle!)";
cycle = true;
break;
}
current = current.__gotoNext();
}
if (!cycle) {
result += " /";
}
return result;
}
// Returns a text representation of the list.
public String toString() {
return toFormattedString();
}
// Returns a shorter, more "java.util.LinkedList"-like text representation of the list.
public String toStringShort() {
ListNode.clearCycleData();
String result = "[";
ListNode current = front;
boolean cycle = false;
while (current != null) {
if (result.length() > 1) {
result += ", ";
}
result += current.data;
if (current.cycle) {
result += " (cycle!)";
cycle = true;
break;
}
current = current.__gotoNext();
}
if (!cycle) {
result += "]";
}
return result;
}
// ListNode is a class for storing a single node of a linked list. This
// node class is for a list of integer values.
// Most of the icky code is related to the task of figuring out
// if the student has accidentally created a cycle by pointing a later part of the list back to an earlier part.
public static class ListNode {
private static final List<ListNode> ALL_NODES = new ArrayList<ListNode>();
public static void clearCycleData() {
for (ListNode node : ALL_NODES) {
node.visited = false;
node.cycle = false;
}
}
public int data; // data stored in this node
public ListNode next; // link to next node in the list
public boolean visited; // has this node been seen yet?
public boolean cycle; // is there a cycle at this node?
// post: constructs a node with data 0 and null link
public ListNode() {
this(0, null);
}
// post: constructs a node with given data and null link
public ListNode(int data) {
this(data, null);
}
// post: constructs a node with given data and given link
public ListNode(int data, ListNode next) {
ALL_NODES.add(this);
this.data = data;
this.next = next;
this.visited = false;
this.cycle = false;
}
public ListNode __gotoNext() {
return __gotoNext(true);
}
public ListNode __gotoNext(boolean checkForCycle) {
if (checkForCycle) {
visited = true;
if (next != null) {
if (next.visited) {
// throw new IllegalStateException("cycle detected in list");
next.cycle = true;
}
next.visited = true;
}
}
return next;
}
}
// YOUR CODE GOES HERE
}
see it this way:
first we need some sort of cursor that will go through the list and point to our "current" node
second we need some boolean variable (i'll call it INV) initialized as FALSE ... everytime we move a node in the list, we invert INV
if you go through the list from the left, the second element is the first to be rearanged, so that will be our initial cursor position
lets take a reference on that element/node, and keep that reference as abort criteria
start of loop:
now remove the current node from the list and insert it at the end of the list (move to the end ... not that the cursor may not move with the node ...)
move the cursor to the node that is right of the former position of the node we just moved (if that exists)
if the current element is our abort criteria (first element we moved) we can assume the list is sorted now in the desired order -> we are finished -> exit the loop ... if it's not our abort criteria ... go on
evaluate "index of the cursor is even" to either TRUE or FALSE ... XOR that with INV
if the result is TRUE move the cursor to the next element ... if it's FALSE remove the node and insert it at the end (move it to the end)
do the loop
--
this approach will not preserve the order while we move through the list, but will have the list in the desired order when it finishes ...
the INV var is for compensation the index shifts when removing a node ... (0,1,2,3 ... if you remove the 1 and put it at the end, 2 will have an odd index, so if we invert that with every move, we get the "right" elements)

Categories

Resources