Stacks and Queues CSC 112 Fall 2009 009
Linear Containers
So far we have seen two types of linear containers: Arrays and LinkedLists
Linear: think Li Linear: hi k off as uniunii-dimensional, di i l an element l is preceded by one other element and followed b one other by h element, l a naturall ordering d i off access from frontfront-toto-back (0…n(0…n-1 indices)
Several differentiating g features; manyy deal with memory usage (dynamic growth, nonnoncontiguous), etc.
Goals
Discuss new container STACK General idea Relevant methods/operations
Show examples of its utility for practical problems bl Consider appropriate implementations
Ordering--Based Datastructures Ordering
Previous containers: allowed access to arbitrary positions Different costs on how to get to those positions Implementation of LL affect those costs
New linear containers: Stacks and Queues Defined by how insertions/deletions/access work than underlying implementation Specific p location of insertions and deletions impart p particular uses
Stacks Ordered list with p property: p y Insertions and deletions always occur at the same end. (HIGHLIGHT THIS POINT) INSERT
DELETE
A3 A3 A2
TOP
TOP
A2
A2
A1
A1
A1
A0
A0
A0
TOP
Stacks
4 3 2 1
New 2 New 1
Freshly Washed
Initial Group of Trays 5 4 3 2 1
New Group of Trays
6 5 4 3 2 1
New Group of Trays 6 5 4 3 2 1
New Group of Trays
Hungry Student
Queues If we have time, on Wednesday – we’ll look at Queues Also restricted linear containers Add at back, Remove at front (much like the queue at the movies)
Stack Example Real World Stack Example: Function call stack during program execution When a new function begins execution, it is placed on top of the call stack. When a function completes, it is removed from the stack and control returns to its calling function which is below it on the stack. Recursion can cause dramatic increases in height because functions aren’t returning.
readFile() ggetData() () main()
Stack Implementations
Stacks are already built into to languages you are familiar with:
Java: http://java.sun.com/j2se/1.4.2/docs/api/java/util/ http://java sun com/j2se/1 4 2/docs/api/java/util/ Stack.html
C++ standard template library (STL): http://www.sgi.com/tech/stl/stack.html http://www sgi com/tech/stl/stack html
Stack Examples Consider a railroad switching network as drawn below: Engine
Caboose
1
…N
Stack
2
3
What are possible orderings of cars one could end up with using this system?
Stack Examples Total p possible p permutations with n = 3 1
2
3
2,3,1 2 31 push 1, push 2 pop2, push 3 pop 3, pop 1 3,1,2 – Not possible Eith one moves outt first Either fi t or two has to be on top of one
2,1,3 push 1,, push 2 pop 2, pop 1 push 3, pop 3
1,2,3 push 1, 1 pop 1 push 2, pop 2 push 3, pop 3 1,3,2 push 1, pop 1 push 2, push 3 pop 3, 3 pop 2 3,2,1 push 1, 1 push 2 push 3, pop 3 pop 2, pop 1
Stack Operations Add an item to the stack (PUSH) Pl on top Place Delete an item from the stack (POP) R Remove ffrom top Read top item on stack (TOP/PEEK) Obtain value for item on top, top but don don’tt remove it Check if empty (EMPTY) See if number of entries is == 0 Check current size (SIZE) Return number of entries in stack
Stack API Stack Definition:
template class Stack { public: Stack(); ~Stack(); // copy constructor constructor, assignment op, op insertion op void push(const Type & item); Type pop(); Type top(); bool isEmpty isEmpty(); (); int size(); private: i t ?? };
Stack Implementation
Stacks need to be constructed on top of an underlying container: Use that container for data storage Restrict how the underlying container is manipulated
Options: Can we argue for one over the other? Arrays LinkedLists
Building a Stack on a LinkedList
LinkedList seems (more) appropriate No size limits using LL Head pointer provides a natural top pointer Using head pointer as top, and given Stack is accessed through top, ensures efficient adds and deletes (as this requires no traversal in LL) Can implement most Stack calls through very simple (sometimes one one--line) calls to LinkedList operations/methods
Stack API Stack Definition:
template class Stack { public: Stack(); ~Stack(); // copy constructor constructor, assignment op, op insertion op void push(const Type & item); Type pop(); Type top(); bool isEmpty isEmpty(); (); int size(); private: i t LinkedList LinkedList linkedList linkedList;; };
Stack Constructor template Stack::Stack(int Stack::Stack( int maxStackSize maxStackSize)) { // nothing to be done, declaration of LinkedList handles the setup for us }
Stack Destructor template Stack::~ Stack ype Stack() { // nothing to be done – LinkedList data destructor will be automatically called (we didn’t dynamically allocate) }
Stack Implementation template b l Stack:: bool S kT Stack::IsEmpty I E IsEmpty() () { return linkedList.isEmpty(); linkedList.isEmpty(); } template int Stack::size() { return linkedList.size(); linkedList.size(); }
Stack Implementation template void Stack::push(const yp p Type& yp x) { linkedList.insertAtFront(x); linkedList.insertAtFront (x); } template // NOTE E WE E ARE E LEAVING E Type Stack::pop() // IT UP TO THE USER TO { // USE TOP, POP CORRECTLY Type toReturn = linkedList.getDataAtIndex(0); linkedList getDataAtIndex(0); linkedList.getDataAtIndex getDataAtIndex(0); linkedList.deleteAtFront(); linkedList.deleteAtFront (); return toReturn; toReturn; } template Type yp Stack::top() yp p() { return linkedList.getDataAtIndex linkedList.getDataAtIndex(0); (0); }