[Instructions] [Search] [Current] [Changes] [Syllabus] [Handouts] [Outlines] [Labs] [Assignments] [Examples] [Bailey Docs] [SamR Docs] [Tutorial] [API]
Held: Monday, March 9, 1998
tail
of a list and then modify that tail, do we modify the original list?
// Assume l is the list 3,6,8,32 lprime = l.tail(); lprime.addToHead(new Integer(5)); System.out.println(l.tail().head());
// Assume l is the list 3,6,8,32 lprime = l.tail(); lprime.remove(new Integer(8)); System.out.println(l.contains(new Integer(8)));
/**
* Nodes for a singly-linked list.
*/
public class Node {
/** The value in the current node. A value of null
* indicates (...)
*/
protected Object value;
/** The next node in the list. A value of null
* indicates that this is the last element of the list.
*/
protected Node next;
...
} // Node
tail, which now needs to create new list
objects.
/**
* A singly-linked list.
*/
public class List {
/** The elements of the list, starting at the front */
protected Node front;
/** The last element of the list. */
protected Node back;
/** The current element of the list. */
protected Node current;
...
} // List
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 of Nodes.
* 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
On to Sorting Lists
Back to Sorting Without Swapping
Outlines:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
Current position in syllabus
[Instructions] [Search] [Current] [Changes] [Syllabus] [Handouts] [Outlines] [Labs] [Assignments] [Examples] [Bailey Docs] [SamR Docs] [Tutorial] [API]
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.
This page may be found at http://www.math.grin.edu/~rebelsky/Courses/CS152/98S/home/rebelsky/public_html/Courses/CS152/98S/Outlines/outline.27.html
Source text last modified Tue Jan 12 11:52:25 1999.
This page generated on Mon Jan 25 09:49:28 1999 by SiteWeaver. Validate this page.
Contact our webmaster at rebelsky@math.grin.edu