# The List ADT

Document Sample

```					An Array-Based List ADT

CS 1037a – Topic 8
The List ADT
• A list is a linear structure
• Each item except the first (front, head) has a
unique predecessor
• Each item except the last (end, tail) has a
unique successor
• First item has no predecessor, and last item
has no successor
• An item within a list is specified by its position
in the list

8-2
Possible Operations on a List
List       Create an empty list
isEmpty    Determine whether the list is empty
isFull     Determine whether the list is full
getLength Return number of items in the list
insert     Add an item to the list
remove     Remove a specified item from list
retrieve   Get the list item at a specified pos’n
8-3
Why Use a List ADT?
• Often, we could just use an array
• May wish to separate what a list does from its
implementation (abstraction)
• Allows for a variety of implementations:
• Fixed versus arbitrary capacity
• Array-based versus linked lists (later in course)
• More natural to work with than an array: first
position is location 1 in a list, but at index 0 in
an array

8-4
UML Diagram for List ADT
List                          This diagram is
based on the design
-m_size: integer              decisions we’ve
-m_container                  made so far; type of
m_container, and
+isEmpty: boolean {query}
parameters and types
+isFull: boolean {query}      for insert, remove,
+getLength: integer {query}   replace and retrieve
+insert                       are not yet known;
+remove                       other attributes and
functions may be
+replace
added later
+retrieve {query}
+swap
8-5
The List ADT
• In an unordered list, relative position of
the items is not important
• Differences with an ordered List ADT:
• Items maintained in sorted order
• Insertions, deletions based on item value,
rather than position
• Must be able to compare items to
determine where they belong in the list
8-6
List ADT Design Decisions
• What kinds of items will be allowed in the list?
• What’s the underlying list implementation?
• What parameters and return types will the
operations have?
• How will we handle attempts to insert into a
full list, or remove from an empty list?
• How will we handle attempts to access an
illegal list position?

8-7
List ADT Implementation 1
• We’ll store either simple types (int, char,
etc) or pointers to simple types or to
objects
• Underlying structure is an array with a
fixed maximum size
• insert operation will return a boolean
value: true if operation is successful,
false otherwise

8-8
List ADT Implementation 1
• remove and retrieve will return the item at a
specified position; precondition: the position
must be one that currently exists in the list
• replace will change the item stored at a
specified position, and return the displaced
item; precondition: the position must be one
that currently exists in the list
• swap will change positions of 2 items stored
at 2 specified positions, precondition: the
positions must currently exist in the list    8-9
List ADT Implementation 1
• Adding an item to a list will change, at most,
the predecessor of one item and the
successor of one item
• Removing an item will change, at most, the
predecessor of one item and the successor of
one item
Add value 5 at loc 3 of the   Delete 1st item from 9,3,6,0,7
list 7,0,23,16,8,4 to get     to get 3,6,0,7; delete 3rd item
7,0,5,23,16,8,4               from this list to get 3,6,7

8-10
List.h (version 1)
const int DEFAULT_LIST = 200;
template <class Item>
class List {
public:
List(unsigned int capacity = DEFAULT_LIST);         // constructor for
// an empty list that can hold up to capacity items; if capacity
// is not supplied, the default size is used
~List( ); // destructor
bool isEmpty( ) const;
// returns true if the list is empty, and false otherwise   cont’d..
8-11
List.h (version 1)
bool isFull( ) const;
// returns true if the list is full, and false otherwise
unsigned int getLength( ) const;
// returns the number of items currently in the list
void insert (unsigned int pos, Item item);
// inserts item into the list at location pos;
// PRECONDITION: pos must be be a valid position
// and the bag should not be full
Item remove (unsigned int pos);
// removes the element at location pos from the list, and returns it;
// PRECONDITION: pos must be a valid position              cont’d...
8-12
List.h (version 1)
Item replace( int pos, Item item );
// replace the element at location pos in the list with item,
// and return the element that was displaced;
// PRECONDITION: pos must be a valid list position
Item retrieve (unsigned int pos) const;
// find the element stored at location pos in the list, and
// return it; PRECONDITION: pos must be a valid list position
void swap (unsigned int i, unsigned int j);
// swaps Item values stored in 2 specified positions
// PRECONDITION: i and j must be valid list positions
cont’d…           8-13
List.h (version 1)
private:
Item * m_container; // pointer to array to hold the list
unsigned int m_max_capacity; // maximum capacity of the list
unsigned int m_size;    // number of items currently in the list
unsigned int translate(unsigned int pos) const;
// converts a list position to the corresponding array index
};
#include “List.template”

8-14
List.template (version 1)
template <class Item>
List<Item> :: List(unsigned int capacity) {
m_max_capacity = capacity;
m_container = new Item [m_max_capacity];
m_size = 0;
}                                              // cont’d..

8-15
List.template (version 1)
template <class Item>
List<Item> :: ~List( ) {
delete [ ] m_container;
}
template <class Item>
bool List <Item> :: isEmpty( ) const {
return (m_size == 0);
}                                        // cont’d..

8-16
List.template (version 1)
template <class Item>
bool List <Item> :: isFull( ) const {
return (m_size == m_max_capacity);
}
template <class Item>
unsigned int List<Item> :: getLength( ) const {
return m_size;
}                                                 // cont’d..

8-17
List.template (version 1)
template <class Item>
void List <Item> :: insert(unsigned int pos, Item item) {
// PRECONDITION: pos must be between 1 and m_size+1
// and the bag should not be at full capacity
for (int k=m_size; k>=pos; k--)
m_container[translate(k+1)] = m_container[translate(k)];
m_container[translate(pos)] = item;
m_size++;
}                                                   // cont’d..
8-18
List.template (version 1)
template <class Item>
Item List<Item> :: remove (unsigned int pos) {
// PRECONDITION: the list is not empty,
// and pos is between 1 and m_size
Item returnValue = m_container[translate(pos)];
for (int k=pos+1; k<=m_size; k++)
m_container[translate(k-1)] = m_container[translate(k)];
m_size--;
return returnValue;
}                                                     // cont’d..
8-19
List.template (version 1)
template <class Item>
Item List<Item> :: replace( unsigned int pos, Item item ) {
// PRECONDITION: the list is not empty,
// and pos is between 1 and m_size
Item returnVal = m_container[translate(pos)];
m_container[translate(pos)] = item;
return returnVal;
}

8-20
List.template (version 1)
template <class Item>
Item List<Item> :: retrieve(unsigned int pos) const {
// PRECONDITION: the list is not empty,
// and pos is between 1 and m_size
return m_container[translate(pos)];
}
template <class Item>
unsigned int List<Item> :: translate(unsigned int pos) const {
return pos-1;
}                                 // end of List implementation
8-21
List.template (version 1)
template <class Item>
void List<Item>::swap (unsigned int i, unsigned int j) {
// PRECONDITION: indexes i and j should be within list range
if ( i==j ) return;
Item temp = m_container[translate(i)];
m_container[translate(i) ] = m_container[translate(j) ];
m_container[translate(j) ] = temp;
}

8-22
Why have replace() in the List ADT?

• Replacing a value in a given list position
can be accomplished by removing the
current value, and then inserting the
new value at the same position
• This process can be inefficient,
depending on the underlying list
implementation

8-23
Why have replace() in the List ADT?

• In our array-based list, using remove
and insert to replace a list item can be
slow:
To replace first item:
remove shifts all
following items one
place left, and insert
moves them back to
original positions

8-24
Why have replace() in the List ADT?

• replace() accomplishes the same task
without all the shifting
• Question: Why did we make replace()
return the displaced item?

8-25
Why have swap() in the List ADT?

• swap(i,j) allows to switch positions of 2 Items
without unnecessary shifting that would take
place if we used code (e.g. for List<Card> a)
Card tmp=a.remove(i); // assuming 1 <= j < i
a.insert(i-1,a.remove(j));
a.insert(j,tmp);
that achieves the same result very inefficiently

8-26
List ADT Implementation 2
• It’s possible to implement an array-
based List ADT in which the list can
become arbitrarily large
• When adding to a “full” list, replace the
underlying array with one that’s, say,
twice as big, and copy over the contents
of the original

8-27
List.h (version 2)
• Same as version 1, except that:
• Implementation of isFull will change
• Implementation of insert will change
• A private function replaceContainer that
increases the list capacity will be added
• Only the differences are shown here

8-28
Change to List.h (version 2)
// …
// in private part, add one more function immediately following
// translate:

void replaceContainer( );
// private function replaces the underlying array with one that holds
// the same values as the original, but has double the capacity

8-29
List.template (version 2)
// replace earlier implementation of isFull with:
template <class Item>
bool List<Item> :: isFull( ) const {
return false;
}
// cont’d..

8-30
List.template (version 2)
// replace earlier implementation of insert with:
template <class Item>
void List<Item> :: insert(unsigned int pos, Item item) {
// PRECONDITION: pos must be between 1 and m_size+1
if (m_size == m_max_capacity) replaceContainer( );
for (int k = m_size; k >= pos; k--)
m_container[translate(k+1)] = m_container[translate(k)];
m_container[translate(pos)] = item;
m_size++;
}                                                    // cont’d..

8-31
List.template (version 2)
template <class Item>
void List<Item> :: replaceContainer( ) {
Item * newList;
newList = new Item [2 * m_max_capacity];
for (int k = 0; k < m_size; k++ )
newList[k] = m_container[k];
m_max_capacity = 2 * m_max_capacity;
delete [ ] m_container;
m_container = newList;
}

8-32
A List-based Stack
Implementation
• We’ll now rewrite the Stack class to use
an underlying array-based list
• Advantage over just using an array: no
upper limit on the stack size
• For efficiency, the top of the stack will
always be at the highest used position
in the list

8-33
Stack.h
#define DEFAULT_STACK 20
#include “List.h”
template <class Item>
class Stack {
public:
Stack(unsigned int capacity = DEFAULT_STACK);
// construct a stack with initial capacity of capacity; if the
// user does not provide a value, the default size is used
~Stack( ); // destructor
bool isEmpty( ) const;
// returns true if stack is empty, and false otherwise cont’d..

8-34
Stack.h
bool isFull( ) const;
// returns true if stack is full, and false otherwise
unsigned int size( ) const;
// returns number of elements currently in the stack
void push( Item k );
// put k on top of the stack
Item pop( );
// Remove and return the top element from the stack;
// PRECONDITION: the stack must not be empty            cont’d..

8-35
Stack.h
Item peek( ) const;
// return the top element without modifying the stack;
// PRECONDITION: the stack must not be empty
private:
// only differences between this file and Stack.h from Topic 7
// are in this part: m_container is now a list;
// m_top and m_max_capacity are no longer needed
List<Item> m_container;
};
#include “Stack.template”                  // end of Stack.h
8-36
Stack.template
template <class Item>
Stack<Item> :: Stack(unsigned int capacity)
: m_container(capacity) { }
template <class Item>                                  m_container
must be
Stack<Item> :: ~Stack( ) { } // nothing to do here     initialized here
template <class Item>                                  in this fashion,
not inside the
bool Stack<Item> :: isEmpty( ) const {                 body of the
return m_container.isEmpty( );                     constructor

}                                        // cont’d..

8-37
Stack.template
template <class Item>
bool Stack<Item> :: isFull( ) const {
return m_container.isFull( );
}
template <class Item>
unsigned int Stack<Item> :: size( ) const {
return m_container.getLength( );
}
// cont’d..

8-38
Stack.template
template <class Item>
void Stack<Item> :: push(Item k) {
m_container.insert( size( ) + 1, k );
}
template <class Item>
Item Stack<Item> :: pop( ) {
return m_container.remove( size( ) );
}
template <class Item>
Item Stack<Item> :: peek( ) const{
return m_container.retrieve( size( ) );
}                                    // end of Stack.template   8-39
Exercises
1. Rewrite the Bag class using the same
technique we employed in the List
class (version 2) to allow the
underlying array to become arbitrarily
large
2. Rewrite the Bag class using a List
(version 2) instead of an array as the
underlying container
8-40

```
DOCUMENT INFO
Shared By:
Categories:
Stats:
 views: 15 posted: 4/6/2010 language: English pages: 40
Description: lists-template pdf
How are you planning on using Docstoc?