List class, we might write
our insert at head function as follows
/** Insert a non-null object at the head of the list.
* pre: The element is not null.
* pre: The current list has been initialized
* post: The head of the list is now that element.
* post: The tail of the list is the previous list.
*/
public void insertAtHead(Object element) {
// Create a node to hold the new element.
Node new_head = new Node(element,null);
// Is the list currently empty? If so, just insert the element
// at front and back, and we're done.
if (front == null) {
front = new_head;
back = new_head;
current = new_head;
}
// Otherwise, update the next reference of the new head
// and replace the front of the list
else {
new_head.setNext(front);
front = new_head;
// We don't need to modify the back of the list.
// Should we modify current?
}
} // insertAtHead
List structure, we can't
really talk about modifying the current list. Hence, we need to create
a static method that takes a Node as a parameter, and
returns a (potentially new) Node.
/**
* Construct a new list from a new head element and old tail.
*/
public Node cons(Element head, Node tail) {
return new Node(head,tail);
} // cons
back field.
List-based version (in which we
do have a back.
/**
* Append an element to the end of the list.
* pre: The element is not null.
* pre: The list has been appropriately initialized and maintained.
* post: The list now contains the element at the end.
*/
public void appendToEnd(Object element) {
// Create the node for the new element
Node new_end = new Node(element,null);
// Special case: the list is empty
if (front == null) {
front = new_end;
back = new_end;
current = new_end;
}
// Normal case: we just need to update the end
else {
back.setNext(new_end);
back = new_end;
}
} // appendToEnd
back field.
public void appendToEnd(Object element) {
// Create the node for the new element
Node new_end = new Node(element,null);
// Special case: the list is empty
if (front == null) {
front = new_end;
}
// Normal case: need to traverse the list until we find
// the end
else {
Node traverse = front;
while (traverse.next != null) {
traverse = traverse.next;
}
traverse.next = new_end;
}
} // appendToEnd
Node class).
/**
* Delete the first element in the list, returning that element.
* pre: the list is nonempty
* post: the list is one element smaller and no longer
* contains the previous head element
public Object deleteHead() throws ListException {
// Special case: the list is empty
if (front == null) {
throw new ListException("Can't delete the head of an empty list");
}
// Standard case: the list is nonempty
else {
Node deleted = front;
// Update the front
front = front.nextNode();
// Update current, if necessary. == is the appropriate comparison
// operation since we want to make sure that we're referring to
// the same node, and not just two nodes with the same contents.
if (current == deleted) {
current = front;
}
// Return the front element
return deleted.contents();
} // else
} // deleteHead
Node class, it
would also be reasonable to directly access Node's fields,
since these are related classes, and would be in the same package.
Node-based version is really just
a call to tail. To delete the head of a list l,
you would just use l = l.tail()
/**
* Delete the last element in the list, returning that element.
* pre: the list is nonempty
* post: the list is one element smaller and no longer
* contains the previous final element
* post: if the current element was the final element, the
* current element is now the first element.
*/
public Object deleteLast() throws ListException {
// The element we're about to delete
Node deleted;
// Special case: the list is empty
if (front == null) {
throw new ListException("Can't delete the last element in an empty list");
}
// Special case: the list has one element
else if (front.next == null) {
deleted = front;
front = null;
current = null;
back = null;
return deleted.contents();
} // only one element
// Standard case: the list has at least two elements
else {
// The element we're currently looking at
Object pointer = front;
// The element we're about to delete
Object
// Keep going until we reach the last node
while (pointer.nextNode().nextNode() != null) {
pointer = pointer.nextNode();
} // while
// We're now one step back from the end, so delete
// the next element.
deleted = pointer.next;
pointer.next = null;
// Update the current element if necessary.
if (current == deleted) {
current = front;
}
// Return the element
return deleted.contents();
} // List of length two or more
} // deleteLast
Node-based deletion.
/** * Delete all copies of an element from a sequence ofNodes. * pre: (none) * post: The returned list no longer contains any copies of the element. * post: Any lists that contain sublists may also be modified. */ public Node deleteCopies(Node list, Object element) { // Base case: empty list if (list == null) { return null; } // The head of the list contains the element. Delete and // recurse else if (list.contents().equals(element)) { return deleteCopies(list.tail(), element); } // The head of the list doesn't contain the element. Work on // the tail. else { list.setNext(deleteCopies(list.tail(), element)); return list; } } // deleteCopies /** * Delete all copies of an element from a list. * pre: (none) * post: The returned list no longer contains any copies of the element. * post: Any lists that contain sublists may also be modified. * post: If the current element was deleted, the current element * now refers to the front of the list. */ public void deleteCopies(element) { front = deleteCopies(front,element); // Fix current element if necessary if (current.contents().equals(element)) current = front; // Recompute the last element if necessary if (back.contents().equals(element)) recomputeBack(); } // deleteCopies
Disclaimer Often, these pages were created "on the fly" with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.
Source text last modified Tue Oct 14 08:30:44 1997.
This page generated on Wed Nov 5 12:38:33 1997 by SiteWeaver.
Contact our webmaster at rebelsky@math.grin.edu