7-1
Chapter 7
Stacks 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 ...
7-3 Using a Stack Object
// Construct an empty stack using Interface in book
GenericStack stackOfInts = new ArrayStack( );...
7-4 You push references to objects
A reference to an Object object is pushed
yes, anObject is an Object object
public voi...
7-5 Type Conversion
You will have to convert references from Object
to its proper class. The following works if
stackOfIn...
7-6
Cast from Object to
BankAccount Stack of BankAccounts is silly
GenericStack s = new ArrayStack( );
s.push( new BankAcc...
7-7 Stacks (continued)
Stack methods names:
 push elements onto the "top" of a stack.
 pop elements off the "top" of th...
7-8 Construct, push, top, pop
The memory shown to the right after
executing the code on the left:
ArrayStack s = new Arra...
7-9
Applications of Stacks:
With Computer Languages
Imagine a compiler scanning code when you
forget ) or ] or }
It's di...
7-10 Balancing Symbols
openers [ ( { and closers ] ) }
public class A
public static void main(String[ args
System.out PRIN...
7-11 Checks Balanced Symbols First
Java's compiler apparently first checks to see
if certain symbols are balanced [] {} (...
7-12
Example 1: Reporting errors
on unclosed symbols
1. Make an empty stack named s
2. Read symbols until end of file
if i...
7-13 Example
Process these characters, which represent
only the openers and closers in a short Java
program: {{([])}}
As...
7-14
Pop the first closer
Do they match?
The next symbol read is a closer: ']'.
Pop '[' and compare to ']'.
Since they ...
7-15 ( matches )
Then ' )' is found, so pop the stack
Since the top symbol '(' matches the closer ')',
no error needs to...
7-16
Pop last two. They match.
All is okay
The two remaining closing curly braces
would cause the two matching openers to...
7-17 When do errors occur?
♦If a closer is found and the stack is empty,
you could also report an error.
− For example wit...
7-18 Implementing a Stack
Let us implement our own stack class to store
a stack of primitive characters
Methods will inc...
7-19 Implementing a stack
There are a variety of ways
 Don't implement it and simply use Java's Stack class
 Use an arr...
7-20 A stack of String Objects
null
null
null
null
null
null
null
null
null
null
my_top = -1
Construct an
empty Stack
"A"
...
7-21
Implement a Stack with an
array instance variable
The class has been defined, fill in the blanks
public class ArrayS...
7-22 ArrayStack.push
/** Put element on "top" of this Stack object.
* @param element The Object that will be
* placed at t...
7-23 ArrayStack.isEmpty
/** Determine if this stack object has more
* than 0 elements.
* @return true if there is at least...
7-24 ArrayStack getTop
this is complete
This method check for an empty stack
 assume import java.util.EmptyStackExceptio...
7-25 ArrayStack now has Exceptions
Now, if you try to reference the top of an empty
stack like this
while( !( s.isEmpty()...
7-26 ArrayStack pop
/** Remove the element from top of this stack
* while returning a reference to the object
* at the top...
7-27
Example 3:
Evaluating postfix expressions
Stacks set up the evaluation of expressions.
4 + 8 / 2 is different if eva...
7-28 Evaluating Postfix Expression
How do we evaluate these expressions?
Steps for evaluating postfix expressions
 Eval...
7-29 Evaluate 3 4 - 5 3 * -
s.push( 3 );
s.push( 4 );
op2 = s.pop( ); // found operator - so pop
op1 = s.pop( );
s.push( o...
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...
7-31 Continue with -
op2 = s.pop(); // found operator -
op1 = s.pop ();
s.push( op1-op2 );
-1 - 15
The expression has bee...
7-32 Converting Infix to Postfix
1 + 2 * 3 ^ 4 in postfix 1 2 3 4 ^ * +
Note: ^ is a symbol in some languages for exponent...
7-33
Part of an algorithm for
creating a postfix "String"
Let postfix be a String that is "" and stack be an empty Stack
F...
7-34
Queues: Containers with First
in first out access
A Queue is another name for waiting line
Ex: Submit jobs to a net...
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 lan...
7-36 Designing a Queue Interface
 Queues typically provide these operations
 enqueue adds an element at the end of the q...
7-37 Specify the interface
Already been done for us. It is well understood.
 This will be an example of using an interfac...
7-38 The Queue Interface
public interface Queue
{
// Add any object at the end this queue
public void enqueue( Object newE...
7-39
Java interfaces specify the
methods a class must have
A Java interface is the ultimate abstract class
 method headi...
7-40 Specifying an interface
An interface looks like a class
 Write interface instead of class
 There is no implementat...
7-41
Let SlowQueue implement the
Queue interface
 We need to store an array of Object objects
 avoids having queue of in...
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...
7-43 First version of enqueue
public void enqueue( Object element )
{ // This method will be changed later
back++;
my_data...
7-44 enqueue another
public void enqueue( Object element )
{ // This method will be changed later
back++;
my_data[back] = ...
7-45
Array Implementation of a
Queue
During dequeue, slide all elements to the left
when if size were 999, 998 assignment...
7-46
Effect of queue operation on an
array with a "floating" front
enqueue("a")
enqueue("b")
enqueue("c")
dequeue()
enqueu...
7-47
"e"
But what happens next when
back equals array.length?
enqueue("e") "a" "b" "c" "d"
front back
back is at the last...
7-48 The Circular Queue
"c"
"d"
back
front
A "circular queue" implementation uses
wraparound The queue has "c" "d" "e"
 ...
7-49
Implementing a Circular Queue
Still have to work with arrays, not circles
 In order for the first and last indices ...
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 ...
7-51 Corrected Circular Queue
 Use this trick to distinguish between full and
empty queues
 The element pointed to by fr...
7-52
Correct Circular Queue
Implementation Illustrated
front
back
empty
backfront
1 in q
"a"
back
front
2 in q
"a"
"b"
bac...
7-53
Correct Circular dequeue
Implementation Illustrated
back
empty q
front
back
full q
"a"
"b""c"
front
back
2 in q
"b""c...
7-54
Quiz: Implement a Queue class
with a LinkedList instance variable
import java.util.*; // For class LinkedList
public ...
7-55 Implement getFront & isEmpty
public Object getFront()
{ // 3. Assume queue is not empty
}
public boolean isEmpty( )
{...
7-56 LinkedQueue
 Show pictures of two choices
 1) Maintain a front and back
• Use a dummy first node, show this in clas...
Upcoming SlideShare
Loading in...5
×

7 stacksqueues

184

Published on

Published in: Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
184
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
8
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

7 stacksqueues

  1. 1. 7-1 Chapter 7 Stacks and Queues Data Structures and Design in Java © Rick Mercer
  2. 2. 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
  3. 3. 7-3 Using a Stack Object // Construct an empty stack using Interface in book GenericStack stackOfInts = new ArrayStack( ); // Push three string values onto the stack stackOfInts.push( new Integer( 1 ) ); stackOfInts.push( new Integer( 2 ) ); stackOfInts.push( new Integer( 3 ) ); // Show each element before removed in a LIFO order while( !stackOfInts.isEmpty( ) ) { // Print the value as it is removed from top of stack System.out.println( stackOfInts.pop( ) ); }
  4. 4. 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
  5. 5. 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()
  6. 6. 7-6 Cast 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 ); } Output Zeke has $300.0 Huey has $200.0 Barb has $100.0
  7. 7. 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
  8. 8. 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"
  9. 9. 7-9 Applications 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
  10. 10. 7-10 Balancing Symbols openers [ ( { 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
  11. 11. 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
  12. 12. 7-12 Example 1: Reporting errors on unclosed symbols 1. Make an empty stack named s 2. 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
  13. 13. 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 [ ( { {
  14. 14. 7-14 Pop the first closer Do 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 ) } }
  15. 15. 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 } }
  16. 16. 7-16 Pop 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 '}'.
  17. 17. 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.
  18. 18. 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
  19. 19. 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
  20. 20. 7-20 A stack of String Objects null null null null 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 null null my_top = -1 pop() [0] [1] [0] [1] [0] [1] [0] [1] [2] [3] ... [9]
  21. 21. 7-21 Implement 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 }
  22. 22. 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 }
  23. 23. 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 }
  24. 24. 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]; }
  25. 25. 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)
  26. 26. 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 }
  27. 27. 7-27 Example 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 / +
  28. 28. 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( );
  29. 29. 7-29 Evaluate 3 4 - 5 3 * - s.push( 3 ); s.push( 4 ); op2 = s.pop( ); // found operator - so pop op1 = 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 push Found operand so push Found operator so pop two values, apply operand, and push the result
  30. 30. 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 values Only one token remains 15 5 3 -1 Found operand so push Found operand so push Found operator so pop two values, apply operand, and push the result -1
  31. 31. 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 -16 Now evaluate 2 3 4 * 5 * - 15 -1 -16
  32. 32. 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
  33. 33. 7-33 Part of an algorithm for creating a postfix "String" Let postfix be a String that is "" and stack be an empty Stack For each token in the input stream { if operand: Immediately concatenate operand to postfix if open parentheses: Push '(' on the stack if 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 expression Note: Left parentheses are treated as a high precedence operator on input but as a low precedence operator when on the stack
  34. 34. 7-34 Queues: Containers with First in first out access A Queue is another name for waiting line Ex: 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 queue Queue have First In First Out (FIFO) access to elements could we also say Last In Last Out (LILO)?
  35. 35. 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
  36. 36. 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
  37. 37. 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
  38. 38. 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( ); }
  39. 39. 7-39 Java 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 {}
  40. 40. 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
  41. 41. 7-41 Let 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
  42. 42. 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
  43. 43. 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
  44. 44. 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
  45. 45. 7-45 Array 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
  46. 46. 7-46 Effect 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
  47. 47. 7-47 "e" But what happens next when back equals array.length? enqueue("e") "a" "b" "c" "d" front back back is at the last array index But this queue is not full Where 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 ? ________________________________ ?
  48. 48. 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
  49. 49. 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?
  50. 50. 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
  51. 51. 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)];
  52. 52. 7-52 Correct 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 front Must waste one array element no big deal
  53. 53. 7-53 Correct 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
  54. 54. 7-54 Quiz: Implement a Queue class with a LinkedList instance variable import java.util.*; // For class LinkedList public class LinkedListQueue implements Queue { private LinkedList my_data; public LinkedQueue( ) { // 1. } public void enqueue( Object element ) { // 2. }
  55. 55. 7-55 Implement getFront & isEmpty public Object getFront() { // 3. Assume queue is not empty } public boolean isEmpty( ) { // 4. } // 5. Completely implement dequeue
  56. 56. 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
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×