stacks1 of 32 stacks what are stacks? creating a stack pushing and popping testing for an empty...
TRANSCRIPT
Stacks 1 of 32
STACKS
• What are Stacks?
• Creating a Stack
• Pushing and Popping
• Testing for an Empty Stack
• Burgers!
© Pearson Education
Stacks 2 of 32
Arrays, Vectors, and Stacks
• Arrays– indexed (allows explicit access to nth item)– cannot change size dynamically– do not keep record of order in which items are
inserted
• Vectors– indexed (allows explicit access to nth item)– can grow/shrink dynamically– do not keep record of order in which items are
inserted
• Stacks– not indexed (can’t explicitly access nth item)– automatically store order of insertion (Last In First
Out)– useful for keeping track of where we’ve been, then
retracing steps (called backtracking)
• All three structures are linear
October 25, 2005
Stacks 3 of 32
Stacks
• One of the simplest ways to build a collection
• Stacks are LIFO: Last In, First Out– last item placed on Stack is first taken off
• What can we do with a Stack?– add items = Push– remove items = Pop– check to see if it’s empty
• Examples: Plate dispensers, spring-loaded coin dispensers
October 25, 2005
Stacks 4 of 32
• Plate dispensers are Stacks
• Number of plates on dispenser can vary from 0 to . . .
Stacks and Plates
1234
item to push
top of Stack
top of Stack
AFTER PUSHBEFORE PUSH
BEFORE POP AFTER POP
1234
top of Stack
1234
1234
top of Stack
popped item
October 25, 2005
Stacks 5 of 32
Execution Stacks, a real example
• Each method has an Activation Record (AR)– contains execution pointer to instruction in method
to be executed next– also contains all local variables and parameters of
method
• When methods execute and call other methods, Java uses a Stack to track these calls– when a method calls another method Java adds
the activation record of the new method to the Stack
– when new method is finished, its AR is removed from Stack and previous method is continued
AR of Method E
AR of Method D
AR of Method C
AR of Method B
AR of Method A
Top of StackA
B
C
D
E
October 25, 2005
A calls BB calls C… etc.
Stacks 6 of 32
The Stack Trace
• An all-too-familiar Stack to novice and expert programmers alike . . . the STACK TRACE!
Exception in thread “main” java.lang.NullPointerException
at wheels.users.Cursor.<init>(Cursor.java:14)
at wheels.users.UpButton.<init>(UpButton.java:36)
at wheels.users.SketchApp.<init>(SketchApp.java:30)
at wheels.users.SketchApp.main(SketchApp.java:48)
• We can read stack traces either top-down or bottom-up – at the top of the stack trace is the method that
caused a particular program to crash at runtime– below that, the method that called the method that
crashed, and so on..– in the above example, someone is trying to use a
reference that points to null in his/her Bee classconstructor
October 25, 2005
Stacks 7 of 32
Stack and Plates (1 of 2)
• What if we wanted to model a PlateDispenser using Swing?
• What does the Stack hold?– Plates: could be represented by simple ovals on
screen
• How does Stack, as particular collection, hold Plates?– sequence of linked nodes (“linear linked list”)
keep track of plates’ order
• Why not use a vector?– user shouldn’t have access to all elements in data
structure– need to enforce LIFO discipline
some object
some object
some object
Top of Stack
October 25, 2005
Stacks 8 of 32
Stack and Plates (2 of 2)
• What’s under bottom plate?– special node, analogous to metal disk at bottom of
real plate dispenser
• What can Stack do?– dispenser should let customers add (push) plates,
remove (pop) plates, and see if Stack is empty
• First thing we need to define are elements we will store in Stack– model Plates as simple ovals, using your ColorEllipse
October 25, 2005
Stacks 9 of 32
Digression: Instance Diagrams• Instance Diagram shows important
properties of specific instances and how they relate (as opposed to class diagram which shows how generic classes relate to other classes)– drawing will be the same for each instance of
class, but values will be different– useful for diagramming data structures– round rectangle represents instance, class name
on top– important relationships are connected with lines
(like class diagram)– if property is not important enough to warrant box,
value is placed next to property name (e.g., attributes)
CSMobile
Engine _engineCity _city
Color _color = red
City
String _name = “Springfield”
Engine
CSMobile
Engine _engineCity _city
Color _color = blueCity
String _name = “Warwick”
Engine
October 25, 2005
Stacks 10 of 32
Writing a Stack
• Stack consists of three parts– top of Stack (Stack itself, not node)– storage spaces within Stack (internal nodes)– bottom of Stack (bottom node)
• Top of Stack:– since items are popped and pushed only from this
end, top can simply be reference to top node in Stack
• Internal Storage Spaces (internal nodes)– store reference to ElementType instance– also store reference to next node– should be removed and added as necessary
• Bottom of Stack (bottom node):– never removed (handles operations on “empty”
Stack)– marks end of Stack
• Note: programmer using the abstraction never sees code that implements Stack methods (called the Stack “API” - Application Program Interface)
October 25, 2005
Stacks 11 of 32
Stacks: The BIG picture
• Let’s represent our description of a Stack from the last slide with an instance diagram
Stack
Node _topNode
InternalNode
ElementType _dataNode<ElementType>
_nextNode
InternalNode
ElementType _dataNode<ElementType>
_nextNode
BottomNode
data
data
October 25, 2005
Stacks 12 of 32
• Our Stack will use generics to store objects
• Stacks use generics, like vectors and arrays– specify a type (class) of object to store at runtime
Instance Variables Node<ElementType> _topNode; First node.
Methods public void push(ElementType
newData); Adds object and node.
public ElementType pop(); Removes object and node from top of Stack. public boolean isEmpty(); Returns true if Stack is empty.
Declaring Stack Class
Stack
October 25, 2005
Stacks 13 of 32
Constructing Stack
• What does Stack constructor do?– sets up instance variable _topNode– _topNode is initialized to refer to new bottom
node, the only node in new Stack
• Our Stack now looks like this:
Stack
Node<ElementType> _topNode
BottomNode
October 25, 2005
Stacks 14 of 32
Stack Code
• Let’s code what we know so far:public class Stack <ElementType> {private Node <ElementType> _topNode;
public Stack() { /** * we want to start with an empty Stack, * so we just create the bottom node. **/ _topNode = new BottomNode<ElementType>(); }
public void push(ElementType newData) {} public ElementType pop() {} public boolean isEmpty() {}}
•Node will be superclass for bottom and internal node classes
•_topNode will (polymorphically) refer to bottom node of Stack when empty, and top internal node when not
• Stack does not have to know which specific type of node _topNode refers to (i.e., whether it is internal or bottom node)– subclass of Node
October 25, 2005
Stacks 15 of 32
Node Superclass
• Superclass Node needs to define names of all messages bottom and internal nodes might need to respond to– stack delegates work to “smart” internal nodes to perform
pop, and handles push itself
• Here’s the class definition: abstract public class Node<ElementType> { // using default constructor abstract public Node<ElementType>
pop(Holder<ElementType> holder); abstract public boolean isEmpty(); }
• Node pop(Holder<ElementType> holder)– sets value of holder (we’ll talk about this more later — it
holds the popped data)– returns reference to Node which will become topmost node
so Stack can update _topNode– don’t confuse Stack’s pop with node’s pop
• boolean isEmpty()– returns false for InternalNode– returns true for BottomNode
• push is done in the Stack and the InternalNode constructor, as we’ll see in a few slides
October 25, 2005
Stacks 16 of 32
InternalNode
• Internal nodes must know how to add themselves in list when made as part of Stack’s push (makes them Smart Nodes):– store reference to next node (thereby
linking to it)– store reference to ElementType stored
at this node
• They must also know how to pop, by returning the data object and object they point to
• Lets see some code!
October 25, 2005
Stacks 17 of 32
Internal Node Cont.
public class InternalNode<ElementType> extends Node
{ private Node<ElementType> _nextNode; private ElementType _data;
public InternalNode(ElementType newData,
Node<ElementType> newNextNode) {
super(); _data = newData; _nextNode = newNextNode; }/** * The Stack’s pop() asks top node to pop
* Pop produces two values: * the data which is stored in * a holder, and the next node reference * that’s returned by the method. * The Stack then sets its _topNode * reference to the returned node. */ public Node<ElementType>
pop(Holder holder) { holder.setObject(_data); return _nextNode; }}
Stacks 18 of 32
BottomNode
public class BottomNode<ElementType> extends Node
{ public BottomNode() { super(); } public Node pop(Holder holder) { return this; }}
• pop just returns this because you cannot pop off BottomNode
• There’s nothing to put in holder because the bottom node doesn’t hold any data– we still get passed a reference to one because
that’s how it was declared in our superclass, Node
October 25, 2005
Stacks 19 of 32
Pushing an Object (1 of 6)
• push gets passed reference to object, and creates new node to hold it, putting this node on top of Stack
• Remainder of Stack then follows new node– new node’s _nextNode gets reference to former
top of Stack
public class Stack<ElementType> { . . . public void push(ElementType newData) { _topNode = new InternalNode<ElementType>(newData,
_topNode); }}
• Just one simple line of code, right? Not really. Let’s look at all it does...
October 25, 2005
Stacks 20 of 32
Pushing an Object (2 of 6)
• newData, created at prior time, is passed in:
• push instantiates new internal node. New node is passed newData to store in _data
• This node also stores as its _nextNode instance variable a link to old top of Stack, in this case a BottomNode
Stack
Node<ElementType> _topNode
InternalNode
ElementType _dataNode<ElementType>
_nextNode
BottomNode
data
newData
Stack
Node<ElementType> _topNode
BottomNode
data
newData
October 25, 2005
Stacks 21 of 32
Pushing an Object (3 of 6)
• After constructing new InternalNode, Stack updates its _topNode instance variable by assignment of a reference to the new internal node
• The new entry is now properly stored in data structure
InternalNode
ElementType _dataNode<ElementType>
_nextNode
Stack
Node<ElementType> _topNode
BottomNode
data
newData
October 25, 2005
Stacks 22 of 32
Pushing an Object (4 of 6)
• If we pushed on more entries, Stack would continue to grow:
• newData, created at prior time is passed into push
Stack
Node<ElementNode> _topNode
InternalNode
ElementType_dataNode<ElementType>
_nextNode
BottomNode
data
newData
data
first entry pushed
October 25, 2005
Stacks 23 of 32
Pushing an Object (5 of 6)
new InternalNode(newData, _topNode);
• Stack and newly created InternalNode refer to current top node
• Note: we leave off the newData reference for readability (and because it is no longer needed)
Stack
Node<ElementType> _topNode
InternalNode
ElementType_dataNode<ElementType>
_nextNode
BottomNode
data
data
first entry pushed
InternalNode
ElementType _dataNode<ElementType>
_nextNode
second entry pushed
October 25, 2005
Stacks 24 of 32
Pushing an Object (6 of 6)
_topNode = new InternalNode(newData, _topNode);
• Stack now assigns _topNode to new InternalNode (we redraw for clarity)
Stack
Node _topNode
InternalNode
ElementType _dataNode<ElementType>
_nextNode
BottomNode
data
data
second entry pushed
InternalNode
ElementType _dataNode<ElementType>
_nextNode
first entry pushed
October 25, 2005
Stacks 25 of 32
Popping
• Stack’s pop() returns reference to data stored in top internal node (not node itself)– returns null if no objects in Stack
• Also removes top node from Stack, unless it is bottom node (there are no nodes to remove)
• How does Stack access data stored in InternalNode?– stored as node’s private instance variable — can’t
access directly– use accessor method of InternalNode– or, have InternalNode use mutator method of
some other object, the holder, and then we access the holder
• We’ll define new class that is a Holder for any object!– when we pop a Stack, we generally want the data
that is held by the first node– holder stores data of popped node so it is not lost
(reference to node is lost after pop)– can’t just return the data because already need to
return _nextNode (can’t return two objects)
October 25, 2005
Stacks 26 of 32
A Holder for every Object
• Simple class — only has two methods, the accessor and mutator: getObject and setObject
public class Holder<ElementType> { private ElementType _data;
public Holder() {} public void setObject(ElementType newData) { _data = newData; } public ElementType getObject() { return _data; }}
• Stack will make instance of Holder and pass it to topNode
• InternalNode will set data value of Holder• Same holder as before, but with generics
• Stack will access data value after InternalNode is popped
October 25, 2005
Stacks 27 of 32
Pop Pseudocode and Code
Create instance of Holder
Call pop(holder) on _topNode (top internal node) and set _topNode to return reference to 2nd internal node
Return data stored in Holder
public class Stack<ElementType> { . . . public ElementType pop() {Holder<ElementType> holder = new
Holder<ElementType>(); _topNode = _topNode.pop(holder); return holder.getObject(); }}
• Remember from earlier that Node’s pop method returns Node reference, but Stack’s pop method returns ElementType reference– no one is referencing the object which _topNode
used to refer to so it gets garbage collected
October 25, 2005
Stacks 28 of 32
isEmpty
• We can ask Stack if it is empty. It doesn’t know so it delegates to its _topNode– InternalNode returns false because if one
exists, then there exists data in Stack– BottomNode returns true because if Stack
refers to it directly, Stack is empty
public class InternalNode<ElementType> extends Node {
. . . public boolean isEmpty() { return false; }}
public class BottomNode<ElementType> extends Node {
. . . public boolean isEmpty() { return true; }}
October 25, 2005
Stacks 29 of 32
Patty Stack
• We now have generic Stack. Let’s use it for some Burgers!– Why? Because we’re hungry for beef!
• push method will take Patty, pop method will return Patty.
public class BurgerStackApp { private Stack<Burger> _stack; public BurgerStackApp() { _stack = new Stack<Burger>(); }
// Code to push and pop some burgers}
• And now let’s make Burgers…
October 25, 2005
Stacks 30 of 32
Alternative Approach to Stacks
• Instead of smart nodes, have a smart list
• No delegation, list controls everything
public class SmartStack<ElementType> {private Node<ElementType> _topNode;
public SmartStack() {_topNode = new BottomNode();
}
public void push(ElementType data) {_topNode = new InternalNode(_topNode,
data);}
// Must add the next() and getData()// methods to Nodepublic ElementType pop() {
ElementType temp = _topNode.getData();
// bop the pointer_topNode = _topNode.next();return temp;
}}
Stacks 31 of 32
Design Choice
• Why do we use smart nodes instead of smart lists?– more Object-Oriented to have smart objects and
delegate to them, rather than have nodes just be holders for data
– interesting pedagogical approach, despite being more complex
– generalizes nicely, as we will see
• Why might you use a smart list?– less code– fewer method calls, so it runs faster
• remember the activation stack?
• Each choice has advantages and disadvantages… neither is “correct”!
Stacks 32 of 32