Nyhoff, ADTs, Data Structures and Problem Solving with C++, Second Edition,
© 2005 Pearson Education, Inc. All rights reserved. 0-13-140909-3
Figure 7.2 Conversion from Base Ten to Base Two |
/*-------------------------------------------------------------- This program uses a stack to convert the base-ten representation of a positive integer entered as input to base two, which is then output. ---------------------------------------------------------------------*/ #include <iostream> using namespace std; #include "Stack.h" // 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'); } |
Figure 7.3 Class Declaration for a Stack Type |
/*-- Stack.h --------------------------------------------------- This header file defines a Stack data type. 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 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 --------------------------------------------------------------*/ #include <iostream> using namespace std; #ifndef STACK #define STACK const int STACK_CAPACITY = 128; typedef int StackElement; class Stack { public: /***** Function Members *****/ private: /***** Data Members *****/ StackElement myArray[STACK_CAPACITY]; int myTop; }; #endif |
Figure 7.4A Completed Stack.h File |
/*-- Stack.h --------------------------------------------------- This header file defines a Stack data type. 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: Retrieves the top stack value; leaves stack unchanged pop: Modifies 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 --------------------------------------------------------------*/ #include <iostream> #ifndef STACK #define STACK const int STACK_CAPACITY = 128; typedef int StackElement; class Stack { public: /***** Function Members *****/ /***** Constructor *****/ Stack(); /*---------------------------------------------------------- Construct a Stack object. Precondition: None. Postcondition: An empty Stack object has been constructed (myTop is initialized to -1 and myArray is an array with STACK_CAPACITY elements of type StackElement). -----------------------------------------------------------*/ bool empty() const; /*----------------------------------------------------------- Check if stack is empty. Precondition: None Postcondition: Returns true if stack is empty and false otherwise. -----------------------------------------------------------*/ void push(const StackElement & value); /*----------------------------------------------------------- Add a value to a stack. Precondition: value is to be added to this stack Postcondition: value is added at top of stack provided there is space; otherwise, a stack-full message is displayed and execution is terminated. -----------------------------------------------------------*/ void display(ostream & out) const; /*----------------------------------------------------------- Display values stored in the stack. Precondition: ostream out is open. Postcondition: Stack's contents, from top down, have been output to out. -----------------------------------------------------------*/ StackElement top() const; /*----------------------------------------------------------- Retrieve value at top of stack (if any). Precondition: Stack is nonempty Postcondition: Value at top of stack is returned, unless the stack is empty; in that case, an error message is displayed and a "garbage value" is returned. ----------------------------------------------------------*/ void pop(); /*----------------------------------------------------------- Remove value at top of stack (if any). Precondition: Stack is nonempty. Postcondition: Value at top of stack has been removed, unless the stack is empty; in that case, an error message is displayed and execution allowed to proceed. ----------------------------------------------------------*/ private: /***** Data Members *****/ StackElement myArray[STACK_CAPACITY]; int myTop; }; // end of class declaration #endif |
Figure 7.4B Stack.cpp File |
/*-- Stack.cpp----------------------------------------------------------- This file implements Stack member functions. -------------------------------------------------------------------------*/ #include <iostream> using namespace std; #include "Stack.h" //--- Definition of Stack constructor Stack::Stack() : myTop(-1) {} //--- Definition of empty() bool Stack::empty() const { return (myTop == -1); } //--- Definition of push() void Stack::push(const StackElement & value) { if (myTop < STACK_CAPACITY - 1) //Preserve stack invariant { ++myTop; myArray[myTop] = value; } else { cerr << "*** Stack full -- can't add new value ***\n" "Must increase value of STACK_CAPACITY in Stack.h\n"; exit(1); } } //--- Definition of display() void Stack::display(ostream & out) const { for (int i = myTop; i >= 0; i--) out << myArray[i] << endl; } //--- Definition of top() StackElement Stack::top() const { if ( !empty() ) return (myArray[myTop]); else { cerr << "*** Stack is empty " " -- returning garbage value ***\n"; return *(new StackElement); } } //--- Definition of pop() void Stack::pop() { if ( !empty() ) myTop--; else cerr << "*** Stack is empty -- " "can't remove a value ***\n"; } |
Figure 7.5 Stack Test Program |
/*--------------------------------------------------------------------- Driver program to test the Stack class. ----------------------------------------------------------------------*/ #include <iostream> #include <iomanip> using namespace std; #include "Stack.h" int main() { Stack s; cout << "Stack created. Empty? " << boolalpha << s.empty() << endl; cout << "How many elements to add to the stack? "; int numItems; cin >> numItems; for (int i = 1; i <= numItems; i++) s.push(i); cout << "Stack contents:\n"; s.display(cout); cout << "Stack empty? " << s.empty() << endl; cout << "Top value: " << s.top() << endl; while (!s.empty()) { cout << "Popping " << s.top() << endl; s.pop(); } cout << "Stack empty? " << s.empty() << endl; cout << "Top value: " << s.top() << endl; cout << "Trying to pop: " << endl; s.pop(); } |
Figure 7.6A DStack.h File |
/*-- DStack.h --------------------------------------------------- This header file defines a Stack data type. 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 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 < myCapacity --------------------------------------------------------------*/ #include <iostream> using namespace std; #ifndef DSTACK #define DSTACK typedef int StackElement; class Stack { public: /***** Function Members *****/ /***** Constructors *****/ Stack(int numElements = 128); /*---------------------------------------------------------- Construct a Stack object. Precondition: None. Postcondition: An empty Stack object has been constructed (myTop is initialized to -1 and myArray is an array with numElements (default 128) elements of type StackElement). -----------------------------------------------------------*/ Stack(const Stack & original); /*---------------------------------------------------------- Copy Constructor Precondition: original is the stack to be copied and is received as a const reference parameter. Postcondition: A copy of original has been constructed. -----------------------------------------------------------*/ /***** Destructor *****/ ~Stack(); /*---------------------------------------------------------- Class destructor Precondition: None Postcondition: The dynamic array in the stack has been deallocated. -----------------------------------------------------------*/ /***** Assignment *****/ Stack & operator= (const Stack & original); /*---------------------------------------------------------- Assignment Operator Precondition: original is the stack to be assigned and is received as a const reference parameter. Postcondition: The current stack becomes a copy of original and a reference to it is returned. -----------------------------------------------------------*/ bool empty() const; /*----------------------------------------------------------- Check if stack is empty. Precondition: None Postcondition: Returns true if stack is empty and false otherwise. -----------------------------------------------------------*/ void push(const StackElement & value); /*----------------------------------------------------------- Add a value to a stack. Precondition: value is to be added to this stack Postcondition: value is added at top of stack provided there is space; otherwise, a stack-full message is displayed and execution is terminated. -----------------------------------------------------------*/ void display(ostream & out) const; /*----------------------------------------------------------- Display values stored in the stack. Precondition: ostream out is open. Postcondition: Stack's contents, from top down, have been output to out. -----------------------------------------------------------*/ StackElement top() const; /*----------------------------------------------------------- Retrieve value at top of stack (if any). Precondition: Stack is nonempty Postcondition: Value at top of stack is returned, unless the stack is empty; in that case, an error message is displayed and a "garbage value" is returned. ----------------------------------------------------------*/ void pop(); /*----------------------------------------------------------- Remove value at top of stack (if any). Precondition: Stack is nonempty. Postcondition: Value at top of stack has been removed, unless the stack is empty; in that case, an error message is displayed and execution allowed to proceed. ----------------------------------------------------------*/ private: /***** Data Members *****/ int myCapacity, // capacity of stack myTop; // top of stack StackElement * myArray; // dynamic array to store elements }; // end of class declaration #endif |
Figure 7.6B DStack.cpp File |
/*-- DStack.cpp---------------------------------------------------------- This file implements Stack member functions. -------------------------------------------------------------------------*/ #include <iostream> #include <cassert> #include <new> using namespace std; #include "DStack.h" //--- Definition of Stack constructor Stack::Stack(int numElements) { assert (numElements > 0); // check precondition myCapacity = numElements; // set stack capacity // allocate array of this capacity myArray = new(nothrow) StackElement[myCapacity]; if (myArray != 0) // memory available myTop = -1; else { cerr << "Inadequate memory to allocate stack \n" " -- terminating execution\n"; exit(1); } // or assert(myArray != 0); } //--- Definition of Stack copy constructor Stack::Stack(const Stack & original) : myCapacity(original.myCapacity), myTop(original.myTop) { //--- Get new array for copy myArray = new(nothrow) StackElement[myCapacity]; // allocate array in copy if (myArray != 0) // check if memory available // copy original's array member into this new array for (int pos = 0; pos < myCapacity; pos++) myArray[pos] = original.myArray[pos]; else { cerr << "*Inadequate memory to allocate stack ***\n"; exit(1); } } //--- Definition of Stack destructor Stack::~Stack() { delete [] myArray; } //--- Definition of assignment operator Stack & Stack::operator=(const Stack & original) { if (this != &original) // check that not st = st { //-- Allocate a new array if necessary if (myCapacity != original.myCapacity) { delete[] myArray; // destroy previous array myCapacity = original.myCapacity; // copy myCapacity myArray = new StackElement[myCapacity]; if (myArray == 0) // check if memory available { cerr << "*** Inadequate memory ***\n"; exit(1); } } //--- Copy original's array into this myArray for (int pos = 0; pos < myCapacity; pos++) myArray[pos] = original.myArray[pos]; myTop = original.myTop; // copy myTop member } return *this; } //--- Definition of empty() bool Stack::empty() const { return (myTop == -1); } //--- Definition of push() void Stack::push(const StackElement & value) { if (myTop < myCapacity - 1) //Preserve stack invariant { ++myTop; myArray[myTop] = value; } else { cerr << "*** Stack full -- can't add new value ***\n" "Must increase value of STACK_CAPACITY in Stack.h\n"; exit(1); } } //--- Definition of display() void Stack::display(ostream & out) const { for (int i = myTop; i >= 0; i--) out << myArray[i] << endl; } //--- Definition of top() StackElement Stack::top() const { if ( !empty() ) return (myArray[myTop]); else { cerr << "*** Stack is empty " " -- returning garbage value ***\n"; return *(new StackElement); } } //--- Definition of pop() void Stack::pop() { if ( !empty() ) myTop--; else cerr << "*** Stack is empty -- " "can't remove a value ***\n"; } |
Figure 7.10 Test Program for DStack Class |
/*--------------------------------------------------------------------- Driver program to test the Stack class. ----------------------------------------------------------------------*/ #include <iostream> #include <iomanip> using namespace std; #include "DStack.h" void print(Stack st) { st.display(cout); } int main() { int cap; cout << "Enter stack capacity: "; cin >> cap; Stack s(cap); cout << "Stack created. Empty? " << boolalpha << s.empty() << endl; cout << "How many elements to add to the stack? "; int numItems; cin >> numItems; for (int i = 1; i <= numItems; i++) s.push(i); cout << "Stack empty? " << s.empty() << endl; cout << "Contents of stack s (via print):\n"; print(s); cout << endl; cout << "Check that the stack wasn't modified by print:\n"; s.display(cout); cout << endl; Stack t, u; t = u = s; cout << "Contents of stacks t and u after t = u = s (via print):\n"; cout << "u:\n"; print(u); cout << endl; cout << "t:\n"; print(t); cout << endl; cout << "Top value in t: " << t.top() << endl; while (!t.empty()) { cout << "Popping t: " << t.top() << endl; t.pop(); } cout << "Stack t empty? " << t.empty() << endl; cout << "\nNow try to retrieve top value from t." << endl; cout << "Top value in t: " << t.top() << endl; cout << "\nTrying to pop t: " << endl; t.pop(); } |
Figure
7.11 Linked-List-Based
|
class Stack { public: /***** Function Members *****/ // Prototypes same as in preceding section private: /*** Node class ***/ class Node { public: StackElement data; Node * next; //--- Node constructor Node(StackElement value, Node * link = 0) /*------------------------------------------------------ Precondition: value is received Postcondition: A Node has been constructed with value in its data part and itb next part set to link (default 0). ------------------------------------------------------*/ { data = value; next = link; } }; typedef Node * NodePointer; /***** Data Members *****/ NodePointer myTop; // pointer to top of stack }; // end of class declaration |
Figure 7.12 LStack.cpp Implementation |
//--- LStack.cpp ------------------------------------------------- #include <new> using namespace std; #include "LStack.h" //--- Definition of Stack constructor Stack::Stack() : myTop(0) {} //--- Definition of Stack copy constructor Stack::Stack(const Stack & original) { myTop = 0; if (!original.empty()) { // Copy first node myTop = new Stack::Node(original.top()); // Set pointers to run through the stack's linked lists Stack::NodePointer lastPtr = myTop, origPtr = original.myTop->next; while (origPtr != 0) { lastPtr->next = new Stack::Node(origPtr->data); lastPtr = lastPtr->next; origPtr = origPtr->next; } } } //--- Definition of Stack destructor Stack::~Stack() { // Set pointers to run through the stack Stack::NodePointer currPtr = myTop, // node to be deallocated nextPtr; // its successor while (currPtr != 0) { nextPtr = currPtr->next; delete currPtr; currPtr = nextPtr; } } //--- Definition of assignment operator Stack & Stack::operator=(const Stack & original) { myTop = 0; if (original.empty()) return *this; if (this != &original) // check that not st = st { this->~Stack(); // destroy current linked list // Copy first node myTop = new Stack::Node(original.top()); // Set pointers to run through the stacks' linked lists Stack::NodePointer lastPtr = myTop, origPtr = original.myTop->next; while (origPtr != 0) { lastPtr->next = new Stack::Node(origPtr->data); lastPtr = lastPtr->next; origPtr = origPtr->next; } } return *this; } //--- Definition of empty() bool Stack::empty() const { return (myTop == 0); } //--- Definition of push() void Stack::push(const StackElement & value) { myTop = new Stack::Node(value, myTop); } //--- Definition of display() void Stack::display(ostream & out) const { Stack::NodePointer ptr; for (ptr = myTop; ptr != 0; ptr = ptr->next) out << ptr->data << endl; } //--- Definition of top() StackElement Stack::top() const { if (!empty()) return (myTop->data); else { cerr << "*** Stack is empty " " -- returning garbage ***\n"; return *(new StackElement); // "Garbage" value } } //--- Definition of pop() void Stack::pop() { if (!empty()) { Stack::NodePointer ptr = myTop; myTop = myTop->next; delete ptr; } else cerr << "*** Stack is empty -- can't remove a value ***\n"; } |
Figure 7.12C Driver Program for Linked List Implementation of Stack |
/*--------------------------------------------------------------------- Driver program to test the Stack class. ----------------------------------------------------------------------*/ #include <iostream> using namespace std; #include "LStack.h" void print(Stack st) { st.display(cout); } int main() { Stack s; cout << "Stack created. Empty? " << boolalpha << s.empty() << endl; cout << "How many elements to add to the stack? "; int numItems; cin >> numItems; for (int i = 1; i <= numItems; i++) s.push(i); cout << "Stack empty? " << s.empty() << endl; cout << "Contents of stack s (via print):\n"; print(s); cout << endl; cout << "Check that the stack wasn't modified by print:\n"; s.display(cout); cout << endl; Stack t, u; t = u = s; cout << "Contents of stacks t and u after t = u = s (via print):\n"; cout << "u:\n"; print(u); cout << endl; cout << "t:\n"; print(t); cout << endl; cout << "Top value in t: " << t.top() << endl; while (!t.empty()) { cout << "Popping t: " << t.top() << endl; t.pop(); } cout << "Stack t empty? " << t.empty() << endl; cout << "\nNow try to retrieve top value from t." << endl; cout << "Top value in t: " << t.top() << endl; cout << "\nTrying to pop t: " << endl; t.pop(); } |
Figure 7.15 Converting Infix to Postfix |
/*-------------------------------------------------------------------------- Convert infix expressions to postfix. Input: An infix expression and user responses Output: The postfix expression --------------------------------------------------------------------------*/ #include <iostream> // <<, >>, cout, cin #include <string> // string, ==, find, npos #include <cassert> // assert() #include <cctype> // alnum() using namespace std; #include "DStack.h" // Stack class with StackElement = char string postfix(string exp); int main() { string exp; // infix expression cout << "NOTE: Enter # for infix expression to stop.\n"; for (;;) { cout << "\nInfix expression? "; getline(cin, exp); if (exp == "#") break; cout << "Postfix expression is " << postfix(exp) << endl; } } string postfix(string exp) /*------------------------------------------------------------------------- Function to convert an infix expression exp to postfix. Precondition: exp is received Postcondition: postfix expression corresponding to exp is returned or an error message displayed if an error was found in exp. -------------------------------------------------------------------------*/ { char token, // character in exp topToken; // token on top of opStack Stack opStack; // stack of operators string RPNexp; // postfix expression const string BLANK = " "; for (int i = 0; i < exp.length(); i++) { token = exp[i]; switch(token) { case ' ' : break; // do nothing -- skip blanks case '(' : opStack.push(token); break; case ')' : for (;;) { assert (!opStack.empty()); topToken = opStack.top(); opStack.pop(); if (topToken == '(') break; RPNexp.append(BLANK + topToken); } break; case '+' : case '-' : case '*' : case '/': case'%': for (;;) { if (opStack.empty() || opStack.top() == '(' || (token == '*' || token == '/' || token == '%') && (opStack.top() == '+' || opStack.top() == '-')) { opStack.push(token); break; } else { topToken = opStack.top(); opStack.pop(); RPNexp.append(BLANK + topToken); } } break; default : // operand RPNexp.append(BLANK + token); for(;;) { if ( !isalnum(exp[i+1]) ) break; // end of identifier i++; token = exp[i]; RPNexp.append(1, token); } } } // Pop remaining operators on the stack for (;;) { if (opStack.empty()) break; topToken = opStack.top(); opStack.pop(); if (topToken != '(') { RPNexp.append(BLANK + topToken); } else { cout << " *** Error in infix expression ***\n"; break; } } return RPNexp; } |
Figure |
|
Figure |
|
Figure |
|
Figure |
|
Figure |
|
Figure |
|
Figure |
|