Download presentation
Presentation is loading. Please wait.
Published byFrederica Mosley Modified over 9 years ago
1
Stacks1 of 32 STACKS What are Stacks? Creating a Stack Pushing and Popping Testing for an Empty Stack Burgers! © Pearson Education
2
Stacks2 of 32 Arrays, Vectors, and Stacks Arrays –indexed (allows explicit access to n th item) –cannot change size dynamically –do not keep record of order in which items are inserted Vectors –indexed (allows explicit access to n th item) –can grow/shrink dynamically –do not keep record of order in which items are inserted Stacks –not indexed (can’t explicitly access n th 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
3
Stacks3 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
4
Stacks4 of 32 Plate dispensers are Stacks Number of plates on dispenser can vary from 0 to... Stacks and Plates 1 234 item to push top of Stack AFTER PUSH BEFORE PUSH BEFORE POP AFTER POP 1 2 3 4 top of Stack 1 2 3 4 1 2 3 4 popped item October 25, 2005
5
Stacks5 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 Stack A B C D E October 25, 2005 A calls B B calls C … etc.
6
Stacks6 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. (Cursor.java:14) at wheels.users.UpButton. (UpButton.java:36) at wheels.users.SketchApp. (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 class constructor October 25, 2005
7
Stacks7 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 node s (“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 Top of Stack October 25, 2005
8
Stacks8 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
9
Stacks9 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 _engine City _city Color _color = red City String _name = “Springfield” Engine CSMobile Engine _engine City _city Color _color = blue City String _name = “Warwick” Engine October 25, 2005
10
Stacks10 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
11
Stacks11 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 _data Node _nextNode InternalNode ElementType _data Node _nextNode BottomNode data October 25, 2005
12
Stacks12 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 _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
13
Stacks13 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 _topNode BottomNode October 25, 2005
14
Stacks14 of 32 Stack Code Let’s code what we know so far: public class Stack { private Node _topNode; public Stack() { /** * we want to start with an empty Stack, * so we just create the bottom node. **/ _topNode = new BottomNode (); } 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
15
Stacks15 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 { // using default constructor abstract public Node pop(Holder holder); abstract public boolean isEmpty(); } Node pop(Holder 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
16
Stacks16 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
17
Stacks17 of 32 Internal Node Cont. public class InternalNode extends Node { private Node _nextNode; private ElementType _data; public InternalNode(ElementType newData, Node 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 pop(Holder holder) { holder.setObject(_data); return _nextNode; }
18
Stacks18 of 32 BottomNode public class BottomNode 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
19
Stacks19 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 {... public void push(ElementType newData) { _topNode = new InternalNode (newData, _topNode); } } Just one simple line of code, right? Not really. Let’s look at all it does... October 25, 2005
20
Stacks20 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 _topNode InternalNode ElementType _data Node _nextNode BottomNode data newData Stack Node _topNode BottomNode data newData October 25, 2005
21
Stacks21 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 _data Node _nextNode Stack Node _topNode BottomNode data newData October 25, 2005
22
Stacks22 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 _topNode InternalNode ElementType_data Node _nextNode BottomNode data newData data first entry pushed October 25, 2005
23
Stacks23 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 _topNode InternalNode ElementType_data Node _nextNode BottomNode data first entry pushed InternalNode ElementType _data Node _nextNode second entry pushed October 25, 2005
24
Stacks24 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 _data Node _nextNode BottomNode data second entry pushed InternalNode ElementType _data Node _nextNode first entry pushed October 25, 2005
25
Stacks25 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
26
Stacks26 of 32 A Holder for every Object Simple class — only has two methods, the accessor and mutator: getObject and setObject public class Holder { 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
27
Stacks27 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 {... public ElementType pop() { Holder holder = new Holder (); _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
28
Stacks28 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 extends Node {... public boolean isEmpty() { return false; } } public class BottomNode extends Node {... public boolean isEmpty() { return true; } } October 25, 2005
29
Stacks29 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 _stack; public BurgerStackApp() { _stack = new Stack (); } // Code to push and pop some burgers } And now let’s make Burgers… October 25, 2005
30
Stacks30 of 32 Alternative Approach to Stacks Instead of smart nodes, have a smart list No delegation, list controls everything public class SmartStack { private Node _topNode; public SmartStack() { _topNode = new BottomNode(); } public void push(ElementType data) { _topNode = new InternalNode(_topNode, data); } // Must add the next() and getData() // methods to Node public ElementType pop() { ElementType temp = _topNode.getData(); // bop the pointer _topNode = _topNode.next(); return temp; } }
31
Stacks31 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”!
32
Stacks32 of 32
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.