04 Stacks
04 Stacks
Introduction
Consider the 4 problems on pp.
170-1
(3) Parentheses checker
(1) Model the discard pile (4) Calculate and display
in a card game base-two
(2) Model a railroad representation
switching yard
26 = ???????2
1
In the last problem:
Remainders are generated in right-to-left order. We
need to "stack" them up, then print them out from
top to bottom.
5
/* Program that uses a stack to convert the base-ten
* representation of a positive integer to base two.
*
* Input: A positive integer
* Output: Base-two representation of the number
***************************************************/
int main()
{
unsigned number, // the number to be converted
remainder; // remainder when number is
// divided by 2
Stack stackOfRemainders; // stack of remainders
char response; // user response
6
do
{
cout << "Enter positive integer to convert: ";
cin >> number;
while (number != 0)
{
remainder = number % 2;
stackOfRemainders.push(remainder);
number /= 2;
}
cout << "Base-two representation: ";
while (!stackOfRemainders.empty() )
{
remainder = stackOfRemainders.top();
stackOfRemainders.pop();
cout << remainder;
}
cout << "\nMore (Y or N)? "; cin >> response;
}
while (response == 'Y' || response == 'y');
} 7
Building a Stack Class
Two steps:
1. Design the class; and
2. Implement the class.
11
Note: No moving of array
Stack's Data
Members
Provide:
• An array data member to hold the stack
elements.
• An integer data member to indicate the top of the
stack.
Problems: We need an array declaration of the form
ArrayElementType myArray[ARRAYCAPACITY];
* top
* display: Displays all the stack elements
* Class Invariant:
* 1. The stack elements (if any) are stored in positions
* 0, 1, . . ., myTop of myArray.
* 2. -1 <= myTop < STACK_CAPACITY
------------------------------------------------------------*/
15
#ifndef STACK
#define STACK
class Stack
{
/***** Function Members *****/
public:
. . .
/***** Data Members *****/
private:
StackElement myArray[STACK_CAPACITY];
int myTop;
}; // end of class declaration
. . .
#endif
16
Stack's Function Members
Constructor:
17
A declaration
Stack s;
s 0 1 2 3 4 . . . 127
myArray ? ? ? ? ? . . . ?
myTop -1
18
empty:
Receives Stack containing it as a function member (perhaps
implicitly)
Returns: True ifYe
stack is empty, false otherwise.
Member
Const function?
function? (Shouldn't
s alter data Ye
Simple enough to
members)? Ye s
inline?
class Stack
s
{
public:
. . .
/* --- Is the Stack empty? ---
* Returns: true if the Stack containing this
* function is empty and false otherwise
***************************************************/
bool empty() const;
. . .
};// end of class declaration
inline bool Stack::empty() const
19
{ return (myTop == -1); }
Test driver:
#include <iostream>
#include <iomanip>
using namespace std;
#include "Stack.h"
int main()
{
Stack s;
cout << boolalpha << "s empty? "
<< s.empty() << endl;
}
Output:
s empty? true
or if boolalpha omitted or not
implemented: 20
push:
Receives Stack containing it as a function member (perhaps
implicitly)
Value to be added to stack
Returns: ModifiedYe stack (perhaps implicitly)
Const
Memberfunction?
Nos
function? Simple enough to inline?
Probably not
22
Add at bottom of driver:
for (int i = 1; i <= 128; i++) s.push(i);
cout << "Stack should now be full\n";
s.push(129);
Output:
s empty? true
Stack should now be full
*** Stack is full -- can't add new value ***
Must increase value of STACK_CAPACITY in Stack.h
23
Output: So we can test our operations.
Receives: Stack containing it as a function member
(perhaps implicitly)
an ostream
Output: Contents Ye ofConst
Stack, from the
Ye top down.
Simple enough to Ye
Member function? s function? s inline? s
Add to class declaration:
/* --- Display values stored in the stack ---
*
* Receive: The ostream out
* Output: Stack's contents, from top down, to out
***************************************************/
void display(ostream & out) const;
Add to Stack.h
inline void Stack::display(ostream & out) const
{
for (int i = myTop; i >= 0; i--)
out << myArray[i] << endl;
} 24
Modify driver:
/*
for (int i = 1; i <= 128; i++) s.push(i);
cout << "Stack should now be full\n"; For your Queue class,
make sure output
s.push(129); works after array has
*/ "wrapped around."
for (int i = 1; i <= 4; i++) s.push(2*i);
cout << "Stack contents:\n";
s.display(cout);
cout << "s empty? " << s.empty() << endl;
Output:
s empty? true
Stack contents:
8
6
4
2
s empty? false
25
top:
Receives: Stack containing it as a function member
(perhaps implicitly)
Returns: Value at the top of the stack
Output: Error message
Ye if stack is empty
Member
Const function?
Yes
function?
Simple enoughs to No?
inline?
26
Add to Stack.cpp:
StackElement Stack::top() const
{
if (myTop >= 0) // or if (!empty())
return (myArray[myTop]);
else
{
cerr << "*** Stack is empty "
" -- returning garbage ***\n";
return myArray[STACK_CAPACITY-1];
}
} Output:
Add to driver at bottom: Stack contents:
8
cout << "Top value: " << s.top()
6
4
<< endl;
2
s empty? false
Top value: 8 27
pop:
Receives Stack containing it as a function member (perhaps
implicitly)
Returns: Stack with top element removed (perhaps implicitly)
Output: Error message
Ye Const if stack isNo
empty.
Simple enough to Ye
Member function?
s function? inline? s
class Stack
. . .
/* --- Remove value at top of the stack ---
* Postcondition: Top value of stack (if any) has
* been removed.
* Output: "Stack-empty" message if stack is empty.
**************************************************/
void pop();
. . .
}; // end of class declaration
28
inline void Stack::pop()
{
if (myTop >= 0) // Preserve stack invariant
myTop--;
else
cerr << "*** Stack is empty -- "
"can't remove a value ***\n";
} Output:
Stack contents:
Add to driver at bottom: 8
while (!s.empty()) 6
{ 4
cout << "Popping " << s.top() 2
<< endl; s empty? false
s.pop(); Top value: 8
} Popping 8
cout << "s empty? " << s.empty() Popping 6
<< endl; Popping 4
Popping 2
s empty? true 29
Read §4.3
Application of Stacks: Run-time
Stack
Whenever a function begins execution (i.e., is
activated), an activation record (or stack frame) is
created to store the
current environment for that function. Its contents
parameters
include:
caller's state information (saved)
(e.g., contents of registers, return address)
local variables
temporary storage
Example:
2 3 42+3546+-5-6*
-
- *2 7 5 6 - - *
2 7 5 6 - - *
2 7 -1 - *
2 7 -1 - * 2 8 * 2 8 * 16 35
Stack Algorithm: (p.195)
Receive: An RPN expression.
Return: A stack whose top element is the value of RPN
expression (unless an error
occurred).
1. Initialize an empty stack.
2. Repeat the following until the end of the expression is
encountered:
a. Get next token (constant, variable, arithmetic operator)
in
Generate code:
the RPN expression.
b. If token is an operand, push it onto the stack. LOAD operand1
If it is an operator, then: op operand2
(i) Pop top two values from the stack. If stack STORE TEMP#:
does not contain two items, signal error due to a
Push TEMP#
malformed RPN and terminate evaluation.
(ii) Apply the operator to these two values.
(iii) Push the resulting value back onto the stack.
36
3. When the end of expression encountered, its value is on
A B C + D E - - *
Sample RPN Evaluation (p.
196)
Example: 2 3 4 + 5 6 - - *
Push 2 4
Push 3 3
Push 4 2
Read +
6
Pop 4, Pop 3, 3 + 4 = 7
Push 7 5
Push 5 7
Push 6 2
Read -
Pop 6, Pop 5,5 - 6 = -1
-1
Push -1
Read - 7
Pop -1, Pop 7,7 - -1 = 8 2
Push 8 8
Read *
2
Pop 8, Pop 2, 2 * 8 = 16
Push 16 16 37
Unary minus causes
problems
Example: 5 3 - -
OR 5 3 - -
5 3 - - 2 -
5 -3 - -2
8
Use a different
symbol:
5 3 - ~
5 3 ~ -
38
Converting Infix to RPN
By hand: Represent infix expression as an expression
tree:
A * B + C A * (B + C) ((A + B) * C) / (D - E)
+ * /
A * -
* C +
A B + C D E
B C
A B
x y
39
x y
/
Traverse the tree in Left-Right-
Parent
* -
order (postorder) to get RPN:
A B+ C*D E-/
+ C D E
Traverse tree in Parent-Left- /
Right A B
order (preorder) to get prefix: -
*
/ * + A BC- D E
+ C D E
40
A B
By hand: "Fully parenthesize-move-erase" method:
1. Fully parenthesize the expression.
2. Replace each right parenthesis by the corresponding
operator.
3. Erase all left parentheses.
Examples:
A * B + C ((A * B) + C) A * (B + C) (A * (B + C) )
((A B * C + (A (B C + *
A B * C + A B C + *
Exercise:
((A + B) * C) / (D - E)
41
Stack Algorithm: (p.199)
1. Initialize an empty stack of operators.
2. While no error has occurred and end of infix expression not reached
a. Get next token in the infix expression.
b. If token is
(i) a left parenthesis: Push it onto the stack.
(ii) a right parenthesis: Pop and display stack elements until a left
parenthesis is encountered, but do not
display
it. (Error if stack empty with no left
parenthesis found.)
(iii) an operator: If stack empty or token has higher priority
than top stack element, push token onto
stack.
(Left parenthesis in stack has lower priority
than operators)
Otherwise, pop and display the top stack
element; then repeat the comparison of
token
with new top stack item. 42
(iv) an operand: Display it.
Example: (A+B*C)/(D-(E-F))
Push ( Output
Display A A *
Push + +
Display B AB
Push * (
Display C ABC +
Read )
(
Pop *, Display *, ABC*
Pop +, Display +, Pop ( ABC*+ (
Push /
Push ( -
Display D ABC*+D (
Push -
Push ( -
Display E ABC*+DE (
Push -
Display F ABC*+DEF /
-
Read )
Pop -, Display -, Pop ( ABC*+DEF- (
Read ) /
Pop -, Display -, Pop ( ABC*+DEF-- / 43
Pop /, Display / ABC*+DEF--/