Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
STACKS • Stacks, Queues, and Deques • ACS-2947 Lecture 4 • The Stack Abstract Data Type • The Stack ADT stores arbitrary objects • • push(e): inserts an element • pop( ): removes and returns the last inserted element E.g. • Web browsers’ recently visited sites • The “undo” feature of text editors Stack Interface in Java • Main stack operations: • A stack is a collection of objects that are inserted and removed according to the last-in, first-out (LIFO) principle. A user may insert objects into a stack at any time, but may only access or remove the most recently inserted object that remains (the “top” of the stack). Java interface corresponding to our Stack ADT • Assumes null is returned from top( ) and pop( ) when stack is empty • Different from the built-in Java class java.util.Stack Auxiliary stack operations: • object top( ): returns the last inserted element without removing it • integer size( ): returns the number of elements stored • boolean isEmpty( ): indicates whether no element is stored Example 8 6 9 7 public interface Stack<E>{ int size( ); boolean isEmpty( ); E top( ); void push (E element); E pop( ); } A Stack Interface for Java • Because of its importance, the stack data structure is included as a "built-in" class in the java.util package of Java. • We construct our own Stack ADT • Differences: If stack is empty: returns null throws exception 1 Simple Array-Based Stack Implementation Simple Array-Based Stack Implementation N-1 . . . t 2 1 0 8 6 9 7 Sample usage " Analyzing the Array-Based Stack Implementation • Each of the stack methods executes a constant number of statements involving arithmetic operations, comparisons, and assignments. • pop also calls isEmpty, which itself runs in constant time à in this implementation of the stack ADT, each method runs in constant time, or O(1) time. Garbage Collection in Java • In the pop method we set a local variable, answer, to reference the element that is being popped, and then we intentionally reset data[t] to null at line 22, before decrementing t. • Assists is Java’s garbage collection mechanism, which searches memory for objects that are no longer actively referenced and reclaims their space for future use. 2 Drawback of Array-Based Stack Implementing a Stack with a Singly Linked List • Must assume a fixed upper bound, CAPACITY, on the ultimate size of the stack. • Good for cases with a good estimate on the number of items needed to go into the stack • The linked-list approach has a memory usage that is always proportional to the number of actual elements currently in the stack • We use the adapter design pattern • • Stacks serve a vital role in a number of computing applications, so it is helpful to have a fast stack ADT implementation such as the simple arraybased implementation. The Adapter Pattern • • Implementing a Stack with a Singly Linked List Define a new class that contains an instance of the existing class as a hidden field • Applies to any context where we effectively want to modify an existing class so that its methods match those of a related, but different, class of interface Then implement each method of the new class using methods of this hidden instance variable. Creates a new class that performs some of the same functions as an existing class, but repackaged in a more convenient way. • In the context of the stack ADT, we can adapt our SinglyLinkedList class to define a new LinkedStack class • Declares a SinglyLinkedList named list as a private field, and uses the following correspondences: Implementing a Stack with a Singly Linked List head 8 6 9 7 Recall: 8 6 9 7 3 Reversing an Array with a Stack • A stack can be used as a general tool to reverse a data sequence. • Create an empty stack for auxiliary storage, push all of the array elements onto the stack, and then pop those elements off of the stack while overwriting the cells of the array from beginning to end. Reversing an Array Using a Stack D C B A a D C B A buffer A B C D a Parentheses Matching • Each opening symbol must match its corresponding closing symbol E.g. • correct: ( )(( )){([( )])} • correct: ((( )(( )){([( )])} • Parentheses: “(” and “)” • incorrect: )(( )){([( )])} • Braces: “{” and “}” • incorrect: ({[ ])} • Brackets: “[” and “]” • incorrect: ( HTML Tag Matching • For fully-correct HTML, each <name> should pair with a matching </name> 4 QUEUES • A queue is a close "cousin" of the stack, as a queue is a collection of objects that are inserted and removed according to the first-in first-out (FIFO) principle. • • E.g. • • • The Queue Abstract Data Type • The Queue ADT stores arbitrary objects • • Main queue operations: • enqueue(e): inserts elements at the end of the queue • object dequeue( ): removes and returns the element at the front of the queue object first( ): returns the element at the front without removing it • integer size( ): returns the number of elements stored • boolean isEmpty( ): indicates whether no elements are stored A Queue Interface for Java • • handling calls in a customer service centre web server responding to requests networked printer Queue Interface in Java • Java interface corresponding to our Queue ADT • Assumes null is returned from first( ) and dequeue( ) when stack is empty • java.util.Stack supports two styles for most operations Auxiliary queue operations • Elements can be inserted at any time, but only the element that has been in the queue the longest can be removed at any time. public interface Queue<E>{ int size( ); boolean isEmpty( ); void enqueue (E e); E first( ); E dequeue( ); } Example The queue data structure is also included as a "built-in" class in the java.util package of Java. We construct our own Queue ADT • Differences: 4 9 7 5 Array-Based Queue Implementation Array-Based Queue Implementation Avoid the loop B. • How to implement the dequeue operation? • Replace an element in the array with a null reference • Maintain an explicit variable f to represent the index of the element that is currently at the front of the queue • Would run in O(1) time Execute a loop to shift all other elements of the queue one cell to the left to align front with cell 0 A. • N O P Q R Results in a O(n) running time • Eventually the back of the queue would reach the end of the underlying array Array-Based Queue Implementation Use an Array Circularly C. . .. P G F L M • N O f r P N-1 Q 0 R 1 • Use an array of size N in a circular fashion • • Queue Operations We use the modulo operator (remainder in division) • • • E.g. 1%5 = 1, 2%5 = 2, 5%5 = 0, 8%5 = 3 To “advance” the front index, use Two variables keep track of the front and rear f index of the front element • r index immediately past the rear element • 2 • Like B., but the contents of the queue wrap around the end of an array as necessary Array location r is kept empty Example avail = (f + sz) % data.length; (0+2) % 6 = 2 f=0 sz = 3 E.g. N = 10, f = 7 2 • (8 + 1) % 10 = 9 • (9 + 1) % 10 = 0 à wraps around q.enqueue(7) 4 3 (7 + 1) % 10 = 8 q.enqueue(5) q.enqueue(3) 5 f = (f + 1) % N • ArrayQueue q = new ArrayQueue(5); 1 0 q.enqueue(9) q.enqueue(4) 7 3 5 q.dequeue() q.dequeue() q.enqueue(2) q.enqueue(8) 6 Example Example f = (f + 1) % data.length; (0+1) % 6 = 1 f=1 sz = 4 ArrayQueue q = new ArrayQueue(5); q.enqueue(5) avail = (f + sz) % data.length; (2+4) % 6 = 0 q.enqueue(3) 5 4 3 2 1 0 f=2 sz = 5 q.enqueue(7) 4 9 7 3 5 q.enqueue(9) 4 q.enqueue(4) 3 q.dequeue() 2 q.dequeue() 2 4 9 7 0 q.enqueue(8) q.enqueue(5) q.enqueue(3) q.enqueue(7) q.enqueue(9) q.enqueue(4) q.dequeue() q.dequeue() 1 q.enqueue(2) ArrayQueue q = new ArrayQueue(5); 8 q.enqueue(2) q.enqueue(8) Analysis A. Loop to shift elements results in O(n) B. Limited by array size C. Each of the queue methods executes a constant number of statements 7 Implementing a Queue with a Linked List • Adapt a singly linked list to implement the queue ADT • Natural orientation to align the front of the queue with the head of the list and the back of the queue with the tail • head 5 3 7 9 Remove from the head and insert at the tail Recall: 9 7 3 5 Analyzing the Efficiency of a Linked Queue • Each method of the LinkedStack class runs in O(1) time. Therefore, each method of our LinkedQueue adaptation also runs in O(1)time. • We also avoid the need to specify a maximum size for the queue, as was done in the array-based queue implementation. • Analyzing the Efficiency of a Linked Queue • Although all methods execute in constant time for both implementations, the operations involving linked lists have a large number of primitive operations per call. • • For example, adding an element to an array-based queue consists primarily of calculating an index with modular arithmetic, storing the element in the array cell, and incrementing the size counter. For a linked list, an insertion includes the instantiation and initialization of a new node, relinking an existing node to the new node, and incrementing the size counter. Because each node stores a next reference, in addition to the element reference, a linked list uses more space per element than a properly sized array of references. DEQUES: Double-Ended Queues • Supports adding at front and back of the line as well as removing from front and back of the line • E.g. Restaurant waitlist • The first person might be removed from the queue only to find that a table was not available; typically, the restaurant will reinsert the person at the first position in the queue. • It may also be that a customer at the end of the queue may grow impatient and leave the restaurant. 8 The Deque Abstract Data Type • • Main queue operations: • AddFirst(e): inserts elements at the front of the deque • AddLast(e): inserts elements at the end of the deque • removeFirst( ): removes and returns the first element of the deque • removeLast( ): removes and returns the last element of the deque Deque Interface in Java • Java interface corresponding to our Deque ADT • Auxiliary deque operations • object first( ): returns the first element without removing it • object last( ): returns the last element without removing it • integer size( ): returns the number of elements stored • boolean isEmpty( ): indicates whether no elements are stored Example Implementing a Deque • 6 8 6 Assumes null is returned from first( ) and last( ) when deque is empty public interface Deque<E>{ int size( ); boolean isEmpty( ); E first( ); E last( ); void addFirst (E e); void addLast (E e); E removeFirst( ); E removeLast( ); } Since the deque requires insertion and removal at both ends of a list, using a singly linked list to implement a deque would be inefficient. • Use a doubly linked list to implement a deque efficiently. • Inserting or removing elements at either end of a doubly linked list is straightforward to do in O(1) time • use sentinel nodes for the header and trailer 9