Please send questions to st10@humboldt.edu .
//---------------------------------------------------------------------
// File: stack.template
// Name: Sharon M. Tuttle
// last modified: 4-01-05
//
// Template class name: stack
//
// Purpose: a collection of items such that entries can be
//    Inserted and removed at only one end (called the top)
// 
// Implementation notes: 
//     * uses a linked list of elements of the node template class
//     * if there is insufficient dynamic memory, then the
//       following methods throw bad_alloc: push
//---------------------------------------------------------------------

#include <cassert> // provides assert
//
// note: because this is a template class, it is included
//    in the header file (at the bottom), and not compiled
//    separately. Thus, the header file is not included here!
//
#include "node.h"
using namespace std;

/*****************************************************/
/* CONSTRUCTORS and DESTRUCTOR                       */
/*****************************************************/

// constructor
//
// postcondition: creates an empty stack  instance
//
template <typename Item>
stack<Item>::stack()
{
    top = NULL;
    used = 0;
}

// copy constructor 
//
// adapted from list_copy, Savitch and Main
//
template <typename Item>
stack<Item>::stack(const stack<Item>& source)
{
    node<Item> *source_curr, *new_curr;

    // start copy out as empty, but with the same value of used
    //    as the source being copied
    top = NULL;
    used = source.used;

    // handle the case of the empty stack
    if (source.top == NULL)
    {
        return; // source is empty, so this copy is, too
    }

    // if source is NOT empty, make a copy of it

    // cause new copy to now have source top's data;
    top = new node<Item>(source.top->get_data());

    // start a pointer walking through the new copy
    //    starting from its top
    new_curr = top;

    // is there another in the source left to be copied?
    source_curr = source.top->get_next();

    // while there is another node in the source left
    //     to be copied...
    while (source_curr != NULL)
    {
        // add a new node to the new copy with the data in
        //    that node;
        new_curr->set_next(new node<Item>(source_curr->get_data()));

        // move the new copy's pointer to the new node
        new_curr = new_curr->get_next();

        // is there another in the source left to be copied?
        source_curr = source_curr->get_next();
    }
}

// destructor 
//
template <typename Item>
stack<Item>::~stack()
{
    node<Item> *curr_ptr, *node_to_delete;

    curr_ptr = top;

    // need to deallocate EACH node in the stack
    while (curr_ptr != NULL)
    {
        node_to_delete = curr_ptr;
        curr_ptr = curr_ptr->get_next();
        delete node_to_delete;
    }

    // playing it safe...
    top = NULL;
    used = 0;
}


/*************************************************************/
/* ACCESSORS and other constant member functions (observers) */
/*************************************************************/

// is_empty
//
// postcondition: returns true if stack is empty, and
//    returns false otherwise
//
template <typename Item>
bool    stack<Item>::is_empty( ) const
{
    return (used == 0);
}

// get_top
//
// precondition: is_empty() == false
//
// postcondition: returns the value of the top item of the
//    stack, BUT the stack is unchanged.
//
template <typename Item>
Item    stack<Item>::get_top( ) const
{
    assert(is_empty() == false);

    return(top->get_data());
}

/*****************************************************/
/* MODIFIERS and other modifying member functions    */
/*****************************************************/

// push
//
// postcondition: a new copy of entry has been pushed
//    onto the (top of the) stack
//
template <typename Item>
void    stack<Item>::push(const Item& entry)
{
    node<Item> *temp;

    temp = new node<Item>(entry);

    // new top element's next field needs to point to
    //    "old" top element
    temp->set_next(top);

    // now, top can safely be made to point to new top
    //    element
    top = temp;

    used++;
}

// pop
//
// precondition: is_empty() == false
//
// postcondition: the top item of the stack has been
//    removed, and a reference to it is returned
//
template <typename Item>
Item   stack<Item>::pop( )
{
    value_type popped_item;
    node<Item>*      temp;

    assert(is_empty() == false);

    used--;

    // remember: if we reach here, we KNOW that stack is
    //    not empty

    popped_item = top->get_data();

    // keep track of item to be removed
    temp = top;

    // now it should be safe to make top point to the
    //    new top element
    top = top->get_next();

    // free the space for this popped node from the heap,
    //    so it be be re-allocated for other uses
    delete temp;

    return popped_item;
}