# Class 26: Implementing Lists

Back to Discussion of Exam 1. On to Vectors.

Held Tuesday, March 9

Summary

• Techniques for implementing lists
• Arrays
• Nodes
• Specification vs. implementation: does a sorted list really have to be sorted?

Contents

Notes

• Make sure to read lab X2 for tomorrow's class.
• There is no way that we'll cover everything in today's outline. Make sure to scan it for information.
• Don't forget: cool math convocation talk this Thursday.
• I may not be here tomorrow because of sick children. If so, Mr. Flynt will cover the class.
• You may be wondering how to study for open-book take-home exams. I'll admit that I don't think you need to do extensive studying for such exams. Here are a few tips I use in studying for any exam.
• Make a ``cheat sheet'', summarizing what you've learned.
• Make an ``index'' of important topics, and where to find more information on those topics.
• Try to do some problems in the book or lab manual.
• Try to write some of your own problems, based on those you've received in homework of I've mentioned in class.
• ...

## Interfaces for the List Classes

• Let's review what we've decided about lists by developing some Java interfaces for the various kinds of lists.

### Simple Lists

```/**
* Simple lists.  The client has no control over placement of
* elements within the list.
*
* @author Samuel A. Rebelsky
* @version 1.0 of March 1999
*/
public interface SimpleList {

// +-----------------------+-----------------------------------
// | Basic List Operations |
// +-----------------------+

/**
* Add an element to the list.
* Precondition: The list has been initialized.
* Precondition: There is ``space'' to add another element.
* Precondition: element is not null.
* Postcondition: The list has grown by one element.
* Postcondition: The new element is somewhere in the list.
* Postcondition: A reset may be needed before iteration
*   is successful.
*/

/**
* Delete one copy of an element from the list.
* Precondition: The list has been initialized.
* Postcondition: If the list contained any elements equal
*   to the specified element, it now contains one fewer.
* Postcondition: A reset may be needed before iteration is
*   successful.
*/
public void delete(Object element);

/**
* Get the length of the list.
* Precondition: The list has been initialized.
* Postcondition: Returns the length of the list.
*/
public int length();

/**
* Is there space for an additional element?
* Precondition: The list has been initialized.
* Postcondition: If there is space for an additional element,
*   returns true.  Otherwise, returns false.
*/
public boolean spaceAvailable();

// +-----------+-----------------------------------------------
// | Iteration |
// +-----------+

/**
* Reset iteration.  Necessary after any call to add or delete.
* Precondition: The list has been initialized.
* Postcondition: All elements are marked as ``unseen''.
* Postcondition: No elements are added or removed.
*/
public void reset();

/**
* Get some unseen element.
* Precondition: The list has been initialized.
* Precondition: There are unseen elements remaining.
* Precondition: There have been no calls to add or delete
*   since the last call to reset.
* Postcondition: One more element is marked as ``seen''.
* Postcondition: That element is returned.
*/
public Object nextElement();

/**
* See if there are any remaining unseen elements.
* Precondition: The list has been initialized.
* Precondition: There have been no calls to add or delete
*   since the last call to reset.
* Postcondition: If there are unseen elements remaining, returns
*   true.  Otherwise, returns false.
*/
public boolean hasMoreElements();
} // interface SimpleList
```

### Simple Ordered Lists

• Simple ordered lists are like simple lists, except they use a different semantics for many operations (one that makes the ordering clear).
• Note that the wonders of inheritance mean that I didn't need to include all of the operations.
```/**
* Simple ordered lists.  The client has primitive control over
* placement of elements within the list.  Also adds a notion
* of ``cursor'' for iteration.  The cursor is on the element
* that will be returned by nextElement().
*
* @author Samuel A. Rebelsky
* @version 1.0 of March 1999
*/
public interface SimpleOrderedList
extends SimpleList
{

// +-----------------------+-----------------------------------
// | Basic List Operations |
// +-----------------------+

/**
* Add an element to the end of the list.
* Precondition: The list has been initialized.
* Precondition: There is ``space'' to add another element.
* Precondition: element is not null.
* Postcondition: The list has grown by one element.
* Postcondition: The new element is at the end of the list.
* Postcondition: If x preceded y in the list before the
*   addition, then x still precedes y.
* Postcondition: The position of the cursor is unspecified.
*/

/**
* Delete the first copy of an element from the list.
* Precondition: The list has been initialized.
* Postcondition: If the list contained any elements equal
*   to the specified element, it now lacks the first such
*   element.
* Postcondition: If x preceded y in the list before the
*   deletion and neither x nor y were deleted, then
*   x still precedes y.
* Postcondition: The position of the cursor is unspecified.
*/
public void delete(Object element);

// +-----------+-----------------------------------------------
// | Iteration |
// +-----------+

/**
* Reset iteration.  Necessary after any call to add or delete.
* Precondition: The list has been initialized.
* Postcondition: Resets iteration to the beginning of the list.
* Postcondition: No elements are added or removed.
* Postcondition: Elements are not rearranged.
* Postcondition: The cursor is on the first element of the list.
*/
public void reset();

/**
* Get the next element of the list (according to the order
*   of addition).  That is, the element which the cursor
*   refers to.
* Precondition: The list has been initialized.
* Precondition: There are unseen elements remaining.
* Precondition: There have been no calls to add or delete
*   since the last call to reset.
* Postcondition: The next element is returned.
* Postcondition: Advances the cursor to the next element.
* Postcondition: Elements are not rearranged.
*/
public Object nextElement();

/**
* See if there are any remaining elements.
* Precondition: The list has been initialized.
* Precondition: There have been no calls to add or delete
*   since the last call to reset.
* Postcondition: If the cursor refers to an element of the
*   list, returns true.  Otherwise, returns false.
* Postcondition: Elements are not rearranged.
*/
public boolean hasMoreElements();
} // interface SimpleList
```

### Ordered Lists

• Ordered lists are like simple ordered lists, except they support additional operations for adding elements.
```/**
* Ordered lists.  The client has control over placement of elements
* within the list.
*
* @author Samuel A. Rebelsky
* @version 1.0 of March 1999
*/
public interface OrderedList
extends SimpleOrderedList
{

// +---------------------+-------------------------------------
// | New List Operations |
// +---------------------+

/**
* Add an element to the end of the list.
* Precondition: The list has been initialized.
* Precondition: There is ``space'' to add another element.
* Precondition: The element is not null.
* Postcondition: The list has grown by one element.
* Postcondition: The new element is at the end of the list.
* Postcondition: If x preceded y in the list before the
*   addition, then x still precedes y.
* Postcondition: The position of the cursor is unknown.
*/

/**
* Add an element at the front of the list.
* Precondition: The list has been initialized.
* Precondition: There is ``space'' to add another element.
* Precondition: The element is not null.
* Postcondition: The list has grown by one element.
* Postcondition: The new element is at the beginning of the list.
* Postcondition: If x preceded y in the list before the
*   addition, then x still precedes y.
* Postcondition: The position of the cursor is unknown.
*/

/**
* Add an element before the cursor.
* Precondition: The list has been initialized.
* Precondition: The position of the cursor is known (there
*   since the last call to reset).
* Precondition: There is ``space'' for another element.
* Precondition: The element is not null.
* Postcondition: The element is added before the cursor.  That
*   is, (1) if x preceded the cursor, it precedes the new element;
*   (2) if y followed the cursor, it follows the new element;
*   (3) the cursor immediately follows the new element.
* Postcondition: The cursor remains on the same element.
*/

/**
* Add an element after the cursor.
* Precondition: The list has been initialized.
* Precondition: The position of the cursor is known (there
*   since the last call to reset).
* Precondition: There is ``space'' for another element.
* Precondition: The element is not null.
* Postcondition: The element is added after the cursor.  That
*   is, (1) if x preceded the cursor, it precedes the new element;
*   (2) if y followed the cursor, it follows the new element;
*   (3) the cursor immediately precedes the new element.
* Postcondition: The cursor remains on the same element.
*/

} // interface OrderedList
```

### Sorted Lists

• Sorted lists add a sort order (we'll need to think about how to specify that sort order). When we iterate the list, we get the next element according to the sort order.
• This means that we just need to change the semantics of the iteration operations.
```/**
* Sorted lists.  The elements are iterated according to some
* specified ``sort order''.
*
* @author Samuel A. Rebelsky
* @version 1.0 of March 1999
*/
public interface SortedList
extends SimpleList
{
// +-----------+-----------------------------------------------
// | Iteration |
// +-----------+

/**
* Reset iteration.  Necessary after any call to add or delete.
* Precondition: The list has been initialized.
* Postcondition: All elements are marked as ``unseen''.
* Postcondition: No elements are added or removed.
*/
public void reset();

/**
* Get the next element, according to the sort order.
* Precondition: The list has been initialized.
* Precondition: There are unseen elements remaining.
* Precondition: There have been no calls to add or delete
*   since the last call to reset.
* Postcondition: Identifies an element, x, such that
*   (1) for all y that have been returned by nextElement
*   since the last call to reset, x >= y; and (2)
*   for all z that have not yet been returned by nextElement,
*   x <= z.
* Postcondition: That element is returned.
*/
public Object nextElement();

/**
* See if there are any remaining unseen elements.
* Precondition: The list has been initialized.
* Precondition: There have been no calls to add or delete
*   since the last call to reset.
* Postcondition: If there are unseen elements remaining, returns
*   true.  Otherwise, returns false.
*/
public boolean hasMoreElements();
} // interface SortedList
```

## Implementing Lists

• We've thought about the various functionalities we might place in our various kinds of list classes.
• It is now time to consider how best to implement lists.
• There are two strategies for implementing lists:
• You can store the elements in an array
• You can allocate space for the elements dynamically
• We will consider each in turn, mostly working with basic lists.

## Implementing Lists With Arrays

• The fields:
• An array of elements
• The index of the next thing to add
• The cursor
• The length
• Possibly a comparison mechanism (for sorted lists)
• The constructors:
• With an initial array size
• With initial array size and default value?
• Does that suggest that the list is full?
• Some questions
• Can we do without the array size?
• Are there other things we need?
• Can we do without the length?
• The methods (think about preconditions and postconditions)
• delete(Object o)
• length
• reset -- reset the cursor
• nextElement -- get the next ``unseen'' element
• hasMoreElements -- are there any more ``unseen'' elements?
• ...
• More questions
• Should we copy elements when assigning, or just copy references.
• Others?
• Here's an untested implementation of simple lists in Java.
```/**
* The start of an implementation of Simple Lists, using arrays
* as the underlying implementation structure.
*
* @author Samuel A. Rebelsky
* @version 1.0 of March 1999
*/
public class ArrayBasedSimpleList
implements SimpleList
{
// +--------+--------------------------------------------------
// | Fields |
// +--------+

/** The elements of the list. */
protected Object[] elements;

/** The cursor. */
protected int cursor;

/**
* The length of the list (different from the length of
* the array).  Also used as the index of the next element
*/
protected int length;

// +--------------+--------------------------------------------
// | Constructors |
// +--------------+

/** Create a new list of specified capacity. */
public ArrayBasedSimpleList(int capacity) {
elements = new Object[capacity];
reset();
} // ArrayBasedSimpleList(int)

// +---------+-------------------------------------------------
// | Methods |
// +---------+

/**
* Add an element to the list.  See the interface for
* preconditions and postconditions.
*/
this.elements[this.length] = element;
// Increase the length
++this.length;

/**
* Delete an element from the list.  See the interface for
* preconditions and postconditions.
*/
public void delete(Object element) {
// Step through the list until we find an equal element
for (int i = 0; i < this.length; ++i) {
// Note that we use element.equal because some
// elements of the list may be null
if (element.equals(this.elements[i])) {
// Found it!
// Put the last thing here.
this.elements[i] = this.elements[this.length-1];
// Clear the last thing.
this.elements[this.length-1] = null;
// Update the length.
--this.length;
// And we're done.
return;
}
} // for
// Nope, didn't find it.  Nothing else to do.
} // delete(Object)

/**
* Determine the length of the list.  See the interface
* for preconditions and postconditions.
*/
public int length() {
return this.length;
} // length()

/**
* Determine whether there is space available.  See the
* interface for preconditions and postconditions.
*/
public boolean spaceAvailable() {
// There is space available if the length of the list is
// less than the length of the array.
return this.length < this.elements.length;
} // spaceAvailable()

/**
* Reset iteration.  See the interface for preconditions and
* postconditions.
*/
public void reset() {
this.cursor = 0;
} // reset()

/**
* Get the next element.  See the interface for preconditions
* and postconditions.
*/
public Object nextElement() {
// Note that it is possible to express this more concisely as
//   return this.elements[this.cursor++];

// Get the element to return.
Object tmp = this.elements[this.cursor];
++this.cursor;
// Return the element.
return tmp;
} // nextElement()

/**
* Are there more elements left?  See the interface for preconditions
* and postconditions.
*/
public boolean hasMoreElements() {
return this.cursor <= this.length;
} // hasMoreElements()
} // class ArrayBasedSimpleList
```

### Resizing List-Based Arrays

• What happens when you run out of space in the array?
• Traditionally, you disallow the addition of new elements if the array has no space remaining.
• You might also create a new, bigger, array when you run out of space.
• Lists can keep expanding
• You don't need to specify the maximum size of the list when you create it.
• ...
• Inserting an element may no longer take constant time
• May still run out of memory
• ...

### ``Gaps'' in The Array

• Rather than copying elements in when we delete, we might also leave ``gaps'' in the array by setting the deleted position to null.
• When we add an element, we might put it in the first space (or some space).
• When iterating, we need to skip over spaces.

### Implementing Simple Ordered Lists

• How does the implementation change for simple ordered lists (assuming we don't support ``gaps''?
• The iterator goes through the elements in a logical order.
• So we just have to fix delete.
• The new delete needs to shift elements, rather than shoving the last element in the proper place.
```  /**
* Delete an element from the list.  See the interface for
* preconditions and postconditions.
*/
public void delete(Object element) {
// Step through the list until we find an equal element
for (int i = 0; i < this.length; ++i) {
// Note that we use element.equal because some
// elements of the list may be null
if (element.equals(this.elements[i])) {
// Found it!
// Shift everything down.
for (int j = i; j < this.length-1; ++j) {
this.elements[j] = this.elements[j+1];
// Clear the last thing.
this.elements[this.length-1] = null;
// Update the length.
--this.length;
// And we're done.
return;
} // if found
} // for
// Nope, didn't find it.  Nothing else to do.
} // delete(Object)
```

History

• Created Monday, January 11, 1999.
• Added short summary on Friday, January 22, 1999.
• Filled in some details on Monday, March 8, 1999.
• Added lots of Java code on Tuesday, March 9, 1999.
• Made a few corrections, and moved some stuff on Thursday, March 11, 1999.
• Made a few more corrections on Sunday, March 14, 1999.

Back to Discussion of Exam 1. On to Vectors.

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.