A list is a finite, ordered sequence of data items.
Important concept: List elements have a position.
Notation: <a0,a1,…,an−1>
What operations should we implement?
List Implementation Concepts
Our list implementation will support the concept of a
current position.
Operations will act relative to the current position.
<20,23|12,15>
List ADT (1)
// List class ADT. Generalize by using "Object" for the element type.// An alternative would be to use Java Generics.publicinterfaceList{// List class ADT// Remove all contents from the list, so it is once again emptypublicvoidclear();// Insert "it" at the current location// The client must ensure that the list's capacity is not exceededpublicbooleaninsert(Objectit);// Append "it" at the end of the list// The client must ensure that the list's capacity is not exceededpublicbooleanappend(Objectit);// Remove and return the current elementpublicObjectremove();
List ADT (2)
// Set the current position to the start of the listpublicvoidmoveToStart();// Set the current position to the end of the listpublicvoidmoveToEnd();// Move the current position one step left, no change if already at beginningpublicvoidprev();// Move the current position one step right, no change if already at endpublicvoidnext();// Return the number of elements in the listpublicintlength();
List ADT (3)
// Return the position of the current elementpublicintcurrPos();// Set the current position to "pos"publicbooleanmoveToPos(intpos);// Return true if current position is at end of the listpublicbooleanisAtEnd();// Return the current elementpublicObjectgetValue();}
// Return true if k is in list L, false otherwisestaticbooleanfind(ListL,intk){for(L.moveToStart();!L.isAtEnd();L.next())if(k==(Integer)L.getValue())returntrue;// Found kreturnfalse;// k not found}
Array-Based List Class (1)
classAListimplementsList{privateObjectlistArray[];// Array holding list elementsprivatestaticfinalintdefaultSize=10;// Default sizeprivateintmaxSize;// Maximum size of listprivateintlistSize;// Current # of list itemsprivateintcurr;// Position of current element
// Constructors// Create a new list object with maximum size "size"AList(intsize){maxSize=size;listSize=curr=0;listArray=newObject[size];// Create listArray}// Create a list with the default capacityAList(){this(defaultSize);}// Just call the other constructor
classLink{// Singly linked list node classprivateObjecte;// Value for this nodeprivateLinkn;// Point to next node in list// ConstructorsLink(Objectit,Linkinn){e=it;n=inn;}Link(Linkinn){e=null;n=inn;}Objectelement(){returne;}// Return the valueObjectsetElement(Objectit){returne=it;}// Set element valueLinknext(){returnn;}// Return next linkLinksetNext(Linkinn){returnn=inn;}// Set next link}
Here is a graphical depiction for a linked list storing five integers. The value stored in a pointer variable is indicated by an arrow "pointing" to something. A NULL pointer is indicated graphically by a diagonal slash through a pointer variable's box. The vertical line between the nodes labeled 23 and 10 indicates the current position (immediately to the right of this line).
Another problem is that we have no link to get us to the preceding node (shown in yellow). So we have no easy way to update the yellow node's next pointer.
We will illustrate using a freelist by performing a series of list operations. Let's start from an empty singly linked list and a freelist variable pointing to null.
Storing a record vs. Storing a reference to a record
Homogeneity: Allow different record types? Check and block?
Deletion: What happens to the record?
Doubly Linked Node (1)
classLink{// Doubly linked list nodeprivateObjecte;// Value for this nodeprivateLinkn;// Pointer to next node in listprivateLinkp;// Pointer to previous node// ConstructorsLink(Objectit,Linkinp,Linkinn){e=it;p=inp;n=inn;}Link(Linkinp,Linkinn){p=inp;n=inn;}// Get and set methods for the data memberspublicObjectelement(){returne;}// Return the valuepublicObjectsetElement(Objectit){returne=it;}// Set element valuepublicLinknext(){returnn;}// Return next linkpublicLinksetNext(Linknextval){returnn=nextval;}// Set next linkpublicLinkprev(){returnp;}// Return prev linkpublicLinksetPrev(Linkprevval){returnp=prevval;}// Set prev link}
Restricted form of list: Insert and remove only at front of list.
Notation:
Insert: PUSH
Remove: POP
The accessible element is called TOP.
Stack ADT
publicinterfaceStack{// Stack class ADT// Reinitialize the stack.publicvoidclear();// Push "it" onto the top of the stackpublicbooleanpush(Objectit);// Remove and return the element at the top of the stackpublicObjectpop();// Return a copy of the top elementpublicObjecttopValue();// Return the number of elements in the stackpublicintlength();}
Array-Based Stack (1)
Issues:
Which end is the top?
Where does “top” point to?
What are the costs of the operations?
Array-Based Stack (2)
classAStackimplementsStack{privateObjectstackArray[];// Array holding stackprivatestaticfinalintdefaultSize=10;privateintmaxSize;// Maximum size of stackprivateinttop;// First free position at top// ConstructorsAStack(intsize){maxSize=size;top=0;stackArray=newObject[size];// Create stackArray}AStack(){this(defaultSize);}
Linked Stack
// Linked stack implementationclassLStackimplementsStack{privateLinktop;// Pointer to first elementprivateintsize;// Number of elements// ConstructorsLStack(){top=null;size=0;}LStack(intsize){top=null;size=0;}
What are the costs of the operations?
How do space requirements compare to the array-based stack
implementation?
Queues
FIFO: First in, First Out
Restricted form of list: Insert at one end, remove from the other.
Assume that there are n elements in the queue. By analogy to the array-based list implementation, we could require that all elements of the queue be stored in the first $n$ positions of the array.
A more efficient implementation can be obtained by relaxing the requirement that all elements of the queue must be in the first $n$ positions of the array. We still require that the queue be stored be in contiguous array positions, but the contents of the queue will be permitted to drift within the array.
The "drifting queue" problem can be solved by pretending that the array is circular and so allow the queue to continue directly from the highest-numbered position in the array to the lowest-numbered position.