The List ADT
The List ADT
9-2
Lists
• A list is a linear collection, like a stack
and queue, but more flexible: adding
and removing elements from a list does
not have to happen at one end or the
other
• We will examine three types of list
collections:
• ordered lists
• unordered lists
• indexed lists
9-3
Ordered Lists
• Ordered list: Its elements are ordered
by some inherent characteristic of the
elements
• Examples:
• Names in alphabetical order
• Numeric scores in ascending order
• So, the elements themselves determine
where they are stored in the list
9-4
Conceptual View of an Ordered List
front rear
16 23 29 40 51 67 88
9-5
Unordered Lists
• Unordered list : the order of the elements in
the list is not based on a characteristic of the
elements, but is determined by the user of the
list
• A new element can be put
• on the front of the list
• or on the rear of the list
• or after a particular element already in the list
• Examples: shopping list, to-do list, …
9-6
Conceptual View of an Unordered List
front rear
front rear
1 2 3 4 5 6 7
Operation Description
removeFirst Removes the first element from the list
removeLast Removes the last element from the list
remove Removes a particular element from the list
first Examines the element at the front of the list
last Examines the element at the rear of the list
contains Determines if a particular element is in the list
isEmpty Determines whether the list is empty
size Determines the number of elements in the list
iterator Returns an iterator for the list’s elements
toString Returns a string representation of the list
9-11
Operation Particular to an
Ordered List
Operation Description
add Adds an element to the list
(in the correct place)
9-12
Operations Particular to an
Unordered List
Operation Description
addToFront Adds an element to the front of the list
addToRear Adds an element to the rear of the list
addAfter Adds an element after a particular
element already in the list
9-13
Operations Particular to an
Indexed List
Operation Description
add Adds an element at a particular index in
the list
set Sets the element at a particular index in
the list
get Returns a reference to the element at
the specified index
indexOf Returns the index of the specified
element
remove Removes and returns the element at a
particular index 9-14
List Operations
• We use Java interfaces to formally define
the operations on the lists, as usual
• Note that interfaces can be defined via
inheritance (derived from other interfaces)
• Define the common list operations in one
interface
• See ListADT.java
• Derive the thee others from it
• see OrderedListADT.java
• see UnorderedListADT.java
• see IndexedListADT.java 9-15
ListADT Interface
import java.util.Iterator;
public interface ListADT<T> {
9-16
// ..cont’d
// Returns true if this list contains the specified target element
public boolean contains (T target);
// Returns true if this list contains no elements
public boolean isEmpty( );
// Returns the number of elements in this list
public int size( );
// Returns an iterator for the elements in this list
public Iterator<T> iterator( );
// Returns a string representation of this list
public String toString( );
}
9-17
OrderedList ADT
9-18
UnorderedListADT
9-19
IndexedListADT
public interface IndexedListADT<T> extends ListADT<T> {
// Inserts the specified element at the specified index
public void add (int index, T element);
// Sets the element at the specified index
public void set (int index, T element);
// Adds the specified element to the rear of this list
public void add (T element);
// Returns a reference to the element at the specified index
public T get (int index);
// Returns the index of the specified element
public int indexOf (T element);
// Removes and returns the element at the specified index
public T remove (int index);
}
9-20
Discussion
• Note that the add method in the
IndexedList ADT is overloaded
• So is the remove method
• Why? Because there is a remove method
in the parent ListADT
• This is not overriding, because the
parameters are different
9-21
<<interface>>
ListADT
removeFirst( )
UML
removeLast( )
remove(T)
Diagrams for
first( )
last( ) Various List
contains(T)
isEmpty( )
size( )
Interfaces
iterator( )
toString( )
<<interface>>
IndexedListADT
<<interface>> <<interface>>
UnorderedListADT OrderedListADT
add(T)
add(int, T)
set(int, T) addToFront(T) add(Comparable)
get(int) addToRear(T)
indexOf(T) addAfter(element:T, target:T) 9-22
remove(int)
List Implementation using Arrays
• Container is an array
• Fix one end of the list at index 0 and shift as
needed when an element is added or removed
• Is a shift needed when an element is added
• at the front?
• somewhere in the middle?
• at the end?
• Is a shift needed when an element is removed
• from the front?
• from somewhere in the middle?
• from the end?
9-23
An Array Implementation of a List
0 1 2 3 4 5
? ? … ?
ls list
4
rear
9-24
UML Diagram for ArrayList
ArrayList <<interface>>
rear ListADT
list
NOT_FOUND
removeFirst( )
DEFAULT_CAPACITY
removeLast( )
removeFirst( )
remove(T element)
removeLast( )
first( )
remove(T element)
last( )
first( )
contains()
last( )
isEmpty( )
contains()
size( )
isEmpty( )
iterator( )
size( )
toString( )
iterator( )
toString( )
- find( )
Class ArrayList will be extended
- expandCapacity( )
to yield classes ArrayOrderedList,
9-25
ArrayUnorderedList, etc.
//-----------------------------------------------------------------
// Removes and returns the specified element.
//-----------------------------------------------------------------
public T remove (T element) throws ElementNotFoundException
{
T result;
int index = find (element); // uses helper method find
if (index == NOT_FOUND)
throw new ElementNotFoundException("list");
result = list[index];
rear--;
// shift the appropriate elements
for (int scan=index; scan < rear; scan++)
list[scan] = list[scan+1];
list[rear] = null; The remove( )
return result; operation
} 9-26
//-----------------------------------------------------------------
// Returns the array index of the specified element,
// or the constant NOT_FOUND if it is not found.
//-----------------------------------------------------------------
private int find (T target)
{
int scan = 0, result = NOT_FOUND;
boolean found = false;
if (! isEmpty( ))
while (! found && scan < rear)
if (target.equals(list[scan])
found = true; The find( )
else helper method
scan++;
if (found)
result = scan;
return result;
9-27
}
//-----------------------------------------------------------------
// Returns true if this list contains the specified element.
//-----------------------------------------------------------------
public boolean contains (T target)
{
return (find(target) != NOT_FOUND);
//uses helper method find
}
The contains( )
operation
9-28
//-----------------------------------------------------------------
// Adds the specified Comparable element to the list,
// keeping the elements in sorted order.
//-----------------------------------------------------------------
public void add (T element)
{
if (size( ) == list.length)
expandCapacity( );
Comparable<T> temp = (Comparable<T>)element;
int scan = 0;
while (scan < rear && temp.compareTo(list[scan]) > 0)
scan++;
for (int scan2=rear; scan2 > scan; scan2--)
list[scan2] = list[scan2-1]
The add( ) operation
list[scan] = element;
rear++;
of ArrayOrderedList
9-29
}
The Comparable Interface
• For an ordered list, the actual class for the
generic type T must have a way of
comparing elements so that they can be
ordered
• So, it must implement the Comparable
interface, i.e. it must define a method called
compareTo
• But, the compiler does not know whether
or not the class that we use to fill in the
generic type T will have a compareTo
method
9-30
The Comparable Interface
• So, to make the compiler happy:
• Declare a variable that is of type
Comparable<T>
• Convert the variable of type T to the
variable of type Comparable<T>
Comparable<T> temp =
(Comparable<T>)element;
9-32
List Implementation Using Links
• We can implement a list collection with a
linked list as the container
• Implementation uses techniques similar to
ones we've used for stacks and queues
• We will first examine the remove operation
for a singly-linked list implementation
• Then we’ll look at the remove operation for a
a doubly-linked list, for comparison
9-33
//-----------------------------------------------------------------
// Removes the first instance of the specified element
// from the list, if it is found in the list, and returns a
// reference to it. Throws an ElementNotFoundException
// if the specified element is not found on the list.
//-----------------------------------------------------------------
public T remove (T targetElement) throws ElementNotFoundException
{
if (isEmpty( ))
throw new ElementNotFoundException ("List");
boolean found = false;
LinearNode<T> previous = null
LinearNode<T> current = head;
// cont’d.. The remove( )
operation
(singly-linked list) 9-34
while (current != null && !found)
if (targetElement.equals (current.getElement( )))
found = true;
else
{
previous = current;
current = current.getNext( );
}
if (!found)
throw new ElementNotFoundException ("List");
if (size( ) == 1)
head = tail = null;
else The remove( )
if (current.equals (head))
head = current.getNext( );
operation (cont’d)
else 9-35
// cont’d
if (current.equals (tail))
{
tail = previous;
tail.setNext(null);
}
else
previous.setNext(current.getNext( ));
count--;
return current.getElement( );
} The remove( )
operation (cont’d)
9-36
Doubly Linked Lists
• A doubly linked list has two
references in each node:
• One to the next element in the list
• One to the previous element
• This makes moving back and forth in a
list easier, and eliminates the need for a
previous reference in particular
algorithms
• Disadvantage? a bit more overhead
when managing the list
9-37
Implementation of a Doubly-
Linked List
A doubly-linked list dl with 4 elements
rear
dl . .
front
4
count
9-38
• See DoubleNode.java
9-39
//-----------------------------------------------------------------
// Removes and returns the specified element.
//-----------------------------------------------------------------
public T remove (T element) throws
ElementNotFoundException
{
T result;
DoubleNode<T> nodeptr = find (element);
// uses helper method find for doubly-linked list
if (nodeptr == null)
throw new ElementNotFoundException ("list");
result = nodeptr.getElement( );
// check to see if front or rear The remove( )
if (nodeptr == front)
result = this.removeFirst( ); operation
// cont’d.. (doubly-linked list)
9-40
else
if (nodeptr == rear)
result = this.removeLast( );
else
{
nodeptr.getNext( ).setPrevious(nodeptr.getPrevious( ));
nodeptr.getPrevious( ).setNext(nodeptr.getNext( ));
count--;
}
The remove( )
}
return result;
operation (cont’d)
9-41
Analysis of List Implementations
• In both array and linked implementations,
many operations are similar in efficiency
• Most are O(1) , except when shifting or
searching need to occur, in which case they
are order O(n)
• Exercise: determine the time complexity of
each operation
• In particular situations, the frequency of the
need for particular operations may guide the
use of one approach over another
9-42