54
B/W Confirming Pages O b j e c t i v e s After you have read and studied this chapter, you should be able to Describe the key features of the List ADT. Implement the List ADT using an array and linked list. Describe and implement the iterator pattern. Explain the key differences between the array and linked implementations of the List ADT. 981 18 List ADT wu23399_ch18.qxd 1/2/07 20:37 Page 981

List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

O b j e c t i v e s

After you have read and studied this chapter, you should be able to

• Describe the key features of the List ADT.

• Implement the List ADT using an array andlinked list.

• Describe and implement the iterator pattern.

• Explain the key differences between the arrayand linked implementations of the List ADT.

981

18List ADT

wu23399_ch18.qxd 1/2/07 20:37 Page 981

Page 2: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

e introduced the concept of linked lists in Chapter 16 and provided the funda-mentals of manipulating links. And, in Chapter 17, we introduced the genericsfeature of Java 5.0 and used it in defining the SimpleLinkedList class that provides ahigher-level abtraction to the client programmers. Using a SimpleLinkedList, theclient programmers do not have to deal directly with the linked nodes. Instead, theydeal strictly with list objects. The fact that the linked nodes are used in implemen-tation is hidden from the client programmers. This embodies the software engineeringprinciple of information hiding. In this chapter, we will expand this concept furtherby introducing an abstract data type (ADT). ADTs are reusable software compo-nents that support reliable and flexible software construction.

An abstract data type (ADT) is a mathematical specification of a set of dataand the corresponding set of operations performed on those data. The key pointis that an ADT does not specify how the set of data is actually represented inmemory or how the set of operations is implemented. Nice examples of ADTscan be found in the Java Collections Framework. When we look in the java.utilpackage, for example, we see the Java interface List and two classes that imple-ment the List interface. The List interface represents the List ADT, and the twoclasses—ArrayList and LinkedList—implement the List ADT. The ArrayListuses an array, and the LinkedList uses linked nodes to implement the List ADT,respectively.

To study how the ADT is defined and implemented, we will create our ownList ADT and provide two implementations in this chapter which we model after thejava.util.List interface and its two implementations. Ours is a much simplified ver-sion of those in the java.util package. In Chapters 19 and 20, we will study the Stackand Queue ADTs, respectively.

18.1 The List ADTA list is a linearly ordered collection of elements. Figure 18.1 shows a sample list,named sampleList, with five elements and another list, named myList, with fivethree-letter animal names (String objects). Mathematically, we can designatesampleList as

sampleList = ( Lo, L1, L2, L3, L4 )

Elements in a list are said to be linearly ordered. This means L0 comes before L1

and L1 comes before L2, and so forth. For the sample list myList, the first ele-ment is L0 and the last element is L4. Note that we are using the zero-based in-dexing. Elements in a list do not have to be distinct; i.e., duplicate elements are

982 Chapter 18 List ADT

I n t r o d u c t i o n

W

abstract datatype (ADT)

list ADT

linear ordering

duplicateelements

wu23399_ch18.qxd 1/2/07 20:37 Page 982

Page 3: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

allowed. Two objects o1 and o2 are considered duplicates if o1.equals(o2) is true.In the sample list myList, we see that L1 and L3 are duplicates. A list also allowsmultiple null elements. We will discuss more about the impact of duplicate and nullelements in the implementation sections.

In the remainder of this section, we will describe the operations of the ListADT.

The add operation adds a new element to a list. There are two versions: Thefirst one adds a new element at the end of the list. The second one adds a newelement at the designated position in the list.

For the second version, all elements in that and higher positions will be shiftedto a position one index higher; that is, an element at position i will be shifted toposition i � 1. If the given position is a negative value, or larger than the currentsize of the list, then the index out-of-bound exception will be thrown. Figure 18.2illustrates the second version of the add operation.

18.1 The List ADT 983

Figure 18.1 A generic list named sampleList with five elements and a list of three-letter animals, namedmyList.

L0 L1 L2 L3 L4

0 1 2 3 4

This value indicatesthe position of anelement in the list.

This line indicates that the listelements are connected in alinear sequence.

"ape" "dog" "bee" "dog" "eel"0 1 2 3 4

Notice that the listelements do not

have to be unique.

sampleList

myList

null elements

add

wu23399_ch18.qxd 1/2/07 20:37 Page 983

Page 4: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

984 Chapter 18 List ADT

Figure 18.2 Sample version 2 add operations on myList.

Before

After

Before

After

"cat" "gnu" "ape" "dog" "bee"0 1 2 3 4

"cat"0

"ape"1

"dog"2

"bee"3

add(1, “gnu”)

throws<index-out-of-bounds-exception>add(5, "gnu")

myList

"cat"0

"ape"1

"dog"2

"bee"3

myList

myList

myList

"cat"0

"ape"1

"dog"2

"bee"3

No structuralchange to the list

contains

The clear operation removes all elements in the list, which results in an emptylist. Figure 18.3 illustrates the clear operation.

The contains operation returns true if a specified element is included in thelist. Otherwise, false is returned. Notice that there could be duplicate objects. Thesearch will stop immediately after the first match, and true is returned. Figure 18.4illustrates the contains operation.

The get operation returns the element stored at the designated position. If thegiven position is outside of a valid range—less than 0 or greater than or equal to thesize of the list—an index out-of-bound exception is thrown. The get operation is aread-only operation. It does not remove the element, so the list remains the sameafter the get operation. Figure 18.5 illustrates the get operation.

get

clear

wu23399_ch18.qxd 1/2/07 20:37 Page 984

Page 5: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

18.1 The List ADT 985

Figure 18.3 The effect of the clear operation on the myList list.

Before

After

"cat"0

"ape"1

"dog"2

"bee"3

clear( )

myList

myList

Figure 18.4 Sample contains operations on the myList list.

Before

After

Before

AfterNo structuralchange to the list

No structuralchange to the list

returnsfalsecontains("gnu")

returnstruecontains("ape")

"cat"0

"ape"1

"dog"2

"bee"3

myList

"cat"0

"ape"1

"dog"2

"bee"3

myList

"cat"0

"ape"1

"dog"2

"bee"3

myList

"cat"0

"ape"1

"dog"2

"bee"3

myList

wu23399_ch18.qxd 1/2/07 20:37 Page 985

Page 6: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

The indexOf operation returns the position of the specified object in the list. Ifthe specified object is not in the list, then NOT_FOUND (�1) is returned. If there areduplicates, then the position of the first match is returned. Figure 18.6 illustrates theindexOf operation.

The isEmpty operation returns true if the list is empty. Otherwise, false isreturned. Figure 18.7 illustrates the isEmpty operation.

There are two versions of the remove operation. In the first version, we spec-ify the element to remove by passing its position; in the second version, we specifythe element to remove by passing the element itself. The first version returns theelement removed from the list. It throws an index out-of-bound exception ifthe index i is outside the valid range of 0 and the size of the list minus 1, that is,0 ≤ i ≤ size � 1.

986 Chapter 18 List ADT

Figure 18.5 Sample get operations on the myList list.

No structuralchange to the list

No structuralchange to the list

returns“dog”get(2)

throws<index-out-of-bounds-exception>get(4)

Before "cat"0

"ape"1

"dog"2

"bee"3

myList

Before "cat"0

"ape"1

"dog"2

"bee"3

myList

myList

After "cat"0

"ape"1

"dog"2

"bee"3

myList

After "cat"0

"ape"1

"dog"2

"bee"3

isEmpty

remove

indexOf

wu23399_ch18.qxd 1/2/07 20:37 Page 986

Page 7: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

The second version removes the element and returns true. If the designatedelement is not found, then the list remains the same and false is returned. If anyduplicates exist, then the first element in the list is removed. In both versions, if anelement is successfully removed, then all elements in the position higher than theposition of the removed element will be shifted to a position one index lower; thatis, elements at position i will be shifted to position i � 1. Figure 18.8 illustrates bothtypes of removal operations.

The set operation replaces the element at the designated position with thegiven element. If the operation is successful, then the operation returns the elementpreviously stored in the designated position. If the designated position is outside ofa valid range, then an index out-of-bound exception is thrown. Figure 18.9 illus-trates the set operations.

The size operation returns the size of the list. Figure 18.10 illustrates the sizeoperation.

18.1 The List ADT 987

Figure 18.6 Sample indexOf operations on the myList list.

No structuralchange to the list

No structuralchange to the list

returnsNOT_FOUND (�1)indexOf("gnu")

returns2indexOf("dog")

Before "cat"0

"ape"1

"dog"2

"bee"3

myList

After "cat"0

"ape"1

"dog"2

"bee"3

myList

Before "cat"0

"ape"1

"dog"2

"bee"3

myList

After "cat"0

"ape"1

"dog"2

"bee"3

myList

set

size

wu23399_ch18.qxd 1/2/07 20:37 Page 987

Page 8: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

18.2 The List InterfaceWe will use a Java interface to define the List ADT. To avoid confusion with thejava.util classes, we will prefix the name of the interfaces and classes we define herewith NPS (NPS stands for the author’s affiliation, Naval Postgraduate School, inMonterey, California). In the NPSList interface definition, we use the generics featureintroduced in Chapter 17. Formalizing what we have presented in Section 18.1, wehave the following definition, and Table 18.1 summarizes the methods:

988 Chapter 18 List ADT

Figure 18.7 Sample isEmpty operations on the myList list.

No structuralchange to the list

No structuralchange to the list

myList

myList

returnsfalseisEmpty( )

returnstrueisEmpty( )

Before "cat"0

"ape"1

"dog"2

"bee"3

myList

After

Before

After

"cat"0

"ape"1

"dog"2

"bee"3

myList

NPSList

package edu.nps.util;

interface NPSList<E> {

public void add(E item);

public void add(int index, E item) throws IndexOutOfBoundsException;

wu23399_ch18.qxd 1/2/07 20:37 Page 988

Page 9: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

18.2 The List Interface 989

Figure 18.8 Sample remove operations on the myList list.

remove(1)returns

gnu

returnstrueremove(“gnu”)

Before "cat"0

"gnu"1

"ape"2 3

"bee"4

myList

After "cat"0

"ape"1

"dog"2

"bee"3

myList

Before

After "cat"0

"ape"1

"dog"2

"bee"3

myList

"dog"

"cat"0

"gnu"1

"ape"2 3

"bee"4

myList

"dog"

public void clear( );

public boolean contains(E item);

public E get(int index) throws IndexOutOfBoundsException;

public int indexOf(E item);

public boolean isEmpty( );

public E remove(int index)throws IndexOutOfBoundsException;

public boolean remove(E item);

public E set(int index, E item) throws IndexOutOfBoundsException;

public int size( );}

wu23399_ch18.qxd 1/2/07 20:37 Page 989

Page 10: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

990 Chapter 18 List ADT

Figure 18.9 Sample set operations on the myList list.

Figure 18.10 A sample size operation on the myList list.

returnsapeset(1, "fox")

No structuralchange to the list

throws<index-out-of-bounds-exception>set(4, "fox")

Before "cat"0

"ape"1

"dog"2

"bee"3

myList

After "cat"0

"fox"1

"dog"2

"bee"3

myList

Before "cat"0

"ape"1

"dog"2

"bee"3

myList

After "cat"0

"ape"1

"dog"2

"bee"3

myList

No structuralchange to the list

returns4size( )

Before "cat"0

"ape"1

"dog"2

"bee"3

myList

After "cat"0

"ape"1

"dog"2

"bee"3

myList

wu23399_ch18.qxd 1/2/07 20:37 Page 990

Page 11: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

18.2 The List Interface 991

Tab

leTable 18.1

Interface:NPSList

void add( E item )

Adds the item to the end of the list.

void add( int index, E item ) throws IndexOutOfBoundsException

Adds the item at the specified index position. If the value for index is less than 0 or larger than the size of the list, an IndexOutOfBoundsExceptionis thrown.

void clear( )

Empties the list. After the clear method is called, the method isEmpty willreturn true.

boolean contains( E item )

Returns true if the item is in the list. Otherwise, returns false. If the list isempty, the result is false.

E get( int index ) throws IndexOutOfBoundsException

Returns the item at the specified index position. Notice that the item is notremoved from the list.

int indexOf( E item )

Returns the index position of the specified item in the list.The value NOT_FOUND(-1) is returned when the item is not in the list.

boolean isEmpty( )

Returns true if the list is empty. Otherwise, returns false.

E remove( int index ) throws IndexOutOfBoundsException

Removes the item at the index position from the list. If the specified index value isless than 0 or greater than size( )-1, an IndexOutOfBoundsException isthrown.

boolean remove( E item )

Removes the item from the list and returns true. Returns false if the item isnot found.

void set( int index, E item ) throws IndexOutOfBoundsException

Replaces the item at the index position with the passed item. If the index is lessthan 0 or greater than size( ) -1, an IndexOutOfBoundsException isthrown.

int size( )

Returns the number of items in the list.

The public methods of the list interface. The identifier E is the parameterizedtype that will be replaced by the actual type such as String and Person

wu23399_ch18.qxd 1/2/07 20:37 Page 991

Page 12: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

We will define two classes—NPSArrayList and NPSLinkedList—in Sections 18.3and 18.4. A typical way to declare and create an NPSList object is as follows:

NPSList<Person> personList = new NPSArrayList<Person>( );NPSList<String> stringList = new NPSLinkedList<String>( );

The first is a (homogeneous) list of Person objects, and the second is a list of Stringobjects.

18.3 The Array Implementation of the List ADTThere are two basic approaches in implementing the List ADT—array and linked-list implementions. In this section, we will implement the list interface by usingan array. The linked-list implementation is presented in Section 18.4. For all ourimplementations, we will use the generics feature so the list members will be homo-geneous. To illustrate the list operations with concrete examples, we will use Stringobjects as list members in the following discussion. Figure 18.11 illustrates thearray implementation of a list.

The NPSArrayList ClassWe use an array to store the elements and an int variable to keep track of the num-ber of elements currently in the list. These members are declared as

private E[] element;private int count;

and initialized as

element = (E[]) new Object[DEFAULT_SIZE];count = 0;

992 Chapter 18 List ADT

myList = ( "cat", "ape", "bee", "eel" )ADT List:

ArrayImplementation:

0 1 2 3 4 n-1...

:String

"cat"

:String

"eel"

:String

"bee"

:String

"ape"

:NPSArrayList

element

count4

myList

Figure 18.11 An array implementation of the list myList.

wu23399_ch18.qxd 1/2/07 20:37 Page 992

Page 13: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

in a constructor. We assume the class constant DEFAULT_SIZE is assigned some arbi-trary integer. Notice that we first create an array of Object and then typecast it to anarray of E, the type parameter. This is necessary because it is not allowed to createan array of generic type.

Adding an element at the end of the list can be achieved very easily. We add anew element at the count position and increment the count by 1. The only compli-cation is the overflow condition. The expand method is used to handle the overflowcondition. We detect the overflow condition when the value for count is equal to thelength of the element array. Here’s the version 1 add method:

public void add(E item) {

if (count == element.length) {

expand( );}

element[count] = item;count++;

}

Instead of implementing the first add method explicitly as shown, we canimplement it by simply calling the second add method as

public void add(E item) {

add(count, item);}

because the value of count is also the index position of the next available slot in thearray, i.e., the end of the list, to add an item.

Now, let’s see how we can implement the second version of the add method.To insert an element at position i, we must shift current elements at positions i tocount-1 one position to the right to positions i+1, . . . , count, respectively. If aninvalid value is given for the position, then an index out-of-bound exception isthrown. Here’s the method:

public void add(int index, E item)throws IndexOutOfBoundsException {

checkInsertPosition(index, size());

if (count == element.length) {expand( );

}

//shift one position to the rightfor (int i = count; i > index; i--) {

element[i] = element[i-1];}

element[index] = item;count++;

}

18.3 The Array Implementation of the List ADT 993

add

See the full source code list-ing at the end of this sectionfor the expand method.

wu23399_ch18.qxd 1/2/07 20:37 Page 993

Page 14: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

The private method checkInsertPosition verifies the validity of index. If it isoutside the valid range, an IndexOutOfBoundsException is thrown. The method isdefined as follows:

private void checkInsertPosition(int index) {

if (index < 0) {

throw new IndexOutOfBoundsException("Negative index of " + index +" is invalid");

} else if (index > size()) {

throw new IndexOutOfBoundsException(index +" is larger than valid upper bound" +size());

}}

The size method returns the number of elements in the list (the method isdefined at the end of this section).

We will set element[i] to null, where i = 0, . . ., count-1, so the objects ref-erenced by element[i] will be garbage-collected. We will then reset the countvariable to 0.

public void clear( ) {

for (int i = 0; i < count; i++) {element[i] = null;

}

count = 0;}

We implement this method by using the indexOf method. If the indexOf methodreturns a value other than NOT_FOUND (-1), then the specified object is in the list, sothe contains method returns true. If the indexOf method returns NOT_FOUND, thenthe contains method returns false.

public boolean contains(E item) {

boolean result = true;

int loc = indexOf(item);

if (loc == NOT_FOUND) {result = false;

}

return result;}

994 Chapter 18 List ADT

clear

contains

NOT_FOUND is a class constant.

wu23399_ch18.qxd 1/2/07 20:37 Page 994

Page 15: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

Because we are using an array, this method is straightforward. All we have to do isto return an object at position index of the element array, after confirming that thevalue for index is valid. Here’s the method:

public E get(int index) throws IndexOutOfBoundsException {

checkAccessPosition(index);

return element[index];}

The private method checkAccessPosition ensures that the given index specifiesa valid position for accessing an element. If it is outside the valid range, anIndexOutOfBoundsException is thrown. Here’s the method:

private void checkAccessPosition(int index) {

if (size() == 0) {

throw new IndexOutOfBoundsException("Index " + index + " is invalid. List is empty.");

} else if (index < 0) {

throw new IndexOutOfBoundsException("Negative index of " + index +" is invalid");

} else if (index > size()-1) {

throw new IndexOutOfBoundsException(index +" is larger than valid upper bound" +(size()-1));

}}

This method scans the list from the beginning and stops when the first match islocated. If the specified object is not in the list, then NOT_FOUND (-1) is returned.For this method to work properly, the elements in the list must support the equalsmethod, which we will use to locate the matching element.

public int indexOf(E item) {

int loc = 0;

while (loc < count && !element[loc].equals(item)) {loc++;

}

if (loc == count) {loc = NOT_FOUND;

}

return loc;}

18.3 The Array Implementation of the List ADT 995

get

indexOf

wu23399_ch18.qxd 1/2/07 20:37 Page 995

Page 16: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

This method is also straightforward. We just check the value of the count variable.

public boolean isEmpty( ) {

return (count == 0);}

After the element at position i is removed, we must shift current elements at posi-tions i+1 to count one position to the left, to positions i, . . . , count-1, respectively.And, we decrement the count variable by 1.

public E remove(int index)throws IndexOutOfBoundsException {

checkAccessPosition(index);

E item = element[index];

//shift one position to the leftfor (int i = index; i < count; i++) {

element[i] = element[i+1];}

element[count] = null;count--;

return item;}

The second version of remove requires a routine to find the index of the item to beremoved. Once we get the index of an object to remove, we call the first removemethod to remove it. If there are any duplicates, then only the first match isremoved. If the passed item is not found, then nothing happens.

public boolean remove(E item) {

int loc = indexOf(item);

if (loc == NOT_FOUND) {

return false;

} else {

remove(loc);

return true;}

}

The set method replaces an object at the specified index position with the passedobject. If the index is invalid, an index out-of-bound error is thrown. If the

996 Chapter 18 List ADT

isEmpty

remove

set

wu23399_ch18.qxd 1/2/07 20:37 Page 996

Page 17: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

operation is successful, then the method returns the previous object in the indexposition.

public E set(int index, E item)throws IndexOutOfBoundsException {

checkAccessPosition(index);

E old = element[index];

element[index] = item;

return old;}

This method is straightforward. We simply return the value of the count variable.

public int size( ) {

return count;}

We are now ready to list the complete NPSArrayList class. In the source codelisting, we do not show any javadoc comments in order to keep the listing to a man-ageable size. The actual source code includes the full javadoc comments.

18.3 The Array Implementation of the List ADT 997

size

package edu.nps.util;

public class NPSArrayList<E> implements NPSList<E> {

public static final int DEFAULT_SIZE = 25;

public static final int NOT_FOUND = -1;

private E[] element;

private int count;

public NPSArrayList( ) {this(DEFAULT_SIZE);

}

public NPSArrayList(int size) {

if (size <= 0) {throw new IllegalArgumentException(

"Initial capacity must be positive" );}

element = (E[]) new Object[size];count = 0;

}

NPSArrayList

Constructors

wu23399_ch18.qxd 1/2/07 20:37 Page 997

Page 18: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

998 Chapter 18 List ADT

public void add(E item) {

if (count == element.length) {expand( );

}

element[count] = item;count++;

}

public void add(int index, E item) throws IndexOutOfBoundsException {

checkInsertPosition(index);

if (count == element.length) {expand( );

}

//shift one position to the rightfor (int i = count; i > index; i--) {

element[i] = element[i-1];}

element[index] = item;count++;

}

public void clear( ) {

for(int i = 0; i < count; i++) {element[i] = null;

}

count = 0;}

public boolean contains(E item) {

boolean result = true;

int loc = indexOf(item);

if (loc == NOT_FOUND) {result = false;

}

return result;}

public E get(int index) throws IndexOutOfBoundsException {

checkAccessPosition(index);

return element[index];}

add

add

clear

contains

get

wu23399_ch18.qxd 1/2/07 20:37 Page 998

Page 19: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

18.3 The Array Implementation of the List ADT 999

public int indexOf(E item) {

int loc = 0;

while (loc < count && !element[loc].equals(item)) {loc++;

}

if (loc == count) {loc = NOT_FOUND;

}

return loc;}

public boolean isEmpty( ) {

return (count == 0);}

public E remove(int index) throws IndexOutOfBoundsException {

checkAccessPosition(index);

E item = element[index];

//shift one position to the leftfor (int i = index; i < count; i++) {

element[i] = element[i+1];}

element[count] = null;count--;

return item;}

public boolean remove(E item) {

int loc = indexOf(item);

if (loc == NOT_FOUND) {

return false;

} else {

remove(loc);

return true;}

}

public E set(int index, E item) throws IndexOutOfBoundsException {

checkAccessPosition(index);

indexOf

isEmpty

remove

remove

set

wu23399_ch18.qxd 1/2/07 20:37 Page 999

Page 20: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

1000 Chapter 18 List ADT

E old = element[index];

element[index] = item;

return old;}

public int size( ) {

return count;}

private void checkAccessPosition(int index) {

if (size() == 0) {

throw new IndexOutOfBoundsException("Index " + index + " is invalid. List is empty.");

} else if (index < 0) {

throw new IndexOutOfBoundsException("Negative index of" + index +"is invalid");

} else if (index > size()-1) {

throw new IndexOutOfBoundsException(index +"is larger than valid upper bound" +(size()-1));

}}

private void checkInsertPosition(int index) {

if (index < 0) {

throw new IndexOutOfBoundsException("Negative index of " + index + " is invalid");

} else if (index > size()) {

throw new IndexOutOfBoundsException(index +" is larger than valid upper bound" + size());

}}

private void expand( ) {

//create a new array whose size is 150% of//the current arrayint newLength = (int) (1.5 * element.length);E[] temp = (E[]) new Object[newLength];

expand

size

checkAccessPosition

checkInsertPosition

wu23399_ch18.qxd 1/2/07 20:37 Page 1000

Page 21: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

18.4 The Linked-List Implementation of the List ADTWith the array implementation, a whole block of memory is allocated at once. Whenan overflow condition occurs, a new larger block of memory is allocated and thecontents of the original array are copied to the new array. The original array willeventually get garbage-collected when the data member element is set to refer to thenew array. Instead of allocating a large block of memory, the linked implementationallocates a small amount of memory that is just large enough for a single element.In general, this finer granularity of memory allocation leads to a more efficient useof memory. These points were discussed in detail in Chapter 16. In this section, wewill describe how the linked-list implementation works. Figure 18.12 illustratesthe linked implementation of a list.

18.4 The Linked-List Implementation of the List ADT 1001

//now copy the data to the new arrayfor (int i = 0; i < element.length; i++) {

temp[i] = element[i];}

//finally set the variable entry to point to the new arrayelement = temp;

}}

Figure 18.12 A linked-list implementation of the list myList.

ADT List:

Linked-ListImplementation:

myList = ( "cat", "ape", "bee", "eel" )

:NPSLinkedList

count

tail

head

:String

"cat"

:String

"ape"

:String

"bee"

:String

"eel"

myList

4

wu23399_ch18.qxd 1/2/07 20:37 Page 1001

Page 22: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

The ListNode ClassFigure 18.13 compares the array implementation and the linked implementation.With the array implementation, these references are grouped together, occupyingthe contiguous memory location. Each reference is accessed by the index valueof the array position. As detailed in Chapter 16, with the linked-list implementa-tion, they are individually allocated. Since they do not occupy any contiguousmemory locations, they must be linked to form a chain for us to be able accessthem.

We define a class named ListNode to represent the pair of references. Weoften use the term link or pointer for the second reference that points to anotherlist node. To distinguish the two different types of references, we use a bluearrow for the first reference and a red arrow for the link. Each node will be rep-resented by a single ListNode object. The ListNode class has two data members,and the class is declared as follows (the generic parameter E is declared in theNPSLinkedList class):

class ListNode {

private E item;

private ListNode next;

public ListNode(E item) {this.item = item;this.next = null;

}}

1002 Chapter 18 List ADT

Figure 18.13 The structural difference between the array and linked-list implementations.

Linked-ListImplementation:

ArrayImplementation:

0 1 2 3 4

�������

�����

�������

���

�������

���

�������

���

�������

�����

�������

���

�������

���

�������

���

wu23399_ch18.qxd 1/2/07 20:37 Page 1002

Page 23: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

The NPSLinkedList ClassSimilar to the NPSArrayList class, we need an int variable to keep track of the numberof elements currently in the list. In addition, we use two references: one points to thefirst node, and the other points to the last node. The reference to the last node allowsus to add a new node at the end of the list quickly. Without it, we have to traverse thelinks from the head to locate the last node. These data members are declared as

private ListNode head;private ListNode tail;private int count;

and initialized as

head = null;tail = null;

count = 0;

in a constructor (the actual constructor calls the clear method, which resets the listas an empty list by executing the above three statements).

Let’s start with the first version. There are two cases we need to consider whenadding an element at the end of the list. The first case involves adding an element toan empty list. Figure 18.14 illustrates this case. Both head and tail are null when thelist is empty. When a node is added to an empty list, this node is both the first andlast node of the list, so both head and tail are set to point to this newly added node.This is the end case.

18.4 The Linked-List Implementation of the List ADT 1003

Figure 18.14 Adding an element at the end of an empty list.

Before After

item

:NPSLinkedList

count

tail

head

Note: newNode is a localvariable and will be erasedwhen the method terminates.

myList

newNode

0

:NPSLinkedList

count

tail

head

myList

1

ListNode newNode = new ListNode(item);

head = newNode;

tail = newNode;

count++;

add

wu23399_ch18.qxd 1/2/07 20:37 Page 1003

Page 24: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

In the general case, where the list has one or more nodes, a newly added nodeis added at the end, so this new added node becomes the new tail node of the list.The pointer from the tail node before the addition is set to point to the new tail nodeafter the addition. Figure 18.15 illustrates the general case.

Here’s the version 1 add method:

public void add(E item) {

//creates a new ListNodeListNode newNode = new ListNode(item);

if (isEmpty()) {

head = tail = newNode;

1004 Chapter 18 List ADT

Figure 18.15 The general case of adding an element at the end of a list.

item

Before

After

1

2

1

2

:NPSLinkedList

count

tail

head

:NPSLinkedList

count

tail

head

myList

myList

newNode

k

k+1

ListNode newNode = new ListNode(item);

tail.next = newNode;

tail = newNode;

count++;

•••

•••

wu23399_ch18.qxd 1/2/07 20:37 Page 1004

Page 25: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

} else {

tail.next = newNode;tail = newNode;

}

count++;}

As was the case with the NPSArrayList class, we implemented the methodexplicitly to illustrate clearly the thinking process behind the operation, but wecan actually implement it succinctly by calling the second version as follows:

public void add(E item) {

add(count, item);}

Now, let’s see how we can implement the second version of the add method.Again, we have to handle the two cases separately. The end case occurs when the newnode is added as the first element, that is, index == 0. In this case we have to adjust thehead to point to the newly added node and the link field of this new node to point to thenode that was the first node before the addition. Figure 18.16 illustrates this case.

In the general case, we must locate the position to insert the new node as theith node. Unlike the array implementation, where we can locate an element at posi-tion i by simply using an indexed expression, in the case of linked implementationwe must traverse the pointers in the linked fields. To insert a new node as the ith nodein the list (the first node being the 0 node), we need a pointer to the i-1st node. Oncewe locate this node, the rest is a matter of adjusting two link fields. Figure 18.17illustrates the general case.

Here’s the complete definition for the second version of the add method:

public void add(int index, E item)throws IndexOutOfBoundsException {

checkInsertPosition(index);

ListNode ptr = head;

ListNode newNode = new ListNode(item);

if (index == 0) { //adding the new node as// the first node

newNode.next = head;head = newNode;

} else {for (int i = 1; i < index; i++) {

ptr = ptr.next;}

newNode.next = ptr.next;ptr.next = newNode;

}

18.4 The Linked-List Implementation of the List ADT 1005

wu23399_ch18.qxd 1/2/07 20:37 Page 1005

Page 26: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

//adjust tail if the new node added is//the last node in the listif (index == count) {

tail = newNode;}

count++;}

1006 Chapter 18 List ADT

Figure 18.16 The second version of add with index == 0, i.e., adding an element as the first node in a list.

Before

After

2

1

1

:NPSLinkedList

count

tail

head

newNode

:NPSLinkedList

count

tail

head

X

X

This is the 0th node. We mark its item X,so the before and after diagrams canbe compared easily.

item

k

k+1

myList

myList

ListNode newNode = new ListNode(item);

newNode.next = head;

head = newNode;

count++;

2•••

•••

wu23399_ch18.qxd 1/2/07 20:37 Page 1006

Page 27: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

Notice the last if statement in the method. If the newly added node is the lastnode after the insertion, then we must adjust the tail pointer. We know that thenewly added node is the last node if its index is equal to count. If the test is true,then we set tail to point to the new node.

18.4 The Linked-List Implementation of the List ADT 1007

Figure 18.17 The general case of adding a new node as the ith node.

ListNode newNode = new ListNode(item);

newNode.next = ptr.next;

ptr.next = newNode;

count++;

1

2

This is the ith node before theinsertion of the new node.

ptr points to the (i-1)st node.

2 1

This is the newith node.

Before

After

newNode

item

:NPSLinkedList

count

tail

head

X

k

myList

ptr:NPSLinkedList

count

tail

head

k�1

myList

X

•••

••••••

•••

wu23399_ch18.qxd 1/2/07 20:37 Page 1007

Page 28: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

The clear method empties the list; that is, it resets the list as an empty list. Itsimplementation is straightforward. We reset head and tail to null and count to 0. Bysetting head to null, all the nodes in the list will eventually get garbage-collected.Here’s the method:

public void clear( ) {

head = tail = null;

count = 0;}

The contains method is implemented by using the indexOf method. If theindexOf method returns a value other than NOT_FOUND (-1), then the specified ob-ject is in the list, so the contains method returns true. If the indexOf method returnsNOT_FOUND, then the contains method returns false.

public boolean contains(E item) {

boolean result = true;

int loc = indexOf(item);

if (loc == NOT_FOUND) {result = false;

}

return result;}

The get method for the linked implementation requires the traversing of linkfields to locate the desired node. After checking that the passed index value is valid,the method traverses the pointers. The traversing is essentially the same as we didfor the second version of the add method. The only difference is that we are settingthe pointer ptr to point to the index node, not to the index-1st node, as was the casewith the add method. Here’s the method:

public E get(int index) throws IndexOutOfBoundsException {

checkAccessPosition(index);

E item = null;

ListNode ptr = head;

for (int i = 0; i < index; i++) {ptr = ptr.next;

}

item = ptr.item;

return item;}

1008 Chapter 18 List ADT

contains

get

clear

This loop traversesthe list by followingthe link field forindex times.

wu23399_ch18.qxd 1/2/07 20:37 Page 1008

Page 29: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

18.4 The Linked-List Implementation of the List ADT 1009

indexOf

INVALID

isEmpty

remove

The indexOf method traverses the pointers from head and stops when the firstmatch is located. The counter loc is incremented every time the next node is visited.If the specified object is not in the list, then NOT_FOUND (-1) is returned.

public int indexOf(E item) {

int loc = 0;

ListNode ptr = head;

while (loc < count && !ptr.item.equals(item)) {loc++;ptr = ptr.next;

}

if (loc == count) {loc = NOT_FOUND;

}

return loc;}

Be careful that the order of operands in the while test is critical. We cannot writeit as

while (!ptr.item.equals(item) && loc < count) {

because doing so would result in a NullPointerException error in the casewhere the searched item is not found (i.e., when loc becomes equal to count, ptris null).

The isEmpty method is simple. We just check the value of the count variable.

public boolean isEmpty( ) {

return (count == 0);}

For the first version of remove, we must locate the i-1st node. Once this node islocated, all that is left to do is to adjust this node’s next field. Unlike in the arrayimplementation, no shifting is necessary. This is one advantage of the linkedimplementation. On the other hand, with the array implementation, there’s nosearch is involved, while the linked implemention requires the traversal of linksto locate the i-1st node. Figure 18.18 illustrates the operation for the general case.There are end cases we need to watch out for: First, when the node we areremoving is the last node in the list, we must adjust the tail pointer to point tothe new last node after the removal. Second, when the node we are removing isthe first node, then we must adjust the head pointer. If this first node is the onlynode in the list, then we must also adjust the tail pointer. If we are removing the

wu23399_ch18.qxd 1/2/07 20:37 Page 1009

Page 30: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

only node in the list (both head and tail point to this node), the net result is thatboth head and tail become null.

public E remove(int index)throws IndexOutOfBoundsException {

checkAccessPosition(index);

ListNode deleteNode;

ListNode ptr = head;

if (index == 0) { //removing the first node

deleteNode = ptr;

head = head.next;

1010 Chapter 18 List ADT

Figure 18.18 The first version of the remove operation. Remove the ith node given the value i.

1

This is the ith nodewe‘re deleting.

ptr points to the (i-1)st node.

1

Before

After

:NPSLinkedList

count

tail

head

X

k

myList

ptr:NPSLinkedList

count

tail

head

X

k

myList

ptr.next = ptr.next.next;

count--;

••••••

••••••

wu23399_ch18.qxd 1/2/07 20:37 Page 1010

Page 31: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

if (head == null) { //the first node is//the only node

tail = null;}

} else {

for (int i = 1; i < index; i++) {ptr = ptr.next;

}

deleteNode = ptr.next;

ptr.next = deleteNode.next;

if (ptr.next == null) { //very last node was removedtail = ptr; //we have a new last node

}}

count--;

return deleteNode.item;}

The second version of remove requires a traversal to locate the node to beremoved. If there are duplicates, then the first match is removed. If the passed itemis not found, then nothing happens. To locate the desired node, we use two pointers:ptr and trail. The ptr will point to the node to be removed, and the trail will point tothe node one before the ptr node. In other words, the following relationship holdsbetween the two:

trail.next == ptr

As with the first version, we must watch out for the end cases of removing the firstnode, the last node, or the only node. Here’s the second remove method:

public boolean remove(E item) {

boolean result = false;

ListNode ptr = head;ListNode trail = null;

while (ptr != null && !ptr.item.equals(item)) {

trail = ptr;ptr = ptr.next;

}

if (ptr != null) { //found item

if (trail == null) { //removing the first node

head = head.next;

18.4 The Linked-List Implementation of the List ADT 1011

wu23399_ch18.qxd 1/2/07 20:37 Page 1011

Page 32: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

if (head == null) { //the first node is//the only node

tail = null;}

} else {

trail.next = ptr.next;

if (trail.next == null) { //very last node wastail = trail; //removed, so set tail to

//point to a new last node}

}

count--;

result=true;}

return result;}

After checking that the passed index value is valid, the set method traverses the listindex times and sets the pointer ptr to the node to be modified. Once this node islocated, its data field is set to refer to the passed item.

public E set(int index, E item) {

checkAccessPosition(index);

ListNode ptr = head;

for (int i = 0; i < index; i++) {ptr = ptr.next;

}

E old = ptr.item;

ptr.item = item;

return old;}

This method is easy (for a change). We simply return the value of the countvariable.

public int size( ) {

return count;}

1012 Chapter 18 List ADT

set

size

wu23399_ch18.qxd 1/2/07 20:37 Page 1012

Page 33: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

We are now ready to list the complete NPSLinkedList class. In the source codelisting, we do not show any javadoc comments, to keep the listing to a manageablesize. The actual source code includes the full javadoc comments.

18.4 The Linked-List Implementation of the List ADT 1013

package edu.nps.util;

public class NPSLinkedList<E> implements NPSList<E> {

public static final int NOT_FOUND = -1;

private ListNode head;

private ListNode tail;

private int count;

public NPSLinkedList( ) {

clear( );}

public void add(E item) {

//creates a new ListNodeListNode newNode = new ListNode(item);

if (count == 0) {

head = tail = newNode;

} else {

tail.next = newNode;tail = newNode;

}

count++;}

public void add(int index, E item) throws IndexOutOfBoundsException {

checkInsertPosition(index);

ListNode ptr = head;

ListNode newNode = new ListNode(item);

if (index == 0) { //adding the new node as the first node

newNode.next = head;head = newNode;

} else {

NPSLinkedList

Constructor

add

add

wu23399_ch18.qxd 1/2/07 20:37 Page 1013

Page 34: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

1014 Chapter 18 List ADT

for (int i = 1; i < index; i++) {ptr = ptr.next;

}

newNode.next = ptr.next;ptr.next = newNode;

}

//adjust tail if the new node added is//the last node in the listif (index == count) {

tail = newNode;}

count++;}

public void clear( ) {

head = tail = null;

count = 0;}

public boolean contains(E item) {

boolean result = true;

int loc = indexOf(item);

if (loc == NOT_FOUND) {result = false;

}

return result;}

public E get(int index) throws IndexOutOfBoundsException {

checkAccessPosition(index);

E item = null;

ListNode ptr = head;

for (int i = 0; i < index; i++) {ptr = ptr.next;

}

item = ptr.item;

return item;}

public int indexOf(E item) {

int loc = 0;

clear

contains

get

indexOf

wu23399_ch18.qxd 1/2/07 20:37 Page 1014

Page 35: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

18.4 The Linked-List Implementation of the List ADT 1015

ListNode ptr = head;

while (loc < count && !ptr.item.equals(item)) {

loc++;ptr = ptr.next;

}

if (loc == count) {loc = NOT_FOUND;

}

return loc;}

public boolean isEmpty( ) {

return (count == 0);}

public E remove(int index) throws IndexOutOfBoundsException {

checkAccessPosition(index);

ListNode deleteNode;

ListNode ptr = head;

if (index == 0) { //removing the first node

deleteNode = ptr;

head = head.next;

if (head == null) { //the first node is the only nodetail = null;

}

} else {

for (int i = 1; i < index; i++) {ptr = ptr.next;

}

deleteNode = ptr.next;

ptr.next = deleteNode.next;

if (ptr.next == null) { //very last node was removedtail = ptr; //we have a new last node

}}

count--;

return deleteNode.item;}

isEmpty

remove

wu23399_ch18.qxd 1/2/07 20:37 Page 1015

Page 36: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

1016 Chapter 18 List ADT

public boolean remove(E item) {

boolean result = false;

ListNode ptr = head;ListNode trail = null;

while (ptr != null && !ptr.item.equals(item)) {

trail = ptr;ptr = ptr.next;

}

if (ptr != null) { //found item

if (trail == null) { //removing the first node

head = head.next;

if (head == null) { //the first node is the only nodetail = null;

}

} else {

trail.next = ptr.next;

if (trail.next == null) { //very last node was removed, sotail = trail; //set tail to point to a new

last node}

}

count--;

result = true;}

return result;}

public E set(int index, E item) {

checkAcessPosition(index);

ListNode ptr = head;

for (int i = 0; i < index; i++) {ptr = ptr.next;

}

E old = ptr.item;

ptr.item = item;

return old;}

remove

set

wu23399_ch18.qxd 1/2/07 20:37 Page 1016

Page 37: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

18.4 The Linked-List Implementation of the List ADT 1017

public int size( ) {

return count;}

private void checkAccessPosition(int index) {

if (size() == 0) {

throw new IndexOutOfBoundsException("Index " + index + " is invalid. List is empty.");

} else if (index < 0) {

throw new IndexOutOfBoundsException("Negative index of " + index +" is invalid");

} else if (index > size()-1) {

throw new IndexOutOfBoundsException(index +" is larger than valid upper bound" +(size()-1));

}}

private void checkInsertPosition(int index) {

if (index < 0) {

throw new IndexOutOfBoundsException("Negative index of " + index + " is invalid");

} else if (index > size()) {

throw new IndexOutOfBoundsException(index +" is larger than valid upper bound" + size());

}}

// Inner Class: ListNode

class ListNode {

private E item;

private ListNode next;

public ListNode(E item) {this.item = item;this.next = null;

}}

}

size

checkAccessPosition

checkInsertPosition

ListNode

wu23399_ch18.qxd 1/2/07 20:37 Page 1017

Page 38: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

1018 Chapter 18 List ADT

end cases

Figure 18.19 Sample linked lists with the head node.

An empty list

A list with four items

:NPSLinkedList

count

tail

head

:NPSLinkedList

count

tail

head

myList

myList

0

4:String

"cat"

:String

"ape"

:String

"bee"

:String

"eel"

This is the head node. Itcontains no information.

18.5 The Linked Implementation with the Head NodeIn both versions of the add and remove methods of the linked implementation, wehave to include a test to determine the special case of removing the first nodebecause we need to treat the removal of the first node differently from the othergeneral cases. The special cases are also called end cases or boundary cases.Consider the case of removal: If we are dealing with a large list, we do not expectthe removal of the first node to happen frequently in ordinary applications. Yet,every time we remove a node we must test if it is the removal of the first node. It isnot efficient to check every time for something that rarely occurs. Can we do some-thing about it? Is there a way to eliminate this testing?

The technique we can use to eliminate the testing of the end case is to insertone extra “dummy” node at the head of a list. By including this head node, one setof code can be used to handle both the end and general cases. Figure 18.19 showsthe lists with the head node.

wu23399_ch18.qxd 1/2/07 20:37 Page 1018

Page 39: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

18.5 The Linked Implementation with the Head Node 1019

With the head node in a list, version 1 remove can be written as follows:

public E remove(int index)throws IndexOutOfBoundsException {

checkAccessPosition(index);

ListNode deleteNode;

ListNode trail = head;

for (int i = 0; i <= index; i++) {trail = trail.next;

}

deleteNode = trail.next;trail.next = deleteNode.next;

if (deleteNode.next == null) { //very last node wastail = trail; //removed so set tail

//to the new last node}

count--;

return deleteNode.item;}

Compare this remove to the corresponding method of the NPSLinkedList class. Theother remove method and the two versions of the add method can be improved in asimilar manner. Here is the NPSLinkedListWithHeader class (the methods thatremain the same as those in NPSLinkedList are not listed here).

NPSLinkedListWithHeader

package edu.nps.util;

public class NPSLinkedListWithHeader<E> implements NPSList<E> {

public static final int NOT_FOUND = -1;

private ListNode head;

private ListNode tail;

private int count;

public NPSLinkedListWithHeader( ) {

ListNode headNode = new ListNode(null);

head = headNode;tail = headNode;

count = 0;}

Note:The methods that remain the sameas those in NPSLinkedList are notlisted here.

Constructor

wu23399_ch18.qxd 1/2/07 20:37 Page 1019

Page 40: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

1020 Chapter 18 List ADT

public void add(E item) {

//creates a new ListNodeListNode newNode = new ListNode(item);

tail.next = newNode;tail = newNode;

count++;}

public void add(int index, E item) throws IndexOutOfBoundsException {

checkInsertPosition(index);

ListNode ptr = head;

ListNode newNode = new ListNode(item);

for (int i = 0; i < index; i++) {ptr = ptr.next;

}

newNode.next = ptr.next;ptr.next = newNode;

//adjust tail if the new node added is//the last node in the listif (index == count) {

tail = newNode;}

count++;}

public void clear( ) {

head.next = null; //don't remove the dummy head nodetail = head;

count = 0;}

public E get(int index) {

checkAccessPosition(index);

ListNode ptr = head.next;

for (int i = 0; i < index; i++) {ptr = ptr.next;

}

return ptr.item;}

add

add

clear

get

wu23399_ch18.qxd 1/2/07 20:37 Page 1020

Page 41: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

public int indexOf(E item) {

int loc = 0;

ListNode ptr = head.next;

while (loc < count && !ptr.item.equals(item)) {loc++;ptr = ptr.next;

}

if (loc == count) {loc = NOT_FOUND;

}

return loc;}

public E remove(int index) throws IndexOutOfBoundsException {

checkAcessPosition(index);

ListNode deleteNode;

ListNode trail = head;

for (int i = 0; i <= index; i++) {trail = trail.next;

}

deleteNode = trail.next;trail.next = deleteNode.next;

if (deleteNode.next == null) { //very last node wastail = trail; //removed so set tail

//to the new last node}

count--;

return deleteNode.item;}

public boolean remove(E item) {

boolean result = false;

ListNode ptr = head.next;ListNode trail = head;

while (ptr != null && !ptr.item.equals(item)) {

trail = ptr;ptr = ptr.next;

}

18.5 The Linked Implementation with the Head Node 1021

indexOf

remove

remove

wu23399_ch18.qxd 1/2/07 20:37 Page 1021

Page 42: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

if (ptr != null) {trail.next = ptr.next;

if (trail.next == null) { //very last node was removedtail = trail; //we have a new last node

}

Count--;

result = true;}

return result;}

public E set(int index, E item) {

checkAccessPosition(index);

ListNode ptr = head.next;

for (int i = 0; i < index; i++) {ptr = ptr.next;

}

E old = ptr.item;

ptr.item = item;

return old;}

. . .}

1022 Chapter 18 List ADT

set

18.6 The Iterator Design PatternOne of the most common operations we perform on a data structure, including thelinear list, is a traversal. Traversing a data structure means visiting, or accessing,every element in the data structure. For example, if a data structure contains Personobjects and we want to find out their average age, we have to visit every Personobject in the data structure to derive the sum of their ages and then divide the sumby the total number of elements.

Traversing a complex data structure can be complicated because there couldbe many different ways to visit elements. For a simpler data structure, such as thelinear list, however, traversal is straightforward. We visit the elements in sequence:visit the first element, the second element, and so forth. Here’s a sample code for

traversal

wu23399_ch18.qxd 1/2/07 20:37 Page 1022

Page 43: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

traversing Person objects in a list to compute their average:

NPSList<Person> personList;

//Assume personList is created and includes//Person objects; for simplicity we assume//the list includes at least one element

double ageSum, avgAge;

ageSum = 0;

for (int i = 0; i < personList.size(); i++) {

Person p = personList.get(i);

ageSum += p.getAge();}

avgAge = ageSum / personList.size();

What would be the cost of such a traversal operation? It depends on the imple-mentation. With the array implementation, the cost of accessing every element in thelist is N, but with the linked-list implementation, the cost is (N2 � N)�2. Let’s see whythere is such an order-of-magnitude difference. The cost of the get method in thearray implementation is the same regardless of the location of an element, becauseany element in an array can be accessed by applying the same address computationformula. How about the get method of the linked implementation? To access the ithelement, we must traverse the links i times, starting from the head node, so the costis i. Assuming that the cost of following a link and the cost of address computationare the same, we can derive the total cost for scanning as follows: �

N

i�1

1� N for the

array implementation and �N

i�1

i � (N2 � N)�2 for the linked implementation.

Since traversal is a frequently used operation, it is worth the effort to improveits performance. We would like to improve the performance of the linked-listimplementation to the level of the array implementation, that is, from (N2 � N)�2 toN. We can do so by applying the technique known as the iterator design pattern. Aniterator is a design pattern that supports a consistent way to access the elementsstored in a data structure. We define an iterator as an ADT that supports two opera-tions—the first to prompt if there are more elements to visit and the second toretrieve the next element to visit. Here’s the interface definition for the ADT:

18.6 The Iterator Design Pattern 1023

package edu.nps.util;

interface NPSIterator<E> {

public boolean hasNext( );

public E next( ) throws NPSNoSuchElementException;}

NPSIterator

iterator

wu23399_ch18.qxd 1/2/07 20:37 Page 1023

Page 44: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

The hasNext method returns true if there are more elements in the iterator. Thenext method returns the next object in the iterator if there is one. Otherwise, itthrows an NPSNoSuchElementException. This exception class is patterned after theNoSuchElementException class in the java.util package. We avoid using classes andinterfaces from the java.util package in our edu.nps.util package to make it self-contained. We do not want to require client programmers to import the java.utilpackage also when using the edu.nps.util package.

We add a method, named iterator, to the NPSList interface that returns aniterator. With the iterator method, we can compute the average age of Person objectsin a list as follows:

NPSList<Person> personList;

//Assume personList is created and includes//Person objects; for simplicity we assume//the list includes at least one element

double ageSum, avgAge;

ageSum = 0;

NPSIterator itr = personList.iterator();

while (itr.hasNext()) {

Person p = itr.next();

ageSum += p.getAge();}

avgAge = ageSum / personList.size();

Let’s first modify the NPSLinkedList class to include the iterator method.Notice that NPSIterator is an interface, so the iterator method must return aninstance of a class that implements this interface. The best way to achieve this isto define an inner class that implements the NPSIterator interface inside theNPSLinkedList class. In this inner class, we keep a data member current that keepstrack of the node whose item value we return when the next method is called.Every time the next method is called, we update the current pointer to the next nodein the list. When the next method is called and the current points to the last nodein the list, the updated current becomes null, and the next time the hasNextmethod is called, it returns false.

Here’s how we define the modified class:

1024 Chapter 18 List ADT

NPSLinkedList (final version)

package edu.nps.util;

public class NPSLinkedList<E> implements NPSList<E> {

...

wu23399_ch18.qxd 1/2/07 20:37 Page 1024

Page 45: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

Notice that the type parameter is not specified for the inner class MyIterator.It is invalid to declare the inner class as

private class MyIterator<E> implements NPSIterator<E> {

Doing so would conflict with the type parameter of the outer class NPSLinkedList.With this invalid declaration, E in the inner class and E in the outer class would beviewed as referring to two different actual types. By not associating any type para-meter to MyIterator, the generic type E in the inner and outer classes refers to thesame actual type.

18.6 The Iterator Design Pattern 1025

public NPSIterator iterator( ) {

return new MyIterator(head);}

...

//-----Inner Class: MyIterator -------------//private class MyIterator implements NPSIterator<E> {

private ListNode current;

public MyIterator(ListNode node) {

current = node;}

public boolean hasNext( ) {

return current != null;}

public E next( ) throws NPSNoSuchElementException {

if (current == null) {throw new NPSNoSuchElementException("No more element");

}

Object item = current.item;

current = current.next;

return item;}

}}

INVALID

wu23399_ch18.qxd 1/2/07 20:37 Page 1025

Page 46: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

The NPSNoSuchElementException class is a very simple class. Here’s thedefinition:

1026 Chapter 18 List ADT

package edu.nps.util;

public class NPSNoSuchElementException extends RuntimeException {

public NPSNoSuchElementException( ) {

this("Requested element does not exist in the data structure");}

public NPSNoSuchElementException(String message) {

super(message);}

}

NPSNoSuchElementException

Now let’s look at how we can implement the iterator method for theNPSArrayList class. We should realize that we are not gaining any performance im-provement in doing this, because the cost of calling the get method N times, oncefor each node in the list, to scan the elements in a list is O(N). But defining theiterator method to the NPSArrayList class gives us a consistent and easy-to-use man-ner of traversing elements in all types of diverse data structures.

We follow the same approach used in the iterator inner class of NPSLinkedList.This time, however, instead of the current pointer, we maintain an int data membercurrent that keeps track of the index of the current node. We initialize current to 0.The hasNext method returns true if the value of current is less than or equal to themaximum possible index value, i.e., the size of the list minus 1. When the nextmethod is called and the value of current is not less than the size of the list, it throwsan exception. Otherwise, the method returns the current element and incrementscurrent by 1 so it will point to the next element.

The modified NPSArrayList is defined as follows:

package edu.nps.util;

public class NPSArrayList<E> implements NPSList<E> {

...

public NPSIterator iterator( ) {

return new MyIterator(0);}

NPSArrayList (final version)

wu23399_ch18.qxd 1/2/07 20:37 Page 1026

Page 47: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

18.7 Sample Development 1027

////---------- Inner Class : MyIterator -------------////private class MyIterator implements NPSIterator<E> {

private int current;

public MyIterator( ) {current = 0;

}

public boolean hasNext( ) {

if (current < size()-1) {return true;

} else {return false;

}}

public E next( ) throws NPSNoSuchElementException {

if (current >= size()) {throw new NPSNoSuchElementException();

} else {int idx = current; //these three statements can be writtencurrent++; //succinctly in a single statement as return element[idx]; //return element[current++]

}}

}}

Sample DevelopmentFortune Cookies

Let’s write a simple application that illustrates the use of a list. The program will display afortune cookie, a short text message, when requested by the user. Since each fortunecookie is a string, we maintain a database of fortune cookies using a list ADT.

Problem Statement

Write a program that displays a fortune cookie (text message) every time the userwishes it. Repeatedly prompt the user if he or she wishes to read another fortunecookie. If the reply is yes, display it. If the reply is no, terminate the program.Assume there is a text file named fortune.txt that contains text messages. Eachline of text represents a single fortune cookie.

18.7 Sample Development

wu23399_ch18.qxd 1/2/07 20:37 Page 1027

Page 48: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

18.7 Sample Development—continued

Overall Design

Let’s begin by identifying the core objects and their tasks. First, we need an object to han-dle the user interaction. This object can serve as the top-level controller of the program.Second, we need an object to maintain a list of fortune cookies. This object will return arandom fortune cookie when requested. And third, we need an object to input fortunecookies from the designated text file.

1028 Chapter 18 List ADT

Design Document: FortuneCookie

Class PurposeFortuneCookieMain The top-level control object handles the user

interaction. This is the instantiable main class.

FortuneCookieFile This class handles the input of text messages forfortune cookies from the designated text filefortune.txt.

FortuneCookieManager This is the core class for this application. It maintainsthe database of fortune cookies.

design document

Among the several different possibilities, we will establish the class dependenciesas follows:

FortuneCookieMain FortuneCookieManager FortuneCookieFile

We will implement this program in the following three major steps:

1. Implement the FortuneCookieMain main class. Use a stubFortuneCookieManager class.

2. Implement the FortuneCookieManager main class. Use a stubFortuneCookieFile class.

3. Implement the FortuneCookieFile class and finalize the program.

We will present some design ideas for steps 1 and 3, but the actual implementa-tions are left as exercises. These two steps are straightforward, and the related topics arediscussed in previous chapters. Our focus for this sample development is step 2.

develop-ment steps

wu23399_ch18.qxd 1/2/07 20:37 Page 1028

Page 49: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

Step 1 Development: Implement the FortuneCookieMain Class

This step is left as an exercise. You may choose a simplistic console-based user interface ora GUI. In either case,you need to call a method of FortuneCookieManager to retrieve thenext fortune cookie. We can use a stub for this method. Here’s how we could define atemporary FortuneCookieManager class.

class FortuneCookieManager {

public FortuneCookieManager( ) {

}

public String nextFortune( ) {

return "Here's your fortune"; //STUB - TEMP}

}

The interaction from the main class to the manager class is limited to the creationof a manager instance and the repeated calling of the nextFortune method.

Step 2 Development: Implement the FortuneCookieManager Class

We now replace the temporary FortuneCookieManager class with the real one. The man-ager class will be assisted by the file class FortuneCookieFile in reading fortune cookies.This file class will hide all the gory details of file input. The manager class simply needs tocall the method getList to get a list of strings. Each string in the list represents a single for-tune cookie. We set NPSList as the return type of this method. We return null from themethod if there’s any problem reading a file. Here’s a sample code to retrieve a list:

NPSList list;FortuneCookieFile inputFile;

inputFile = new FortuneCookieFile();

list = inputFile.getList();

The temporary FortuneCookieFile class can be defined as follows:

import edu.nps.util.*;

public class FortuneCookieFile {

public FortuneCookieFile() {

}

public NPSList<String> getList( ) {

NPSList<String> list = new NPSArrayList<String>();

list.add("You will lead a happy life");list.add("Patience is virtue");list.add("Your talent is unbounded and will be" +

" rewarded with happiness");

18.7 Sample Development 1029

Step 2 Design

wu23399_ch18.qxd 1/2/07 20:37 Page 1029

Page 50: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

18.7 Sample Development—continued

list.add("You will live to a ripe old age.");list.add("You will graduate with distinction");

return list;}

}

Implementation of the FortuneCookieManager class is remarkably simple, thanksto the use of a list. All the hard work is taken care of by the list. We just need one methodthat returns a fortune cookie and a constructor. Here’s the design document:

1030 Chapter 18 List ADT

Design Document: The FortuneCookieManager Class

Method Visibility Purpose<constructor> public Creates and initializes the data members.

Throws an IOException when thefortune cookie list cannot be created. Thishappens, for example, when the specifiedfile is not found or is corrupted.

nextFortune public Returns a randomly selected fortune cookiefrom the list.

Here’s the full code listing:

import java.io.IOException;import java.util.Random;import edu.nps.util.NPSList;

public class FortuneCookieManager {

private NPSList<String> fortunes;

private Random random;

private int listSize;

public FortuneCookieManager( ) throws IOException {

FortuneCookieFile fortuneFile = new FortuneCookieFile();fortunes = fortuneFile.getList();

if (fortunes == null) {throw new IOException();

}

FortuneCookieManager

step 2 code

wu23399_ch18.qxd 1/2/07 20:37 Page 1030

Page 51: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

We run the same main class from step 1 with the fully implemented FortuneCookie-Manager class and confirm that the random fortune cookies are displayed beforeproceeding to the final step.

Step 3 Development: Implement the FortuneCookieFile Class

In this final step,we implement the file class that handles the input of fortune cookies fromthe designated text file. This step is left as an exercise. The name of the text file is set tofortune.txt.To add flexibility to the program, we can pass the name of the text file to openwhen we create an instance of FortuneCookieFile.We also leave this option as an exercise.

Key Concepts 1031

random = new Random();

listSize = fortunes.size();}

public String nextFortune( ) {

return fortunes.get(random.nextInt(listSize));}

}

step 2 test

• An abstract data type (ADT) is a mathematical specification of a set of dataand the corresponding set of operations performed on those data.

• A list is a linearly ordered collection of elements.

• An array and a linked list are two possible implementations of a List ADT.

• The linked-list implementation with a dummy head node eliminates thetesting for the boundary cases.

• The traversal of list members is a very common operation.

• The iterator pattern supports a very efficient traversal operation.

• The use of a list ADT simplifies the program development remarkably asillustrated in the Fortune Cookies sample development.

S u m m a r y

K e y C o n c e p t s

abstract data type (ADT)

List ADT

array implementation

linked-list implementation

header node

iterator pattern

wu23399_ch18.qxd 1/2/07 20:37 Page 1031

Page 52: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

1032 Chapter 18 List ADT

E x e r c i s e s

1. Both NPSArrayList and NPSLinkedList implement the NPSList interfaceso they behave exactly the same. However, since their implementationsare different, the performances of their methods are different. Comparethe performances of their add and remove methods. Contrast theamount of time required to locate the position to add or remove the itemand the amount of time required to update the structure (shifting theitems for the array implementation and chaining of links for the linkedimplementation).

2. Suppose p1, p2, and p3 are unique instances of the Person class. What would be an output from the following code?

Person p1, p2, p3;p1 = ...;p2 = ...;p3 = ...;

NPSList list = new NPSArrayList();

list.add(p1);list.add(p2);list.add(p3);list.add(p2);

System.out.prinlnt("Size of list: " + list.size());

3. Add a new method called removeRange

public void removeRange(int fromIndex, int toIndex)

that removes elements in the index positions from fromIndex, inclusive, to toIndex, exclusive. Throw an IndexOutOfBoundsException if eitherfromIndex or toIndex is less than 0 or greater than size( ). Do nothing iffromIndex is greater than or equal to toIndex.

4. Write a method returns a union of two given lists. Assume the two listscontain String objects. There are no duplicates in each of the two input lists.If the two input lists are, for example,

("one", "two", "three", "four", "five")

and

("one", "five", "zero", "four", "eight")

then their union is

("one", "two", "three", "four", "five", "zero", "eight")

The method prototype is as follows:

public NPSList<String> union(NPSList<String> list1,NPSList<String> list2)

wu23399_ch18.qxd 1/2/07 20:37 Page 1032

Page 53: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

5. Repeat Exercise 4, but this time the method returns the intersection of thetwo given lists. If the two input lists are, for example,

("one", "two", "three", "four", "five")

and

("one", "five", "zero", "four", "eight")

then their intersection is

("one", "four", "five")

The method prototype is as follows:

public NPSList<String> intersect(NPSList<String> list1,NPSList<String> list2)

6. Repeat Exercise 4, but this time the method returns the difference of the twogiven lists. If the two input lists are, for example,

("one", "two", "three", "four", "five")

and

("one", "five", "zero", "four", "eight")

then their intersection is

("two", "three", "four")

The method prototype is as follows:

public NPSList<String> difference (NPSList<String> list1,NPSList<String> list2)

7. Draw a state-of-memory diagram for the list after the following code isexecuted:

NPSList<Integer> list = new NPSLinkedList<Integer>( );

Integer intObj = new Integer(10);

list.add(intObj);list.add(intObj);list.add(intObj);

8. Write a subclass of NPSLinkedList that does not allow any duplicates in thelist. Call this subclass NPSNoDupLinkedList. Elements e1 and e2 areduplicates if e1.equals(e2) is true. Implement the subclass by overriding thetwo add methods. The modified add methods disallow the insertion of aduplicate. The methods do nothing when a duplicate is passed to them.

9. Repeat Exercise 8, but this time write a subclass of NPSArrayList. Call thissubclass NPSNoDupArrayList.

10. Elements in the NPSList are unordered. Define a new interface NPSOrderedListwhere elements are ordered in ascending order. Elements we add to an

Exercises 1033

wu23399_ch18.qxd 1/2/07 20:37 Page 1033

Page 54: List ADT - Facultyfaculty.nps.edu/kmsquire/cs3901/section2/Wu_Ch16... · B/W Confirming Pages Objec tiv es After you have read and studied this chapter,you should be able to • Describe

B/W Confirming Pages

ordered list must be instances of a class that implements the Comparableinterface so they can be compared. The methods for the NPSOrderedListinterface are essentially the same as those for the NPSList interface, except forthe add method that specifies the index position of a newly added element.With the NPSOrderedList interface, there is only one add method that adds anelement to the correct position, so the resulting list is ordered. Duplicates arenot allowed in the ordered list. Throw an IllegalArgumentException when oneattempts to add a duplicate. An element e1 is a duplicate if there is an e2 in thelist such that e1.compareTo(e2) == 0. Define only the interface in this exercise.You will be asked to implement the interface in Exercises 11 and 12.

11. Implement the NPSOrderedList interface (see Exercise 10) by using an array.Name this class NPSOrderedArrayList.

12. Implement the NPSOrderedList interface (see Exercise 10) by using a linkedlist. Name this class NPSOrderedLinkedList.

13. The Iterator interface we presented in the chapter allows you to move in onedirection. Define a new interface called TwoWayIterator that allows you tomove both forward and backward. When you try to go beyond the first orthe last element, throw an NPSNoSuchElementException. You only need todefine the interface here. You will define classes that implement this interfacein the next two exercises. (Note: This TwoWayIterator interface is inspired bythe ListIterator interface in the java.util package.)

14. Add an inner class that implements the TwoWayIterator interface to theNPSArrayList class.

15. Add an inner class that implements the TwoWayIterator interface to theNPSLinkedList class.

16. Implement step 1 of the fortune cookie sample development.

17. Implement step 3 of the fortune cookie sample development.

18. Modify the base implementation of the FortuneCookieFile class done inExercise 17 so the modified class can input data from any text file. The filename of the text file to open is passed as an argument to the constructor.

19. Extend the fortune cookie sample development program so that theadministrator can add and delete fortunes from the list. The administratorenters a password when the program prompts whether to display the nextfortune. This will bring the program into an administrative mode. In thismode, you can add new fortunes and delete existing fortunes. A new fortune isadded to the end of the list. You can delete existing fortunes in two ways. Withthe first way, you specify the index position of the fortune in the list. With thesecond way, the program will list all fortunes in the list one by one. For eachfortune listed, you can enter D to delete it, K to keep it, or X to stop the listing.

20. In Section 16.5, we implemented the HumongousInteger class using linkednodes. We defined the inner Node class and manipulated links ourselves.Reimplement the HumongousInteger class by using an NPSList instead. Isthere any clear benefit in using an NPSList?

1034 Chapter 18 List ADT

wu23399_ch18.qxd 1/2/07 20:37 Page 1034