380 likes | 596 Views
Chapter 6: Stacks. Data Abstraction & Problem Solving with C++ Fifth Edition by Frank M. Carrano. Developing an ADT During the Design of a Solution. ADT stack operations Create an empty stack Destroy a stack Determine whether a stack is empty Add a new item to the stack
E N D
Chapter 6: Stacks Data Abstraction & Problem Solving withC++ Fifth Edition by Frank M. Carrano
Developing an ADT During the Design of a Solution • ADT stack operations • Create an empty stack • Destroy a stack • Determine whether a stack is empty • Add a new item to the stack • Remove the item that was added most recently • Retrieve the item that was added most recently
Developing an ADT During the Design of a Solution • A stack • Last-in, first-out (LIFO) property • The last item placed on the stack will be the first item removed • Analogy • A stack of dishes in a cafeteria Figure 6-1 Stack of cafeteria dishes
Refining the Definition of the ADT Stack • Operation Contract for the ADT Stack isEmpty():boolean {query} push(in newItem:StackItemType) throw StackException pop() throw StackException pop(out stackTop:StackItemType) throw StackException getTop(out stackTop:StackItemType) {query} throw StackException
Checking for Balanced Braces, Parenthesis and Brackets • A stack can be used to verify whether a program contains balanced braces • An example of balanced braces abc{defg[ijk](l{mn})op}qr • An example of unbalanced braces abc{def]}[gh{ij(kl}m) though you have the same number of open and closing types
Checking for Balanced Braces • Requirements for balanced braces • Each time you encounter a “}])”, it should match the previously encountered “{[(” • When you reach the end of the string, you have matched each
In-class exercise:Write the pseudocode for the balancing parenthesis problem
Recognizing Strings in a Language • L = {w$w’ : w is a possibly empty string of characters other than $, w’ = reverse(w) } • A solution using a stack • Traverse the first half of the string, pushing each character onto a stack • Once you reach the $, for each character in the second half of the string, match a popped character off the stack
Implementations of the ADT Stack • The ADT stack can be implemented using • An array • A linked list • The ADT list • All three implementations use a StackException class to handle possible exceptions
An Array-Based Implementation of the ADT Stack • Private data fields • An array of items of type StackItemType • The index top to the top item • Compiler-generated destructor and copy constructor Figure 6-5 An array-based implementation
/** @file StackA.h */ #include "StackException.h" const int MAX_STACK = maximum-size-of-stack; typedef desired-type-of-stack-item StackItemType; / * ADT stack - Array-based implementation. */ class Stack {public: Stack(); bool isEmpty() const; void push(const StackItemType& newItem) ; void pop(); void pop(StackItemType& stackTop) ; void getTop(StackItemType& stackTop) const;
private: /** Array of stack items */ StackItemType items[MAX_STACK]; /** Index to top of stack */ int top; }; // end Stack
/** @file StackA.cpp */ #include "StackA.h" // Stack class specification file Stack::Stack() : top(-1) { } // end default constructor bool Stack::isEmpty() const { return top < 0; } // end isEmpty void Stack::push(const StackItemType& newItem) { // if stack has no more room for another item if (top >= MAX_STACK-1) cout << "StackException: stack full on push"; else { ++top; items[top] = newItem; } // end if } // end push
void Stack::pop() { if (isEmpty()) cout << “StackException: stack empty on pop"; else --top; // stack is not empty; pop top } // end pop void Stack::pop(StackItemType& stackTop) { if (isEmpty()) cout << "StackException: stack empty on pop"; else { // stack is not empty; retrieve top stackTop = items[top]; --top; // pop top } // end if } // end pop file.
void Stack::getTop(StackItemType& stackTop) const { if (isEmpty()) cout << "StackException: stack empty "; else // stack is not empty; retrieve top stackTop = items[top]; } // end getTop // End of implementation
#include <iostream> #include "StackA.h" using namespace std; int main() { StackItemType anItem; Stack aStack; cin >> anItem; // read an item aStack.push(anItem); // push it onto stack return 0; } // end main
A Pointer-Based Implementation of the ADT Stack • A pointer-based implementation • Enables the stack to grow and shrink dynamically • topPtr is a pointer to the head of a linked list of items • A copy constructor and destructor must be supplied Figure 6-6A pointer-based implementation
/** @file StackP.h */ #include "StackException.h" typedef desired-type-of-stack-item StackItemType; /** ADT stack - Pointer-based implementation. */ class Stack {public: Stack(); Stack(const Stack& aStack); ~Stack(); bool isEmpty() const; void push(const StackItemType& newItem) throw(StackException); void pop() throw(StackException); void pop(StackItemType& stackTop) throw(StackException); void getTop(StackItemType& stackTop) const throw(StackException); Pointer implementation of a stack
private: /** A node on the stack. */ struct StackNode { /** A data item on the stack. */ StackItemType item; /** Pointer to next node. */ StackNode *next; }; // end StackNode /** Pointer to first node in the stack. */ StackNode *topPtr; }; // end Stack // End of header file.
/** @file StackP.cpp */ #include <cstddef> // for NULL #include <new> // for bad_alloc #include "StackP.h" // header file using namespace std; Stack::Stack() : topPtr(NULL) { } // end default constructor Stack::Stack(const Stack& aStack) { if (aStack.topPtr == NULL) topPtr = NULL; // original list is empty else
{ // copy first node topPtr = new StackNode; topPtr->item = aStack.topPtr->item; // copy rest of list StackNode *newPtr = topPtr; // new list pointer for (StackNode *origPtr = aStack.topPtr->next; origPtr != NULL; origPtr = origPtr->next) { newPtr->next = new StackNode; newPtr = newPtr->next; newPtr->item = origPtr->item; } // end for newPtr->next = NULL; } // end if } // end copy constructor
Stack::~Stack() { // pop until stack is empty while (!isEmpty()) pop(); // Assertion: topPtr == NULL } // end destructor bool Stack::isEmpty() const { return topPtr == NULL; } // end isEmpty
void Stack::push(const StackItemType& newItem) throw(StackException) { // create a new node try { StackNode *newPtr = new StackNode; // set data portion of new node newPtr->item = newItem; // insert the new node newPtr->next = topPtr; topPtr = newPtr; } catch (bad_alloc e) { throw StackException( "StackException: push cannot allocate memory."); } // try } // end push
void Stack::pop() throw(StackException) { if (isEmpty()) throw StackException("StackException: stack empty "); else { // stack is not empty; delete top StackNode *temp = topPtr; topPtr = topPtr->next; // return deleted node to system temp->next = NULL; // safeguard delete temp; } // end if } // end pop
void Stack::pop(StackItemType& stackTop) throw(StackException) { if (isEmpty()) throw StackException("StackException: stack empty "); else { // stack is not empty; retrieve and delete top stackTop = topPtr->item; StackNode *temp = topPtr; topPtr = topPtr->next; // return deleted node to system temp->next = NULL; // safeguard delete temp; } // end if } // end pop
void Stack::getTop(StackItemType& stackTop) const throw(StackException) { if (isEmpty()) throw StackException("StackException: stack empty "); else // stack is not empty; retrieve top stackTop = topPtr->item; } // end getTop // End of implementation file.
Comparing Implementations • Fixed size versus dynamic size • A statically allocated array-based implementation • Fixed-size stack that can get full • Prevents the push operation from adding an item to the stack, if the array is full • A dynamically allocated array-based implementation or a pointer-based implementation • No size restriction on the stack
Comparing Implementations • A pointer-based implementation vs. one that uses a pointer-based implementation of the ADT list • Pointer-based implementation is more efficient • ADT list approach reuses an already implemented class • Much simpler to write • Saves programming time
The STL Class stack • Provides a size function • Has two data type parameters • T, the data type for the stack items • Container, the container class that the STL uses in its implementation of the stack • Uses the keyword explicit in the constructor’s declaration to prevent use of the assignment operator to invoke the constructor
Application: Algebraic Expressions • When the ADT stack is used to solve a problem, the use of the ADT’s operations should not depend on its implementation • To evaluate an infix expression • Convert the infix expression to postfix form • Evaluate the postfix expression
Evaluating Postfix Expressions • A postfix calculator • When an operand is entered, the calculator • Pushes it onto a stack • When an operator is entered, the calculator • Pops the stack twice • Applies the operation to the values popped • Pushes the result of the operation onto the stack
The STL stack Container • The STL stack container may be implemented as a vector, a list, or a deque (which you will learn about later in this chapter). • Because the stack container is used to adapt these other containers, it is often referred to as a container adapter.
The STL stack Container • Here are examples of how to declare a stack of ints, implemented as a vector, a list, and a deque. stack< int, vector<int> > iStack;//Vector stackstack< int, list<int> > iStack; // List stackstack< int > iStack; // Default – deque stack
18.3 The STL stack Container • See the STL documentation that describes many of the stack container’s member functions.
// This program demonstrates the STL stack// container adapter.#include <iostream>#include <vector>#include <stack>using namespace std;void main(void){ int x; stack< int, vector<int> > iStack;for (x = 2; x < 8; x += 2) { cout << "Pushing " << x << endl; iStack.push(x); }
cout << "The size of the stack is "; cout << iStack.size() << endl; for (x = 2; x < 8; x += 2) { cout << "Popping " << iStack.top() << endl; iStack.pop(); }}Program OutputPushing 2Pushing 4Pushing 6The size of the stack is 3Popping 6Popping 4Popping 2