/* * File: stack.h * ------------- * This file exports the Stack class, which implements * a collection that processes values in a last-in/first-out (LIFO) order. */ #ifndef _stack_h #define _stack_h #include "vector.h" /* * Class: Stack * ----------------------- * This class models a linear structure called a stack * in which values are added and removed only from one end. * This discipline gives rise to a last-in/first-out behavior (LIFO) * that is the defining feature of stacks. The fundamental stack * operations are push (add to top) and pop * (remove from top). */ template class Stack { public: /* * Constructor: Stack * Usage: Stack stack; * ------------------------------ * Initializes a new empty stack. */ Stack(); /* * Destructor: ~Stack * ------------------ * Frees any heap storage associated with this stack. */ virtual ~Stack(); /* * Method: size * Usage: int n = stack.size(); * ---------------------------- * Returns the number of values in this stack. */ int size() const; /* * Method: isEmpty * Usage: if (stack.isEmpty()) ... * ------------------------------- * Returns true if this stack contains no elements. */ bool isEmpty() const; /* * Method: clear * Usage: stack.clear(); * --------------------- * Removes all elements from this stack. */ void clear(); /* * Method: push * Usage: stack.push(value); * ------------------------- * Pushes the specified value onto this stack. */ void push(ValueType value); /* * Method: pop * Usage: ValueType top = stack.pop(); * ----------------------------------- * Removes the top element from this stack and returns it. This * method signals an error if called on an empty stack. */ ValueType pop(); /* * Method: peek * Usage: ValueType top = stack.peek(); * ------------------------------------ * Returns the value of top element from this stack, without removing * it. This method signals an error if called on an empty stack. For * compatibility with the STL classes, this method is also exported * under the name top, in which case it returns the value * by reference. */ ValueType peek() const; ValueType & top(); /* * Method: toString * Usage: string str = stack.toString(); * ------------------------------------- * Converts the stack to a printable string representation. */ std::string toString(); /* * Operator: == * Usage: stack1 == stack2 * ------------------- * Returns true if stack1 and stack2 * contain the same elements. */ bool operator==(const Stack & stack2) const; /* * Operator: != * Usage: stack1 != stack2 * ------------------- * Returns true if stack1 and stack2 * do not contain the same elements. */ bool operator!=(const Stack & stack2) const; /* Private section */ /**********************************************************************/ /* Note: Everything below this point in the file is logically part */ /* of the implementation and should not be of interest to clients. */ /**********************************************************************/ /* * Implementation notes: Stack data structure * ------------------------------------------ * The easiest way to implement a stack is to store the elements in a * Vector. Doing so means that the problems of dynamic memory allocation * and copy assignment are already solved by the implementation of the * underlying Vector class. */ private: Vector elements; }; extern void error(std::string msg); /* * Stack class implementation * -------------------------- * The Stack is internally managed using a Vector. This layered design * makes the implementation extremely simple, to the point that most * methods can be implemented in as single line. */ template Stack::Stack() { /* Empty */ } template Stack::~Stack() { /* Empty */ } template int Stack::size() const { return elements.size(); } template bool Stack::isEmpty() const { return size() == 0; } template void Stack::push(ValueType value) { elements.add(value); } template ValueType Stack::pop() { if (isEmpty()) error("pop: Attempting to pop an empty stack"); ValueType top = elements[elements.size() - 1]; elements.remove(elements.size() - 1); return top; } template ValueType Stack::peek() const { if (isEmpty()) error("peek: Attempting to peek at an empty stack"); return elements.get(elements.size() - 1); } template ValueType & Stack::top() { if (isEmpty()) error("top: Attempting to read top of an empty stack"); return elements[elements.size() - 1]; } template void Stack::clear() { elements.clear(); } template std::string Stack::toString() { ostringstream os; os << *this; return os.str(); } template bool Stack::operator==(const Stack & stack2) const { if (size() != stack2.size()) return false; for (int i = 0; i < size(); i++) { if (this->elements[i] != stack2.elements[i]) { return false; } } return true; } template bool Stack::operator!=(const Stack & stack2) const { return !(*this == stack2); } template std::ostream & operator<<(std::ostream & os, const Stack & stack) { os << "{"; Stack copy = stack; Stack reversed; while (!copy.isEmpty()) { reversed.push(copy.pop()); } int len = stack.size(); for (int i = 0; i < len; i++) { if (i > 0) os << ", "; writeGenericValue(os, reversed.pop(), true); } return os << "}"; } template std::istream & operator>>(std::istream & is, Stack & stack) { char ch; is >> ch; if (ch != '{') error("operator >>: Missing {"); stack.clear(); is >> ch; if (ch != '}') { is.unget(); while (true) { ValueType value; readGenericValue(is, value); stack.push(value); is >> ch; if (ch == '}') break; if (ch != ',') { error(std::string("operator >>: Unexpected character ") + ch); } } } return is; } // hashing functions for stacks; defined in hashmap.cpp int hashCode(const Stack& s); int hashCode(const Stack& s); int hashCode(const Stack& s); int hashCode(const Stack& s); int hashCode(const Stack& s); #endif