7 stacksqueues
DESCRIPTION
TRANSCRIPT
7-1
Chapter 7Stacks and Queues
Data Structures and Design in Java © Rick Mercer
7-2 Stacks
A Stack Is a collection with one accessible element--the most
recent element "pushed" onto the stack. Has a Last-In, First-Out (LIFO) characteristic Used often in computer systems
maintain order of method calls (demo stack of calls) compiler matches openers { [ ( and closers ) } ] converting expressions into postfix notation
Useful in applications where a last-in-first-out characteristic makes sense to the programmer
7-3 Using a Stack Object
// Construct an empty stack using Interface in bookGenericStack stackOfInts = new ArrayStack( );
// Push three string values onto the stackstackOfInts.push( new Integer( 1 ) );stackOfInts.push( new Integer( 2 ) );stackOfInts.push( new Integer( 3 ) );
// Show each element before removed in a LIFO orderwhile( !stackOfInts.isEmpty( ) ){ // Print the value as it is removed from top of stack System.out.println( stackOfInts.pop( ) );}
7-4 You push references to objects
A reference to an Object object is pushed yes, anObject is an Object object
public void push( Object anObject ) { ... }
You can not s.push(12) or s.push('A')However you can push a reference to any
Java object including your objects
7-5 Type Conversion
You will have to convert references from Object to its proper class. The following works if stackOfInts contains only Integer objects
System.out.println( ((Integer)stackOfInts.getTop()).intValue () );
Cast Object to a Integer by preceding it with Integer within parentheses
(Integer)s.getTop() But you need an extra set of parentheses before sending
a length message ( (Integer)s.getTop() ).intValue()
7-6Cast from Object to BankAccount Stack of BankAccounts is silly
GenericStack s = new ArrayStack( );s.push( new BankAccount( "Barb", 100.00 ) ); s.push( new BankAccount( "Huey", 200.00 ) ); s.push( new BankAccount( "Zeke", 300.00 ) );
while( ! s.isEmpty() ) { // The . is highest priority, then ( ) BankAccount ref = (BankAccount)s.pop(); // Had to cast just to trick the compiler double balance = ref.getBalance( ); String ID = ref.getID( ); System.out.println( ID + " has $" + balance );}OutputZeke has $300.0Huey has $200.0Barb has $100.0
7-7 Stacks (continued)
Stack methods names: push elements onto the "top" of a stack. pop elements off the "top" of the stack isEmpty true is there are no elements getTop provides access only the top element
the most recently pushed element
Some methods throw EmptyStackException pop and getTop
7-8 Construct, push, top, pop
The memory shown to the right after executing the code on the left:ArrayStack s = new ArrayStack();
s.push("A"); // strings ok, chars not
s.push("B");
s.push("C");
What is the value of s.getTop() now?Here's what happens with: s.pop();
"B"
"C"
"A"
"B"
"A"
7-9Applications of Stacks: With Computer Languages
Imagine a compiler scanning code when you forget ) or ] or }
It's difficult to find the source of the error compilers check to see if things aren't balanced
Push opening symbols onto a stack and see if closing symbols make sense
compile a Java with several errors
Algorithm follows
7-10 Balancing Symbolsopeners [ ( { and closers ] ) }
public class A public static void main(String[ args System.out PRINTln( "Hello" ); for( int j = 0; j < 6 j++ ) j++ doub x = 0.0; inTeger j = 0; System.out.println( "Goodbye" ); }}
Java says 2 errors, but how many can you find?
A.java:1: '{' expected.A.java:12: Unbalanced parentheses
2 errors
7-11 Checks Balanced Symbols First
Java's compiler apparently first checks to see if certain symbols are balanced [] {} ()
It ignores others errors by making a run over the entire source code just looking for unbalanced symbols
If it finds none, it will begin a new pass starts reading character by character again
Fix the unbalanced errors of the previous slide one by one to observe this behavior
it probably uses a Stack and an algorithm like this
7-12Example 1: Reporting errors on unclosed symbols
1. Make an empty stack named s2. Read symbols until end of file if it's an opening symbol, push it if it is a closing symbol && s.isEmpty report error otherwise pop the stack if symbol is not a closer for pop's value, report error 3. At end of file, if !s.isEmpty, report error
Use Java code with mismatched symbols as input
7-13 Example
Process these characters, which represent only the openers and closers in a short Java program: {{([])}}
As the first four characters are read — all openers —push each onto the stack
[ ( { {
7-14Pop the first closerDo they match?
The next symbol read is a closer: ']'. Pop '[' and compare to ']'. Since they match, no error would be reported.
The stack would now look like this:
( { {
Still need to process ) } }
7-15 ( matches )
Then ' )' is found, so pop the stack Since the top symbol '(' matches the closer ')',
no error needs to be reported. The stack now has two opening curly braces
{ { Still need to process
} }
7-16Pop last two. They match. All is okay
The two remaining closing curly braces would cause the two matching openers to be popped with no errors
It is the last in first out nature of stacks that allows the first '{' to be associated with the last closer '}'.
7-17 When do errors occur?
If a closer is found and the stack is empty, you could also report an error.
For example with}}, where the opening { was not incorrectly typed, the stack has no openers.
If you process all symbols and the stack is not empty, an error should be reported,
In the case of {{([])} there is a missing right curly brace. Symbols are processed without error.
Except at the end, the stack should be empty. It is not and an error gets reported.
7-18 Implementing a Stack
Let us implement our own stack class to store a stack of primitive characters
Methods will include push pop getTop isEmpty
7-19 Implementing a stack
There are a variety of ways Don't implement it and simply use Java's Stack class Use an array instance variable will do this now
Use a linked structure this will be the quiz
Or just use LinkedList (getFront and removeFront)
First consider an array based implementation
7-20 A stack of String Objects
null
null
nullnull
null
null
null
null
null
null
my_top = -1
Construct an empty Stack
"A""B"null
null
null
null
null
null
null
null
my_top = 1
push("A")push ("B")
"A"
null
null
null
null
null
null
null
null
null
my_top = 0
pop()
null
null
null
null
null
null
null
null
nullnull
my_top = -1
pop()
[0]
[1]
[0]
[1]
[0]
[1]
[0][1][2][3]
...
[9]
7-21Implement a Stack with an array instance variable
The class has been defined, fill in the blanks public class ArrayStack { // Instance Variables private Object[] my_data; private int my_top;
/** Construct empty stack with capacity 10 */ public ArrayStack( ) { // YOU COMPLETE THIS
}
7-22 ArrayStack.push
/** Put element on "top" of this Stack object. * @param element The Object that will be * placed at the top of this stack object */ public void push( Object element ) { // YOU COMPLETE THIS
}
7-23 ArrayStack.isEmpty
/** Determine if this stack object has more * than 0 elements. * @return true if there is at least one * element in this stack object */ public boolean isEmpty( ) { // YOU COMPLETE THIS
}
7-24 ArrayStack getTop this is complete
This method check for an empty stack assume import java.util.EmptyStackException
/** @return reference to the element at the * top of this stack object */public Object getTop(){ // Throw exception if this stack is empty if( this.isEmpty() ) throw new EmptyStackException( ); // Program may have terminated already return my_data[my_top];}
7-25 ArrayStack now has Exceptions
Now, if you try to reference the top of an empty stack like this
while( !( s.isEmpty() ) ) s.pop( ); // s is now definitely empty System.out.println( s.getTop( ) ); // Exception
you will get something like this:
Exception in thread "main"java.util.EmptyStackException at ArrayStack.getTop(ArrayStack.java:31) at ArrayStack.main(Compiled Code)
7-26 ArrayStack pop
/** Remove the element from top of this stack * while returning a reference to the object * at the top of stack */public Object pop( ) throws EmptyStackException{ // YOU COMPLETE THIS
}
7-27Example 3: Evaluating postfix expressions
Stacks set up the evaluation of expressions.4 + 8 / 2 is different if evaluated left to right.
Evaluating "infix" expressions is not easy. So compilers convert what we write in infix into the
equivalent postfix expression.
The expression 2 plus 2 in postfix 2 2 +Postfix of 1-2+3*3/4 is 1 2 - 3 3 * 4 / +
7-28 Evaluating Postfix Expression
How do we evaluate these expressions?Steps for evaluating postfix expressions
Evaluate from left to right At each occurrence of an operator, apply it to the
two operands to the left and replace these three items with the single value.
// Use this stack to help on the next slides GenericStack s = new ArrayStack( );
7-29 Evaluate 3 4 - 5 3 * -
s.push( 3 ); s.push( 4 ); op2 = s.pop( ); // found operator - so popop1 = s.pop( );s.push( op1 - op2 ); 3 - 4
The stack now has one value -1 The remainder of the expression: 5 3 * -
-1
3
4
Found operand so pushFound operand so pushFound operator so pop two values, apply operand, and push the result
7-30 Continue with 5 3 * -
s.push( 5 ); s.push( 3 ); op2 = s.pop(); op1 = s.pop();s.push( op1*op2 ); 5 * 3
The Stack has 2 valuesOnly one token remains
15
5
3
-1
Found operand so pushFound operand so pushFound operator so pop two values, apply operand, and push the result
-1
7-31 Continue with -
op2 = s.pop(); // found operator -op1 = s.pop ();s.push( op1-op2 ); -1 - 15
The expression has been processed. The value at the top of the stack is the value of
the expression is -16Now evaluate 2 3 4 * 5 * -
15
-1
-16
7-32 Converting Infix to Postfix
1 + 2 * 3 ^ 4 in postfix 1 2 3 4 ^ * +Note: ^ is a symbol in some languages for exponentiation
Operators are in reverse order So we need to store them on a stack When an operand is encountered, pop higher order
operands before pushing the lower order operand
Algorithm on the next slide
7-33Part of an algorithm for creating a postfix "String"
Let postfix be a String that is "" and stack be an empty StackFor each token in the input stream {
if operand: Immediately concatenate operand to postfixif open parentheses: Push '(' on the stackif close parentheses: Pop stack symbols and attach to postfix until open
parentheses is at getTop, then pop ')'if operator: While the stack is not empty, pop all operators as long as
they are of equal or higher precedence and the top is not '('. Concatenate each operator from stack to postfix. Then push the current operator.
}Pop any remaining operators from the stack, concatenating them to the
postfix expressionNote: Left parentheses are treated as a high precedence operator on input but as a low
precedence operator when on the stack
7-34Queues: Containers with First in first out access
A Queue is another name for waiting lineEx: Submit jobs to a network printer
What gets printed first? The most recently submitted print job?
– No! that would be a stack characteristic Print the least recently submitted no priorities given
Add new print jobs at the end of the queueQueue have First In First Out (FIFO) access
to elements could we also say Last In Last Out (LILO)?
7-35 Is there a Java Queue class?
Some languages have a queue class or Queue is part of a library that works with the language
Java does not it uses class LinkedList to offer the functionality
Outline of what we'll do design an interface for Queue review the Java interface again show why array based version is difficult show an implementation with Java's LinkedList class implement the interface using a linked structure with
two external references: front and back
7-36 Designing a Queue Interface
Queues typically provide these operations enqueue adds an element at the end of the queue getFront returns a reference to the element at the front of the
queue dequeue removes the element from the front of the queue and
returns a reference to the front element isEmpty returns false if there is at least one element in the
queue
So we will accept these methods as a well-understood interface for queue
7-37 Specify the interface Already been done for us. It is well understood.
This will be an example of using an interface and alternative implementations
Something collection libraries do to allow tradeoffs between program speed and memory usage
First, design the interface capture methods with return types, parameters
The Queue interface declares that users can enqueue and dequeue any Object object or anything that extends Object which is everything except primitive values
7-38 The Queue Interface
public interface Queue{ // Add any object at the end this queue public void enqueue( Object newEl );
// Returns a reference to the object at the // front of this Q (you will need to cast) public Object getFront( );
// Remove the object from the front of this Q public Object dequeue( );
// Return true if this Q is empty public boolean isEmpty( );}
7-39Java interfaces specify the methods a class must have
A Java interface is the ultimate abstract class method headings, no implementation
An interface has these things only public method headings with ; rather than {/*...*/} public static final data fields occasionally
A class is said to implement an interface if the class implements all methods with headings as-is
public class AbtractList implements List
Interfaces don't provide any implementation no {}
7-40 Specifying an interface
An interface looks like a class Write interface instead of class There is no implementation no { }
interfaces provides interesting capabilities When a class implements an interface, it promises to
implement the methods (or it is a compiletime error) Later on, we will see that the Comparable interface
comes in very handy for generic collections It guarantees a class has the compareTo method
7-41Let SlowQueue implement the Queue interface
We need to store an array of Object objects avoids having queue of int and people and cars, and...
public class SlowQueue implements Queue { private int back; private Object[] my_data; // ...
We must now implement all methods of the Queue interface as they are written
plus a constructor with the proper name
7-42 Bad array type queue
Queue as an array could have the front of the queue is always in my_data [0]
public SlowQueue( int max ) { my_data = new Object[max]; back = -1; }
back == -1
null
my_data[0] my_data[1] my_data[2] my_data[3]my_data[0] my_data[1] my_data[2] my_data[3]
nullnull null
So far so good. An empty queue
7-43 First version of enqueue
public void enqueue( Object element ){ // This method will be changed later back++; my_data[back] = element;}
Send an enqueue message aQueue.enqueue( "a" );
So far so good. A queue of size 1
null
my_data[0] my_data[1] my_data[2] my_data[3]my_data[0] my_data[1] my_data[2] my_data[3]
null"a""a" null
back == 0
7-44 enqueue another
public void enqueue( Object element ){ // This method will be changed later back++; my_data[back] = element;}
Send two more enqueue messages aQueue.enqueue( "b" ); aQueue.enqueue( "c" );
So far so good. A Queue of size 3
"c""c"
my_data[0] my_data[1] my_data[2] my_data[3]my_data[0] my_data[1] my_data[2] my_data[3]
"b""b""a""a" null
back == 2
7-45Array Implementation of a Queue
During dequeue, slide all elements to the left when if size were 999, 998 assignments necessary
"a" "b" "c"
back
"b" "c" "c"
back
Before dequeue
After dequeue
A bad algorithm for enqueue.
null
null
7-46Effect of queue operation on an array with a "floating" front
enqueue("a")enqueue("b")enqueue("c")
dequeue()
enqueue("d")
dequeue()
"a" "b" "c" ?
front back
"a" "b" "c" ?
front back
"a" "b" "c" "d"
front back
"a" "b" "c" "d"
front back
7-47
"e"
But what happens next when back equals array.length?
enqueue("e") "a" "b" "c" "d"
front backback is at the last array indexBut this queue is not fullWhere do you place "e"?
my_data[0] is available Write code that increments back correctly even if back is
referencing the last available array index
? ________________________________ ?
7-48 The Circular Queue
"c"
"d"back
front
A "circular queue" implementation uses wraparound The queue has "c" "d" "e"
either increase back by 1 or set back to 0
"a"
"b"
"e"my_data[0]my_data[0]
enqueue("e")now works in this "circular" queue.It reuses previously used array indexes
Write the code that does this
7-49 Implementing a Circular Queue
Still have to work with arrays, not circles In order for the first and last indices to work in a
circular manner: increase by one element at a time after largest index in the array, go to zero. back = 0 1 2 3 0 1 2 3 0 1 2 3 0 ...
could contain code you just wrote on previous slide
But what is an empty queue? What values should be given to front and back when
the queue is constructed?
7-50 Problem: A full queue can not be distinguished from an empty queue
back front
empty
back front
1 in q
a
back
front
3 in q
a
bc
front
full q
a
bc
d
back
What does back == front imply? An empty queue, or a full queue?
One option is to have the constructor place back one slot before front then increment back during enqueue before storing the reference to the new element into the my_data
7-51 Corrected Circular Queue
Use this trick to distinguish between full and empty queues
The element pointed to by front never indexes the front element— the “real” front is located at nextIndex( front )
private int nextIndex( int index ) { // Return an int to indicate next position return (index + 1) % my_data.length; }
For example, use this during getFront()
return my_data[nextIndex(front)];
7-52Correct Circular Queue Implementation Illustrated
front
back
empty
backfront
1 in q
"a"
back
front
2 in q
"a"
"b"
back
full q
"a"
"b""c"
front
The front index is always 1 behind the actual frontMust waste one array element no big deal
7-53Correct Circular dequeue Implementation Illustrated
back
empty q
front
back
full q
"a"
"b""c"
front
back
2 in q
"b""c"
front
back
1 in q
"c"
front
dequeue three times to make this queue empty
Demo QueueEfficency.java
7-54Quiz: Implement a Queue class with a LinkedList instance variable
import java.util.*; // For class LinkedListpublic class LinkedListQueue implements Queue{ private LinkedList my_data; public LinkedQueue( ) { // 1.
} public void enqueue( Object element ) { // 2.
}
7-55 Implement getFront & isEmpty
public Object getFront() { // 3. Assume queue is not empty
} public boolean isEmpty( ) { // 4.
}
// 5. Completely implement dequeue
7-56 LinkedQueue
Show pictures of two choices 1) Maintain a front and back
Use a dummy first node, show this in class 2) Maintain front only
But then to enqueue, you have to traverse the entire linked structure
In class Write and test class LinkedQueue that implements the Queue
interface. Use two external references: front and back