(Cf. F&T, pp 189ff)
We will first implement a stack using an array as the underlying, fundamental data structure, and then use a different approach which will include "pointer" variables and "linked lists."
We can contrast how a stack is implemented in Pascal or even in (pure) C with how we can implement it in C++. In C++ we can make use of "data encapsulation" and include within the class both the data storage structure as well as the fundamental operations which operate on the data. Including operations in a record structure is not possible in many older languages!
Thus, in C++, (among other things) "push" and "pop" are member functions within the class that we design as our "stack" data structure, and the actual data storage structure (the array) is kept private and unable to be accessed except by means of the member functions of the class.
For the sake of generality, F&T write the code using the data-type "DataType", which may be defined to be any standard or user defined type. This may be done by means of a typedef statement as follows. If one wishes, in a specific program, to make DataType actually be int, one includes the statement:
typedef int DataType;and after this statement, DataType is synonymous with int. Of course, this makes most sense when included with the global (file) declarations (e.g., with the class, const and similar definitions and declarations that are meant to apply to every function in the file).
In creating a stack, we assume some maximum number of elements in the stack. It is best to declare this as a constant identifier, e.g.,
const int MaxStackSize = 50;We then can begin constructing a "stack" class blueprint by including the storage array (call it stacklist) and the top of stack "pointer" (i.e., array index) (call it top) as components of the private section of the class. Thus, we have:
class Stack { private: DataType stacklist[MaxStackSize]; int top; public: //... to be determined ... }In the public section, we will definitely include
In the following code, we assume that the first element into the stack will be placed in subscript location zero, and the others will follow in higher numbered subscript locations. We also assume that the "top of stack" pointer points to (i.e., has the subscript value of) the last location used for a stack element. Thus, if the stack is empty, the "top of stack" value is -1, and before storing an element in the stack, we must increase the "top of stack" pointer value.
Internal to Push and Pop we will also test to make sure that we have not exceeded the capacity of the stack and that the stack actually contains something to "pop" off.
C++ provides a standard output "file" called cerr in which error messages can be directed. Also there is an abrupt ending function, exit, which is usually given the argument of 1 when used to abort the program's operation immediately. This value can be tested at the system level to determine whether a program ended abnormally or not. (Cf. Savitch 2, p. 226)
The F&T book sometimes uses const to designate member functions which do not change anything in the class. This is an optional modifier which helps by warning the user if something has been miscoded and the member function is, in fact, changing something it was not intended to do. Its use is completely optional. (Cf. F&T, p. 9, Savitch 2, p 453-56. Also Notes M1 for Math 10.)
To determine whether a stack is empty, we merely need to check the value of the "top of stack" pointer to see whether it is -1 or not. This can be done by using the logical expression top == -1 which evaluate to 1 (true) if it is true or 0 (false) if false. Thus, we need only return the value of this expression without any other statements needed.
int Stack::StackEmpty(void) { return (top == -1); }Similar code can be written to test for a full stack or to clear the stack.
void Stack::Push (DataType & item) { // if the stack is full, terminate the program if (top == MaxStackSize-1) { cerr << "Stack overflow!" << endl; exit (1); } // else increment top and copy item to stacklist top++; stacklist[top] = item; }
DataType Stack::Pop (void) { DataType temp; // if the stack is empty, terminate the program if (top == -1) { cerr << "Attempt to pop an empty stack!" << endl; exit(1); } // copy the top element temp = stacklist[top]; // decrement the top pointer top--; // return the top value from temp return temp; }
DataType Stack::Peek (void) { // if the stack is empty, terminate the program if (top == -1) { cerr << "Attempt to peek at an empty stack!" << endl; exit(1); } // return the top element return stacklist[top]; }
This page is maintained by Dennis C. Smolarski, S.J.
© Copyright 1998 Dennis C. Smolarski, SJ, All rights reserved.
Last changed: 28 April 1998.