IV. Stacks. A. Introduction 1. Consider the 4 problems on pp (1) Model the discard pile in a card game. (2) Model a railroad switching yard

Similar documents
Chapter 7: Stacks. Exercises 7.2

The Stack and Queue Types

III. Classes (Chap. 3)

STACKS AND QUEUES. Problem Solving with Computers-II

STACKS. A stack is defined in terms of its behavior. The common operations associated with a stack are as follows:

EECE.3220: Data Structures Spring 2017

Containers: Stack. Jordi Cortadella and Jordi Petit Department of Computer Science

CSC 222: Computer Programming II. Spring 2004

Containers: Stack. The Stack ADT. The Stack ADT. The Stack ADT

ADTs: Stacks and Queues

Data Structures using OOP C++ Lecture 9

ADT: Lists, Stacks and Queues

More Group HW. #ifndef Stackh #define Stackh. #include <cstdlib> using namespace std;

Stacks. stacks of dishes or trays in a cafeteria. Last In First Out discipline (LIFO)

Stacks and their Applications

Some Applications of Stack. Spring Semester 2007 Programming and Data Structure 1

Stacks. Chapter 5. Copyright 2012 by Pearson Education, Inc. All rights reserved

// The next 4 functions return true on success, false on failure

Programming Abstractions

Introduction. Problem Solving on Computer. Data Structures (collection of data and relationships) Algorithms

Lecture Data Structure Stack

CSCE 110 PROGRAMMING FUNDAMENTALS

Abstract Data Types 1

DEEPIKA KAMBOJ UNIT 2. What is Stack?

Linear Data Structure

Stack. 4. In Stack all Operations such as Insertion and Deletion are permitted at only one end. Size of the Stack 6. Maximum Value of Stack Top 5

Largest Online Community of VU Students

Data Structures & Algorithm Analysis. Lecturer: Souad Alonazi

Abstract Data Types. CptS 223 Advanced Data Structures. Larry Holder School of Electrical Engineering and Computer Science Washington State University

09 STACK APPLICATION DATA STRUCTURES AND ALGORITHMS REVERSE POLISH NOTATION

Stacks. Chapter 5. Copyright 2012 by Pearson Education, Inc. All rights reserved

Stacks. Revised based on textbook author s notes.

Data Structures and Algorithms

Problem with Scanning an Infix Expression

! A data type for which: ! In fact, an ADT may be implemented by various. ! Examples:

Formal Languages and Automata Theory, SS Project (due Week 14)

CS 211 Programming Practicum Spring 2018

the Stack stack ADT using the STL stack are parentheses balanced? algorithm uses a stack adapting the STL vector class adapting the STL list class

Data Structure using C++ Lecture 04. Data Structures and algorithm analysis in C++ Chapter , 3.2, 3.2.1

Stack ADT. ! push(x) puts the element x on top of the stack! pop removes the topmost element from the stack.

Data Structures Week #3. Stacks

CS 211 Programming Practicum Fall 2018

VI. Templates A. Introduction.

CS 211 Programming Practicum Spring 2017

List, Stack, and Queues

March 13/2003 Jayakanth Srinivasan,

7.1 Optional Parameters

CS 106B Lecture 5: Stacks and Queues

Introduction to the C programming language

CHAPTER 3 STACKS AND QUEUES. Iris Hui-Ru Jiang Fall 2008

Generic Programming: Overloading and Templates

EC8393FUNDAMENTALS OF DATA STRUCTURES IN C Unit 3

Reference Parameters A reference parameter is an alias for its corresponding argument in the function call. Use the ampersand (&) to indicate that

-The Hacker's Dictionary. Friedrich L. Bauer German computer scientist who proposed "stack method of expression evaluation" in 1955.

Introduction to the C programming language

Review: Expressions, Variables, Loops, and more.

Stacks. 1 Introduction. 2 The Stack ADT. Prof. Stewart Weiss. CSci 235 Software Design and Analysis II Stacks

Lecture No.04. Data Structures

UNIT- 3 Introduction to C++

[CS302-Data Structures] Homework 2: Stacks

MIDTERM EXAMINATION Spring 2010 CS301- Data Structures

Chapter 12: Searching: Binary Trees and Hash Tables. Exercises 12.1

Lecture 7. Log into Linux New documents posted to course webpage

CSI33 Data Structures

Stacks Fall 2018 Margaret Reid-Miller

Lab 2: ADT Design & Implementation

ADT: Design & Implementation

Largest Online Community of VU Students

double d0, d1, d2, d3; double * dp = new double[4]; double da[4];

Operator overloading

Introduction to Computers and C++ Programming p. 1 Computer Systems p. 2 Hardware p. 2 Software p. 7 High-Level Languages p. 8 Compilers p.

Topic Binary Trees (Non-Linear Data Structures)

Programming Abstractions

Topics. bool and string types input/output library functions comments memory allocation templates classes

Stack and Its Implementation

Data Structures and Algorithms

Outline. Introduction Stack Operations Stack Implementation Implementation of Push and Pop operations Applications. ADT for stacks

Abstract Data Types 1

Stacks. Manolis Koubarakis. Data Structures and Programming Techniques

C++ For Science and Engineering Lecture 27

Review: Exam 1. Your First C++ Program. Declaration Statements. Tells the compiler. Examples of declaration statements

Stack Applications. Lecture 27 Sections Robb T. Koether. Hampden-Sydney College. Wed, Mar 29, 2017

Datastructuren André Deutz

Programming in C/C Lecture 3

Welcome Back. CSCI 262 Data Structures. Hello, Let s Review. Hello, Let s Review. How to Review 8/19/ Review. Here s a simple C++ program:

pointers & references

Infix to Postfix Conversion

UNIVERSITY OF EDINBURGH COLLEGE OF SCIENCE AND ENGINEERING SCHOOL OF INFORMATICS INFR08013 INFORMATICS 1 - FUNCTIONAL PROGRAMMING

Ch. 18: ADTs: Stacks and Queues. Abstract Data Type

CISC-235. At this point we fnally turned our atention to a data structure: the stack

Short Notes of CS201

An Introduction to Trees

Where do we go from here?

The Stack ADT. Stacks. The Stack ADT. The Stack ADT. Set of objects in which the location an item is inserted and deleted is prespecified.

CS201 - Introduction to Programming Glossary By

Character Set. The character set of C represents alphabet, digit or any symbol used to represent information. Digits 0, 1, 2, 3, 9

Basic memory model Using functions Writing functions. Basics Prototypes Parameters Return types Functions and memory Names and namespaces

Introduction to C++ Systems Programming

MULTIMEDIA COLLEGE JALAN GURNEY KIRI KUALA LUMPUR

Abstract Data Types (ADTs) 1. Legal Values. Client Code for Rational ADT. ADT Design. CS 247: Software Engineering Principles

Transcription:

IV. Stacks 1 A. Introduction 1. Consider the problems on pp. 170-1 (1) Model the discard pile in a card game (2) Model a railroad switching yard (3) Parentheses checker () Calculate and display base-two representation 26 =????????2 Remainders are generated in right-to-left order. We need to "stack" them up, then print them out from top to bottom. Need a "last-discarded-first-removed," "last-pushed-onto-first-removed," "laststored-first-removed, " "last-generated-first-displayed" structured data type. In summary... a LIFO (last-in-first-out) structure.

2 2. Definition of a stack as an ADT (abstract data type): A stack is an ordered collection of data items in which access is possible only at one end, called the top of the stack. Its basic operations are: 1. Construct a stack (usually empty) 2. Check if stack is empty 3. Push: Add an element at the top of the stack. Top: Retrieve the top element of the stack 5. Pop: Remove the top element of the stack The terminology comes from a spring-loaded stack of plates in a cafeteria: Adding a plate pushed those below it are pushed down in the stack When a plate is removed from the stack, those below it pop up one position. 3. If we had a stack class we could use it to easily develop a short program for the baseconversion problem. 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. 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.

3

/* 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 *********************************************************/ #include "Stack.h" #include <iostream> using namespace std; // our own -- <stack> for STL version 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 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 << endl; cout << "\nmore (Y or N)? "; cin >> response; while (response == 'Y' response == 'y');

5 B. Building a Stack Class Two steps: 1. Design the class; and 2. Implement the class. 1. Designing a Stack Class Designing a class consists of identifying those operations that are needed to manipulate the "real-world" object being modeled by the class. Time invested in this design phase will pay off, because it results in a well-planned class that is easy to use. Note: The operations are described independently of how the class will be implemented. At this point, we have no idea what data members will be available, so the operations must be described in some manner that does not depend on any particular representation of the object. The resulting specification then constitutes the "blueprint" for building the class. From definition of stack as ADT, we must have (at least) the following operations: Construction: Initializes an empty stack.) Empty operation: Examines a stack and return false or true depending on whether the stack contains any values: Push operation: Modifies a stack by adding a value at the top of the stack: Top operation: Retrieves the value at the top of the stack: Pop operation: Modifies a stack by removing the value at the top of the stack: To help with debugging, add early on: Output: Displays all the elements stored in the stack.

2. Implementing a Stack Class Two steps: 6 1. Define data members. 2. Define the operations a. Selecting Data Members. A stack must store a collection of values, so we begin by considering what kind of storage structure(s) to use. Attempt #1: Use an array with the top of the stack at position 0. e.g., Push 75, Push 89, Push 6, Pop 0 1 2 3 Push 75 Push 89 0 75 0 89 1 1 75 2 2 3 3 Push 6 0 6 0 1 89 1 2 75 2 3 3 Pop 89 75 + features: This models the operation of the stack of plates. features: Not efficient to shift the array elements up and down in the array.

Attempt #2 A Better Approach Instead of modeling the stack of plates, model a stack of books. 7 Push Push Pop Keep the bottom of stack at position 0 and maintain a "pointer" mytop to the top of the stack. e.g., Push 75, Push 89, Push 6, Pop 3 2 1 0 mytop Push 75 Push 89 Push 6 3 3 3 3 2 2 mytop 2 6 2 1 mytop 1 89 1 89 mytop 1 mytop 0 75 0 75 0 75 0 mytop = 1 mytop = 0 mytop = 1 mytop = 2 mytop = 1 Pop 6 89 75 Note: No moving of array elements.

So, we can begin the declaration of our class by selecting data members: 8 Provide an array data member to hold the stack elements. Provide a constant data member to refer to the capacity of the array. Provide an integer data member to indicate the top of the stack. Problems: We need an array declaration of the form ArrayElementType myarray[arraycapacity]; What type should be used? Solution (for now): Use the typedef mechanism: typedef int StackElement; // put this before the class declaration What about the capacity? const int STACK_CAPACITY = 128; // put this before the class declaration Then declare the array as a data member in the private section: StackElement myarray[stack_capacity]; Notes: 1. The typedef makes StackElement a synonym for int. Putting it outside the class makes it accessible throughout the class and in any file that #includes Stack.h. If in the future we want a stack of reals, or characters, or..., we need only change the typedef: typedef double StackElementType; or typedef char StackElementType; or... When the class library is recompiled, the type of the array's elements will be double or char or... 2. A more modern alternative that doesn't require using (and changing a typedef is to use the template mechanism to build a Stack class whose element type is left unspecified. The element type is then passed as a special kind of parameter at compile time. We'll describe this soon. This is the approach used in the Standard Template Library (STL).

3. Putting the typedef and declaration of STACK_CAPACITY ahead of the class declaration makes these declarations easy to find when they need changing. 9. If the type StackElement or the constant STACK_CAPACITY were defined as public members inside the class declaration, they could be accessed outside the class but would require qualification: Stack::STACK_CAPACITY Stack::StackElement 5. If we were to make the constant STACK_CAPACITY a class member we would probably make it a static data member: static const int STACK_CAPACITY = 128; This makes it a property of the class usable by all class objects, but they do not have their own copies of STACK_CAPACITY. So, we can begin writing Stack.h: 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 ------------------------------------------------------------------*/ #ifndef STACK #define STACK const int STACK_CAPACITY = 128; typedef int StackElement; class Stack /***** Function Members *****/ public:... /***** Data Members *****/ private: StackElement myarray[stack_capacity]; int mytop; ; // end of class declaration... #endif

10 b. Function Members Constructor : Simple enough to inline? Yes class Stack public: /* --- Constructor --- Precondition: A stack has been declared. Postcondition: The stack has been constructed as an empty stack. ------------------------------------------------------------*/ Stack();... ;// end of class declaration inline Stack::Stack() mytop = -1; A declaration Stack S; will construct S as follows: S 0 1 2 3... 127 myarray?????...? mytop -1 empty: Receives: Stack containing it as a function member (implicitly) Returns: True if stack is empty, false otherwise. Member function? Yes const function? (Shouldn't alter data members?) Yes Simple enough to inline? Yes

class Stack public:... /* --- Is the Stack empty? --- * Receive: stack containing this function (implicitly) * 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 return (mytop == -1); 11 Test driver: Output #include <iostream> s empty? true using namespace std; #include "Stack.h" int main() Stack s; cout << boolalpha << "s empty? " << s.empty() << endl; push: Receives: Stack containing it as a function member (implicitly) Value to be added to stack Return: Modified Stack (implicitly) Member function? Yes const function? No Simple enough to inline? Probably not

class Stack public:... /* --- Add a value to the stack --- * * Receive: The Stack containing this function (implicitly) * A value to be added to a Stack * Pass back: The Stack (implicitly), with value added at its * top, provided there's space * Output: "Stack full" message if no space for value *************************************************************/ void push(const StackElement & value);... ; // end of class declaration Definition In Stack.cpp void Stack::push(const StackElement & value) if (mytop < STACK_CAPACITY - 1) // Preserve stack invariant 12 ++mytop; myarray[mytop] = value; // or simply, myarray[++mytop] = value; else cerr << "*** Stack is full -- can't add new value ***\n" << "Must increase value of STACK_CAPACITY in Stack.h\n"; 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 ***

Output: So we can test our operations. Receives: Stack containing it as a function member (implicitly) Output: Contents of Stack, from the top down. Member function? Yes const function? (Shouldn't alter data members?) Yes Simple enough to inline? No 13 Prototype: /* --- Display values stored in the stack --- * * Receive: The Stack containing this function (implicitly) * The ostream out * Output: The Stack's contents, from top down, to out *************************************************************/ void display(ostream & out) const; Definition in Stack.cpp: void Stack::display(ostream & out) const for (int i = mytop; i >= 0; i--) out << myarray[i] << endl; 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 <= ; 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 2 s empty? false

1 top: Member function? Yes const function? Yes Simple enough to inline? Probably not Prototype: /* --- Return value at top of the stack --- * * Receive: The Stack containing this function (implicitly) * Return: The value at the top of the Stack, if nonempty * Output: "Stack empty" message if stack is empty *************************************************************/ StackElement top() const; Definition (in Stack.cpp): StackElement Stack::top() const if (mytop >= 0) return (myarray[mytop]); cerr << "*** Stack is empty ***\n"; Add to driver at bottom: cout << "Top value: " << s.top() << endl; Output Stack contents: 8 6 2 s empty? false Top value: 8

pop: Member function? Yes const function? No Simple enough to inline? Probably not 15 Prototype: /* --- Remove value at top of the stack --- * * Receive: The Stack containing this function (implicitly) * Pass back: The Stack containing this function (implicitly) * with its top value (if any) removed * Output: "Stack-empty" message if stack is empty. *************************************************************/ void pop(); Definition (in Stack.cpp): void Stack::pop() if (mytop >= 0) // Preserve stack invariant mytop--; 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 2 s empty? false Top value: 8 Popping 8 Popping 6 Popping Popping 2 s empty? true

C. Two Applications of Stacks 16 Use of Stacks in Function Calls 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 when a function calls other functions and interrupts its own execution so that they can be recovered and the system reset when the function resumes execution? Clearly need LIFO behavior. (Obviously necessary for recursive functions.) So use a stack. Since it is manipulated at run-time, it is called the run-time stack. What happens when a function is called: (1) Push a copy of its activation record onto the run-time stack (2) Copy its arguments into the parameter spaces (3) Transfer control to the address of the function's body So the top activation record in the run-time stack is always that of the function currently executing. What happens when a function terminates? (1) Pop activation record of terminated function from the run-time stack (2) Use new top activiation record to restore the environment of the interrupted function and resume execution of it.

Examples:... int main()... f2(...); f3(...); void f1(...)... void f2(...)... f1(...);... void f3(...)... f2(...);... 17 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(); This pushing and popping of the run-time stack is the real overhead associated with function calls that inline functions avoid by replacing the function call with the body of the function. Application to Reverse Polish Notation 1. What is RPN? A notation for arithmetic expressions in which operators are written after the operands. Expressions can be written without using parentheses. Developed by Polish logician, Jan Lukasiewics, in 1950's Infix notation: operators written between the operands Postfix " (RPN): operators written after the operands Prefix " : operators written before the operands Examples: INFIX RPN (POSTFIX) PREFIX A + B A B + + A B A * B + C A B * C + + * A B C A * (B + C) A B C + * * A + B C A (B (C D)) A B C D - - - - A - B - C D A B C D A B - C - D - - - - A B C D

2. Evaluating RPN Expressions a. "By hand": Underlining technique: 18 Scan the expression from left to right to find an operator. Locate ("underline") the last two preceding operands and combine them using this operator. Repeat this until the end of the expression is reached. Example: 2 3 + 5 6 - - * 2 3 + 5 6 - - * 2 7 5 6 - - * 2 7 5 6 - - * 2 7-1 - * 2 7-1 - * 2 8 * 2 8 * 16 b. Algorithm using a stack of operands ALGORITHM TO EVALUATE RPN EXPRESSIONS Receive: An RPN expression. Return: A stack whose top element is the value of the RPN expression (unless an error occurred). Note: Uses a stack to store operands. ---------------------------------------------------------- 1. Initialize an empty stack. 2. Repeat the following until the end of the expression is encountered: a. Get the next token (constant, variable, arithmetic operator) in the RPN expression. b. If the token is an operand, push it onto the stack. If it is an operator, then do the following: (i) Pop the top two values from the stack. (If the stack does not contain two items, an error due to a malformed RPN expression has occurred, and evaluation is terminated.) (ii) Apply the operator to these two values. (iii) Push the resulting value back onto the stack. 3. When the end of the expression is encountered, its value is on top of the stack (and, in fact, must be the only value in the stack).

Example: See p. 172. 19 To generate code, change (ii) and (iii) to: (ii') Generate code: LOAD operand 1 op operand 2 STORE TEMP# (iii') Push TEMP# onto stack. Example: Generate code for A B + C D + *

c. Unary minus causes problems use different symbol 20 Example: 5 3 - - 5 3 - - 5-3 - 8 5 3 - - 5 3 - - 2 - -2 We'll use a different symbol: 5 3 ~ - 5 3 - ~ 3. Converting from Infix to RPN a. "By hand": Represent infix expression as an expression tree: A * B + C * + C A * (B + C) * A + A B B C ((A + B) * C) / (D - E) / * - + C D E A B Traverse the tree in Left-Right-Parent order to get RPN Traverse tree in Parent-Left-Right order to get Prefix Traverse tree in Left-Parent-Right order to get Infix [must insert ()'s]

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. 21 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 + * ((A + B) * C) / (D - E) (((A + B) * C) / (D - E) ) (((A B + C * (D E - / A B + C * D E - /

c. Algorithm using a stack of operators ALGORITHM TO CONVERT AN INFIX EXPRESSION TO RPN Accepts: Output: Note: An infix expression. The RPN expression. Uses a stack to store operators. 1. Initialize an empty stack of operators. 2. While no error has occurred and the end of the infix expression has not been reached: a. Get the next input Token (constant, variable, arithmetic operator, left parenthesis, right parenthesis) in the infix expression. b. If Token is (i) a left parenthesis: (ii) a right parenthesis: (iii) an operator: Push it onto the stack. Pop and display stack elements until a left parenthesis is encountered, but do not display it. (It is an error if the stack becomes empty with no left parenthesis found.) If the stack is empty or Token has a higher priority than the top stack element, push Token onto the stack. 22 (iv) an operand: Otherwise, pop and display the top stack element; then repeat the comparison of Token with the new top stack item. Note: A left parenthesis in the stack is assumed to have a lower priority than that of operators. Display it. 3. When the end of the infix expression is reached, pop and display stack items until the stack is empty.

23