260 likes | 318 Views
Linked Lists, Stacks and Queues Textbook Sections 3.5 - 3.7. CMSC 341. Implementing A Linked List. To create a doubly linked list as seen below MyLinkedList class Node class LinkedListIterator class Sentinel nodes at head and tail. Empty Linked List.
E N D
CMSC 341 Lists, Stacks &Queues Linked Lists, Stacks and Queues Textbook Sections 3.5 - 3.7 CMSC 341
CMSC 341 Lists, Stacks &Queues Implementing A Linked List • To create a doubly linked list as seen below • MyLinkedList class • Node class • LinkedListIterator class • Sentinel nodes at head and tail
CMSC 341 Lists, Stacks &Queues Empty Linked List • An empty double linked list with sentinel nodes.
CMSC 341 Lists, Stacks &Queues Inner classes • Inner class objects require the construction of an outer class object before they are instantiated. • Compiler adds an implicit reference to outer class in an inner class (MyArrayList.this). • Good for when you need several inner objects to refer to exactly one outer object (as in an Iterator object).
CMSC 341 Lists, Stacks &Queues Nested classes • Considered part of the outer class, thus no issues of visibility. • Making an inner class private means that only the outer class may access the data fields within the nested class. • Is Node a prime candidate for nested or inner class? public or private?
CMSC 341 Lists, Stacks &Queues Implementation for MyLinkedList • Class declaration and nested Node class public class MyLinkedList<AnyType> implements Iterable<AnyType> { // Node is a nested class private static class Node<AnyType> { public Node( AnyType d, Node<AnyType> p, Node<AnyType> n ) { data = d; prev = p; next = n; } public AnyType data; public Node<AnyType> prev; public Node<AnyType> next; }
CMSC 341 Lists, Stacks &Queues 2. Data Fields and Accessors private int theSize; //used to help iterator detect changes in List private int modCount = 0; private Node<AnyType> beginMarker; //head node private Node<AnyType> endMarker; //tail node public int size( ){ return theSize; } public boolean isEmpty( ){ return size( ) == 0; }
CMSC 341 Lists, Stacks &Queues 3. Constructor(s) public MyLinkedList( ) { clear( ); } // Changes the size of this collection to zero. public void clear( ) { beginMarker = new Node<AnyType>( null, null,null ); endMarker = new Node<AnyType>( null, beginMarker, null ); beginMarker.next = endMarker; theSize = 0; modCount++; }
CMSC 341 Lists, Stacks &Queues 4. More Accessors and Mutators public boolean add( AnyType x ) { add( size( ), x ); return true; } public void add( int idx, AnyType x ) { addBefore( getNode( idx ), x ); } public AnyType get( int idx ) { return getNode( idx ).data; } public AnyType set( int idx, AnyType newVal ) { Node<AnyType> p = getNode( idx ); AnyType oldVal = p.data; p.data = newVal; return oldVal; } public AnyType remove( int idx ) { return remove( getNode( idx ) ); }
CMSC 341 Lists, Stacks &Queues 5. getNode Method private Node<AnyType> getNode( int idx ) { Node<AnyType> p; if( idx < 0 || idx > size( ) ) throw new IndexOutOfBoundsException( ); if( idx < size( ) / 2 ) { p = beginMarker.next; for( int i = 0; i < idx; i++ ) p = p.next; } else { p = endMarker; for( int i = size( ); i > idx; i-- ) p = p.prev; } return p; }
CMSC 341 Lists, Stacks &Queues 6. addBefore Method private void addBefore(Node<AnyType> p, AnyType x) { Node<AnyType> newNode = new Node<AnyType>( x, p.prev, p ); newNode.prev.next = newNode; p.prev = newNode; theSize++; modCount++; }
CMSC 341 Lists, Stacks &Queues 7. remove and iterator methods private AnyType remove( Node<AnyType> p ) { p.next.prev = p.prev; p.prev.next = p.next; theSize--; modCount++; return p.data; } //required by the Iterable interface public java.util.Iterator<AnyType> iterator( ) { return new LinkedListIterator( ); }
CMSC 341 Lists, Stacks &Queues 8a. LinkedListIterator class private class LinkedListIterator implements Iterator<AnyType> { private Node<AnyType> current = beginMarker.next; //used to check for modifications to List private int expectedModCount = modCount; private boolean okToRemove = false; public boolean hasNext( ) { return current != endMarker; } //continues on next slide…
CMSC 341 Lists, Stacks &Queues 8b. LinkedListIterator class public AnyType next( ) { if( modCount != expectedModCount ) throw new ConcurrentModificationException( ); if( !hasNext( ) ) throw new NoSuchElementException( ); AnyType nextItem = current.data; current = current.next; okToRemove = true; return nextItem; } //continues on next slide…
CMSC 341 Lists, Stacks &Queues 8c. LinkedListIterator class public void remove( ){ if( modCount != expectedModCount ) throw new ConcurrentModificationException( ); if( !okToRemove ) throw new IllegalStateException( ); MyLinkedList.this.remove(current.prev); okToRemove = false; ++expectedModCount; } // end of remove Method } // end of LinkedListIterator class }//end of MyLinkedList class
CMSC 341 Lists, Stacks &Queues Stacks • A restricted list where insertions and deletions can only be performed at one location, the end of the list (top). • LIFO – Last In First Out • Laundry Basket – last thing you put in is the first thing you remove • Plates – remove from the top of the stack and add to the top of the stack
CMSC 341 Lists, Stacks &Queues Stack Model Stack ADT • Basic operations are push, pop, and top
CMSC 341 Lists, Stacks &Queues Adapting Lists to Implement Stacks • Adapter Design Pattern • Allow a client to use a class whose interface is different from the one expected by the client • Do not modify client or class, write adapter class that sits between them • In this case, the List is an adapter for the Stack. The client (user) calls methods of the Stack which in turn calls appropriate List method(s).
CMSC 341 Lists, Stacks &Queues Client (Stack user) theStack.push( 10 ) Stack (adapter) theList.add(0, 10 ) ; List (adaptee) Adapter Model for Stack
CMSC 341 Lists, Stacks &Queues Queues • Restricted List • only add to head • only remove from tail • Examples • line waiting for service • jobs waiting to print • Implement as an adapter of List
CMSC 341 Lists, Stacks &Queues Queue ADT • Basic Operations are enqueue and dequeue
CMSC 341 Lists, Stacks &Queues Adapter Model for Queue Client (Queue user) theQ.enqueue( 10 ) Queue (adapter) theList.add(theList.size() -1, 10 ) List (adaptee)
CMSC 341 Lists, Stacks &Queues Circular Queue • Adapter pattern may be impractical • Overhead for creating, deleting nodes • Max size of queue is often known • A circular queue is a fixed size array • Slots in array reused after elements dequeued
CMSC 341 Lists, Stacks &Queues Circular Queue Data • A fixed size array • Control Variables • arraySize • the fixed size (capacity) of the array • currentSize • the current number of items in the queue • Initialized to 0 • front • the array index from which the next item will be dequeued. • Initialized to 0 • back • the array index last item that was enqueued • Initialized to -1
CMSC 341 Lists, Stacks &Queues Circular Queue Psuedocode • void enqueue( Object x ) { • if currentSize == arraySize, throw exception // Q is full • back = (back + 1) % arraySize; • array[ back ] = x; • ++currentSize; • } • Object dequeue( ) { • if currentSize == 0, throw exception // Q is empty • --currentSize; • Object x = array[ front ]; • front = (front + 1) % arraySize • return x; • }
CMSC 341 Lists, Stacks &Queues Circular Queue Example 0 1 2 3 4 5 Trace the contents of the array and the values of currentSize, front and back after each of the following operations. 1. enqueue( 12 ) 7. enqueue( 42 ) 2. enqueue( 17 ) 8. dequeue( ) 3. enqueue( 43 ) 9. enqueue( 33 ) 4. enqueue( 62 ) 10. enqueue( 18 ) 5. dequeue( ) 11. enqueue( 99 ) 6. dequeue( )