• No results found

Example use of Stack

N/A
N/A
Protected

Academic year: 2021

Share "Example use of Stack "

Copied!
43
0
0

Loading.... (view fulltext now)

Full text

(1)

1

4. Stacks

Introduction

Consider the 4 problems on pp.

170-1

(1) Model the discard pile in a card game

(2) Model a railroad switching yard

(3) Parentheses checker (4) Calculate and display

base-two

representation 26 = ???????2

(2)

2

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.

In these problems we need a

"last-discarded-first-removed,"

"last-pushed-onto-first-removed,"

"last-stored-first-removed, "

"last-generated-first-displayed"

structured data type.

In summary ... a

_____________________________structure.

(3)

3

Stack as an ADT

A stack is:

Basic operations

1. _________________________________

2. Check if stack _______________

3. _____________an element ______________ of the stack

4. _____________ the _____________ of the stack 5. _____________ the _____________ of the stack Terminology is from spring-loaded

stack of plates in a cafeteria: Adding a plate pushes those below it

down in the stack

Removing a plate pops those below it

up one position.

(4)

4

Example use of Stack

BASE-CONVERSION ALGORITHM (See p. 171-2)

/* This algorithm displays the base-2 representation of a base-10 number.

Receive: a positive integer number

Output: the base-two representation of number.

---*/

1. Create an empty stack to hold the remainders.

2. While number ≠ 0:

a. Calculate the remainder that results when number is divided by 2.

b. Push remainder onto the stack of remainders.

c. Replace number by the integer quotient of number divided by 2.

(5)

5

3. While the stack of remainders is not empty:

a. Retrieve and remove the remainder from the top of the stack of

remainders.

b. Display remainder.

(6)

6

/* 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

***************************************************/

__________________ // our own -- <stack> for STL version

#include <iostream>

using namespace std;

int main() {

unsigned number, // the number to be converted remainder; // remainder when number is // divided by 2

_______________________________________________________

char response; // user response

(7)

7

do {

cout << "Enter positive integer to convert: ";

cin >> number;

while (number != 0) {

remainder = number % 2;

____________________________________; number /= 2;

}

cout << "Base-two representation: ";

while (_________________________________) {

____________________________________; ____________________________________; cout << remainder;

}

cout << "\nMore (Y or N)? "; cin >> response;

}

while (response == 'Y' || response == 'y');

)

(8)

8

Building a Stack Class

Two steps:

1. ____________the class; and 2. ____________the class.

1. Design:

__________________________needed to manipulate

"real-world" objects being modeled by class.

Operations are described:

_______________________________________________.

In a manner independent of any specific

representation of object (because we have no idea of what data members will be available).

(9)

9

Stack Operations:

Construction: Initializes an empty stack.

Empty operation: Determines if stack contains any values

Push operation: Modifies a stack by adding a value to top of stack

Top operation: Retrieves the value at the top of the stack

Pop operation: Modifies a stack by removing the top value of the stack

To help with debugging, add early on:

Output: Displays all the elements stored in the stack.

(10)

10

2. Implementing a Stack Class

Define data members: consider storage structure(s) Attempt #1: Use an array with the top of the stack at position 0.

e.g., Push 75, Push 89, Push 64, Pop

+ features:

________________________________________________________

– features:

________________________________________________________

0 1 2 3 4

0 1 2 3 4

Push 75

0 1 2 3 4

Push 89

0 1 2 3 4

Push 64

0 1 2 3 4

Pop

(11)

11

Implementing Stack Class — Refined

Keep the bottom of stack at position 0. Maintain a "pointer"

myTop to the top of the stack.

Instead of modeling a stack of plates, model a stack of books (or a discard pile in a card game.)

43 21 0

Push 75 Push 89 Push 64 Pop

43 21 0

43 21 0

43 21 0

43 21 0

myTop = __

myTop = __

myTop = __

myTop = __

myTop = __

Note: _______________________________________

(12)

12

Provide:

• An ________ data member to hold the____________________.

• An ________ data member to indicate the ________________.

Problems: We need an array declaration of the form

ArrayElementType myArray[ARRAYCAPACITY];

— What type should be used?

Solution (for now): Use the _____________ mechanism:

______________________________

// put this before the class declaration

— What about the capacity?

______________________________

// put this before the class declaration

Now we can declare the array data member in the private section:

_______________________________________

Stack's Data Members

(13)

13

Notes:

1. typedef makes StackElement a _______________ for int

2 Want a stack of reals, or characters, or . . . ? Change the typedef typedef double StackElementType;

or

typedef char StackElementType;

or . . .

When class library is recompiled, array elements will be double or char or . . .

3. An alternative to using and changing a typedef: A ______________

to build a Stack class is built whose element type is left unspecified.

The element type is

__________________________________________________ at compile time.

This is the approach used in the Standard Template Library (STL) and in

most of the other C++ libraries.

(14)

14

4. The typedef and declaration of STACK_CAPACITY outside the class

declaration makes them:

 easy to find when they need changing

accessible throughout the class and in any file that #includes Stack.h

If we put typedef of StackElement and declaration of the without qualification constant STACK_CAPACITY in public section of the class declaration, they can be accessed outside the class, but require qualification:

_____________________________

_____________________________

5. If we were to make STACK_CAPACITY a data member, we would probably make it a _________ data member:

_________ const int STACK_CAPACITY = 128;

This makes it a property of the class useable by all class objects, but they ___________________________ of STACK_CAPACITY.

(15)

15

//Stack.h

/* Stack.h provides a Stack class.

*

* Basic operations:

* Constructor: Constructs an empty stack * empty: Checks if a stack is empty

* push: Modifies a stack by adding a value at the top * top: Accesses the top stack value; leaves stack * unchanged

* pop: Modifies a stack by removing the value at the * 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

---*/

(16)

16

#ifndef STACK

#define STACK

class Stack {

/***** Function Members *****/

public:

. . .

/***** Data Members *****/

private:

}; // end of class declaration . . .

#endif

(17)

17

Stack's Function Members

Constructor:

class Stack {

public:

/*--- Constructor ---

Precondition: A stack has been declared.

Postcondition: Stack has been constructed as an empty stack.

*/

_______________________

...

} // end of class declaration

Simple enough to inline?

___________________________________________

(18)

18

A declaration Stack s;

will construct s as follows:

s 0 1 2 3 4 . . . 127

(19)

19

empty:

Receives Stack containing it as a function member (perhaps implicitly) Returns: True if stack is empty, false otherwise.

Member function? _______

Const function? (Shouldn't alter data members)? _______

Simple enough to inline? ______

class Stack {

public:

. . .

/* --- Is the Stack empty? ---

* Returns: true if the Stack containing this

* function is empty and false otherwise

***************************************************/

_______________________________

. . .

};// end of class declaration

(20)

20

Test driver:

#include <iostream>

#include <iomanip>

using namespace std;

#include "Stack.h"

int main() {

Stack s;

cout << boolalpha << "s empty? "

<< s.empty() << endl;

}

Output:

_______________________________

or if boolalpha omitted or not implemented:

_______________________________

(21)

21

push:

Receives Stack containing it as a function member (perhaps implicitly)

Value to be added to stack

Returns: Modified stack (perhaps implicitly) Member function? _______

Const function? _______

Simple enough to inline? _______

Add to class declaration:

/* --- Add a value to the stack --- *

* Receive: A value to be added to a Stack

* Postcondition: Value is added at top of stack * provided there's space

* Output: "Stack full" message if no space

*************************************************/

_____________________________________________________

(22)

22

Add to Stack.cpp:

void Stack::push(_____________________________________) {

} // or simply,_______________________ = value;

else

cerr <<

"*** Stack full -- can't add new value ***\n"

"Must increase value of STACK_CAPACITY in Stack.h\n";

}

(23)

23

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

(24)

24

Output: So we can test our operations.

Receives: Stack containing it as a function member (perhaps implicitly)

Output: Contents of Stack, from the top down.

Member function?______

Const function?_____Simple enough to inline?

______

Add to class declaration:

/* --- Display values stored in the stack --- *

* Receive: The ostream out

* Output: Stack's contents, from top down, to out ***************************************************/

____________________________________________

_____

Add to Stack.cpp

void Stack::display(ostream & out) const {

}

(25)

25

Modify driver:

/*

for (int i = 1; i <= 128; i++) s.push(i);

cout << "Stack should now be full\n";

s.push(129);

*/

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:

(26)

26

Add to class declaration:

/* --- Return value at top of the stack --- * Return: value at the top of nonempty Stack

* Output: "Stack empty" message if stack empty

***************************************************/

_________________________________________

top:

Receives: Stack containing it as a function member (perhaps implicitly)

Returns: Value at the top of the stack Output: Error message if stack is empty Member function? _______

Const function?

_______

Simple enough to inline?

_______

(27)

27

Add to Stack.cpp:

StackElement Stack::top() const {

else {

cerr << "*** Stack is empty "

" -- returning garbage ***\n";

return myArray[STACK_CAPACITY-1];

} }

Add to driver at bottom:

cout << "Top value: " << s.top() << endl;

Output:

Stack contents:

8 6 4 2

s empty? false Top value: 8

(28)

28

pop:

Receives Stack containing it as a function member (perhaps implicitly)

Returns: Stack with top element removed (perhaps implicitly) Output: Error message if stack is empty.

Member function?_____Const function?

______ Simple enough to inline?

______

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.

**************************************************/

____________________________

. . .

}; // end of class declaration

(29)

29

inline void Stack::pop() {

else

cerr << "*** Stack is empty -- "

"can't remove a value ***\n";

}

Add to driver at bottom:

while (!s.empty()) {

cout << "Popping " << s.top() << endl;

s.pop();

}

cout << "s empty? " << s.empty() << endl;

Output:

Stack contents:

8 6 4 2

s empty? false Top value: 8 Popping 8

Popping 6 Popping 4 Popping 2

s empty? true

(30)

30

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 include: parameters

caller's state information (saved)

(e.g., contents of registers, return address) local variables

temporary storage

What kind of data structure should be used to store these so that they can be recovered and the system reset when the function resumes execution?

(31)

31

Problem:FunctionA can call FunctionB FunctionB can call FunctionC

. . .

When a function calls another function, it interrupts its own execution and needs to be able to resume its execution in the same state it was in when it was

interrupted.

When FunctionC finishes, control should return to FunctionB.

When FunctionB finishes, control should return to FunctionA.

So, the order of returns from a function is the reverse of function invocations; that is, ________behavior.

Use a _________to store the activation records.

Since it is manipulated at run-time, it is called the ____________________

(32)

32

What happens when a function is called?

1.

___________________________________________________

2. Copy its arguments into the parameter spaces 3. Transfer control to the address of the function's body

The ______________________in the run-time stack is always

that of the function ___________________________.

What happens when a function terminates?

1. _____________________________________________

from the run-time stack

2. Use new top activiation record to ______________________

___________________________________________________

execution of the interrupted function.

(33)

33

Trace run-time stack for the following:

. . .

int main() { . . .

f2(...);

f3(...);

}

void f1(...) {. . .}

void f2(...) {...

f1(...); ...}

void f3(...) {...

f2(...); ...}

In-Class Problems

int factorial(int n) {

if (n < 2) return 1;

else

return n * factorial(n-1);

}

What happens to the run-time stack when the following statement

executes?

int answer = factorial(4);

This pushing and popping of the run-time stack is the real overhead associated with function calls that inlining avoids by replacing the function call with the body of the function.

(34)

34

Appliation of Stacks: RPN

1. What is RPN (Reverse Polish Notation)?

A notation for arithmetic expressions in which _____________________

____________________________________. Expressions can be written

_____________________________.

Developed by Polish logician, Jan Lukasiewics, in 1950's _________notation: operators written _________ the operands

_________ " (RPN): operators written _________ the operands

_________ " : operators written _________ the operands

Examples:

INFIX RPN (POSTFIX) PREFIX

A + B __________________ ____________________

A * B + C __________________ ____________________

A * (B + C) __________________ ____________________

A - (B - (C - D)) __________________ ____________________

A - B - C - D __________________ ____________________

(35)

35

Evaluating RPN Expressions

"By hand" (Underlining technique):

1. Scan the expression from left to right to find an operator.

2. Locate ("underline") the last two preceding operands and combine them using this operator.

3. Repeat until the end of the expression is reached.

Example:

2 3 4 + 5 6 - - *

 2 3 4 + 5 6 - - *

2 __ *  2 8 *

___

 2 __ 5 6 - - *

 2 7 5 6 - - *

 2 7 ____ - *

 2 7 -1 - * 

(36)

36

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 the RPN expression.

b. If token is an operand, push it onto the stack.

If it is an operator, then:

(i) Pop top two values from the stack. If stack

does not contain two items, signal error due to a

malformed RPN and terminate evaluation.

(ii) Apply the operator to these two values.

(iii) Push the resulting value back onto the stack.

3. When the end of expression encountered, its value is on top

of the stack (and, in fact, must be the only value in the stack).

Push TEMP#

Generate code:

LOAD operand1 op operand2 STORE TEMP#:

(37)

37

Sample RPN Evaluation (p.

Example: 2 3 4 + 5 6 - - *

196)

Push 2 Push 3 Push 4 Read +

Pop 4, Pop 3, ___________

Push 7 Push 5 Push 6 Read -

Pop 6, Pop 5, ___________

Push -1 Read -

Pop -1, Pop 7, __________

Push 8 Read *

Pop 8, Pop 2, ___________

Push 16

2

2

2

(38)

38

Unary minus causes problems

Example: 5 3 - - 5 3 - -



OR 5 3 - -

 

Use a different symbol:

____________

____________

(39)

39

Converting Infix to RPN

By hand: Represent infix expression as an expression tree:

A * B + C A * (B + C) ((A + B) * C) / (D - E)

(40)

40

C

A B

D E

*

+

/

-

Traverse the tree in Left-Right- Parent

order (postorder) to get __________:

C

A B

D E

*

+

/

-

Traverse tree in Parent-Left- Right

order (preorder) to get prefix:

Traverse tree in Left-Parent- Right

order (inorder) to get infix

— must insert ()'s

C

A B

D E

*

+

/

-

(41)

41

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)  _____________

 _____________

 _____________

Class Exercise:

((A + B) * C) / (D - E)

(42)

42

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.

(iv) an operand: Display it.

3. When end of infix expression reached, pop and display stack items until stack is empty.

(43)

43

Example:

Push ( Output

Display A _____________

Push +

Display B _____________

Push *

Display C _____________

Read )

Pop *, Display *, _____________

Pop +, Display +, Pop ( _____________

Push / Push ( Display D Push - Push ( Display E Push - Display F Read )

Pop -, Display -, Pop ( __________________

Read )

Pop -, Display -, Pop ( __________________

Pop /, Display /

___________________

(A+B*C)/(D-(E-F))

ABC*+D

ABC*+DE ABC*+DEF

(A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F)) (A+B*C)/(D-(E-F))

References

Related documents