Please send questions to st10@humboldt.edu .
/************************************************************/
/* ADAPTED FROM:                                            */
/* http://www.cs.colorado.edu/~main/chapter4/node1.cxx      */
/*                                                          */
/* Main and Savitch, "Data Structures and Other Objects     */
/*    using C++", 2nd edition, Addison-Wesley, Ch.5         */
/************************************************************/

//---------------------------------------------------------------------
// File: node1.cpp
// Name: Michael Main, Walter Savitch
//       (adapted by Sharon M. Tuttle)
// last modified: 3-2-05
//
// Class name: node
//
// Purpose: serves as the unit from which a singly-linked list
//    can be built.
// 
//    Also included in this file are a collection of
//    useful list-manipulation functions, called the 
//    "linked list toolkit"
//
// DYNAMIC MEMORY USAGE by the node class and linked list toolkit:
//    If there is insufficient dynamic memory, then the
//       following functions throw bad_alloc:
//          the contructors, 
//          list_head_insert, list_insert, list_copy, list_piece
//
// NOTE: 
//    Some of the methods and functions have return value that is
//       a pointer to a node. Each of these functions comes in TWO
//       versions: a non-const version (where the return value is
//       node*) and a const version (where the return value is
//       const node*).
//---------------------------------------------------------------------

#include <cassert>
#include "node1.h"
using namespace std;

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

//---------------------------------------------------------------------
// postcondition: creates a node with data_field obtained from
//    the default constructor of the value_type, and
//    next_field set to NULL.
//
// NOTE: In the ANSI/ISO standard, this default-constructor
//     notation is also allowed for the built-in types, 
//     providing a default value of zero.
//
node::node( )
{
    data_field = value_type();
    next_field = NULL;
}  

//---------------------------------------------------------------------
// postcondition: creates a node with data_field set to
//    init_data, and next_field set to NULL.
//
node::node(const value_type& init_data)
{
    data_field = init_data;
    next_field = NULL;
}

//---------------------------------------------------------------------
// postcondition: create a node with data_field obtained from
//    the default constructor of the value_type, and
//    next_field set to init_next.
//
node::node(node* init_next)
{
    data_field = value_type();
    next_field = init_next;
}

//---------------------------------------------------------------------
// postcondition: create a node with data_field set to
//    init_data, and next_field set to init_next.
//
node::node(const value_type& init_data, node* init_next)
{
    data_field = init_data;
    next_field = init_next;
}

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

//---------------------------------------------------------------------
// postcondition: returns the data from this node
//
node::value_type node::get_data( ) const
{
    return data_field;
}
   
//---------------------------------------------------------------------
// postcondition: returns the next pointer from this node.
//    (See note above --- need both a const and non-const
//    version of this, because it returns a pointer.
//    See also pp. 219-221 of Savitch and Main, 3rd edition.)
//
const node* node::get_next( ) const
{
    return next_field;
}

node* node::get_next( )
{
    return next_field;
}
        
/*****************************************************/
/* MODIFIERS and other modifying member functions    */
/*****************************************************/

//---------------------------------------------------------------------
// postcondition: the node now contains the specified
//    new_data.
//
void node::set_data(const value_type& new_data)
{
    data_field = new_data;
}

//---------------------------------------------------------------------
// postcondition: the node now contains the specified
//    new_next pointer.
//
void node::set_next(node* new_next)
{
    next_field = new_next;
}
        
/****************************************************/
/* NONMEMBER FUNCTIONS for the node class           */
/****************************************************/
       
//----------------------------------------------
// HERE, these are functions for the so-called 
//    LINKED LIST TOOLKIT.
//----------------------------------------------

//---------------------------------------------------------------------
// function: list_length
//
// preconditions: head_ptr is the head pointer of a linked list
//
// postconditions: the value returned in the number of nodes in
//    the linked list
//
// Examples: if node* begin_ptr is the first node in a linked list of
//    3 nodes, then:
//       list_length(begin_ptr) == 3
//    if node* empty_ptr = NULL,
//       list_length(empty_ptr) == 0
//    
size_t list_length(const node* head_ptr)
{
    const node *cursor;
    size_t answer;

    answer = 0;
    for (cursor = head_ptr; cursor != NULL; cursor = cursor->get_next( ))
    {
        answer++;
    }     
   
    return answer;
}

//---------------------------------------------------------------------
// function: list_head_insert
//
// preconditions: head_ptr is the head pointer of a linked list.
//
// postconditions: 
//    *   a new node containing the given entry has been
//        added at the head of the linked list; 
//    *   head_ptr now points to the head of the new, longer
//        linked list
//
// Examples: if node* begin_ptr points to a list containing 8 2 7,
//    and value_type is int,
//    then list_head_insert(begin_ptr, 5)
//       results in a list containing 5 8 2 7;
//       that is, begin_ptr->get_data( ) == 5,
//                list_length(begin_ptr) == 4    
//    if node* empty_ptr = NULL, 
//    then list_head_insert(empty_ptr, 5)
//       results in a list containing 5;
//       that is, empty_ptr->get_data( ) == 5,
//                list_length(empty_ptr) == 1
//
void list_head_insert(node*& head_ptr, const node::value_type& entry)
{
    node* temp;

    temp = new node(entry);

    // temp will be pointing to the new first node --- so
    //    this new node's next_field should be pointing
    //    to the OLD first node...
    //
    temp->set_next(head_ptr);

    // and now it is safe to reset head_ptr to its new first node
    head_ptr = temp;
}

//---------------------------------------------------------------------
// function: list_insert
//
// preconditions: previous_ptr points to a node in a linked list.
//
// postconditions: a new node containing the given entry has been added
//    after the node that previous_ptr points to.
//
// Examples: if you have a linked list 8 5 2 7,
//    and prev_ptr points to the node containing 8, 
//       then list_insert(prev_ptr, 9) results in the list 8 9 5 2 7,
//       and prev_ptr->get_next()->get_data() == 9;
//    if prev_ptr2 points to the node containing 7, 
//       then list_insert(prev_ptr2, 6) results in the list 8 9 5 2 7 6,
//       and prev_ptr->get_next()->get_data() == 6;
//    if prev_ptr3 points to the node containing 5, 
//       then list_insert(prev_ptr3, 4) results in the list 8 9 5 4 2 7 6,
//       and prev_ptr->get_next()->get_data() == 4;
//
void list_insert(node* previous_ptr, const node::value_type& entry)
{
    node *insert_ptr;

    insert_ptr = new node(entry);
    
    // newly-inserted node needs to point to the one AFTER
    //    the previous_ptr's node;
    insert_ptr->set_next(previous_ptr->get_next( ));

    // now, the previous_ptr's node needs to now know that
    //    the NEW node comes next after it;
    previous_ptr->set_next(insert_ptr);
}

//---------------------------------------------------------------------
// function: list_search
//    (See note above --- need both a const and non-const version
//    of this, because it returns a pointer. 
//    See also pp. 219-221 of Savitch and Main, 3rd edition.)
//    
// preconditions: head_ptr is the head pointer of a linked list
//
// postconditions: the pointer returned points to the first node containing
//    the specified target in its data member. If there is no such node,
//    the NULL pointer is returned.
//
// Examples: for the linked list containing 8 5 2 7 8 10,
//    assuming that node* begin_ptr points to its head, and
//    assuming that node* result_ptr,
//    if result_ptr = list_search(begin_ptr, 8),
//        then result_ptr->get_data() == 8
//    if result_ptr = list_search(begin_ptr, 10),
//        then result_ptr->get_data() == 10
//    if result_ptr = list_search(begin_ptr, 2),
//        then result_ptr->get_data() == 2
//    if result_ptr = list_search(begin_ptr, 13),
//        then result_ptr == NULL
//    
node* list_search(node* head_ptr, const node::value_type& target)
{
    node *cursor;
   
    for (cursor = head_ptr; cursor != NULL; cursor = cursor->get_next( ))
    {
        if (target == cursor->get_data( ))
        {
            return cursor;
        }
    }

    // if REACH here (didn't return in loop), then target NOT in list
    return NULL;
}

const node* list_search(const node* head_ptr, 
                        const node::value_type& target)
{
    const node *cursor;
   
    for (cursor = head_ptr; cursor != NULL; cursor = cursor->get_next( ))
    {
        if (target == cursor->get_data( ))
        {
            return cursor;
        }
    }

    // if REACH here (didn't return in loop), then target NOT in list
    return NULL;
}

//---------------------------------------------------------------------
// function: list_locate
//    (See note above --- need both a const and non-const version
//    of this, because it returns a pointer. 
//    See also pp. 219-221 of Savitch and Main, 3rd edition.)
//
// preconditions: 
//    *   head_ptr is the head pointer of a linked list
//    *   position > 0
//
// postconditions:
//    *   The pointer returned points to the node at the specified
//        position in the list. (The head node is position 1, the next node
//        is position 2, and so on.)
//    *   If there is no such position, then the NULL pointer is returned.
//
// Examples: for the linked list containing 8 5 2 7 8 10,
//    assuming that node* begin_ptr points to its head, and
//    assuming that node* result_ptr,
//    if result_ptr = list_search(begin_ptr, 1),
//        then result_ptr->get_data() == 8
//    if result_ptr = list_search(begin_ptr, 6),
//        then result_ptr->get_data() == 10
//    if result_ptr = list_search(begin_ptr, 3),
//        then result_ptr->get_data() == 2
//    if result_ptr = list_search(begin_ptr, 13),
//        then result_ptr == NULL
//    
node* list_locate(node* head_ptr, size_t position)
{
    node *cursor;
    size_t i;
    
    assert (position > 0);
    cursor = head_ptr;

    // remember: head of list is position 1, in THIS function!!!
    for (i = 1; (i < position) && (cursor != NULL); i++)
    {
        cursor = cursor->get_next( );
    }

    return cursor;
}

const node* list_locate(const node* head_ptr, size_t position)
{
    const node *cursor;
    size_t i;
    
    assert (position > 0);
    cursor = head_ptr;

    // remember: head of list is position 1, in THIS function!!!
    for (i = 1; (i < position) && (cursor != NULL); i++)
    {
        cursor = cursor->get_next( );
    }

    return cursor;
}

//---------------------------------------------------------------------
// function: list_head_remove
//
// preconditions: head_ptr is the head pointer of a linked list with
//    at least one node;
//
// postconditions:
//    *   the head node has been removed and returned to the heap;
//    *   head_ptr is now the head pointer of the new, shorter linked
//        list
//
// Examples: for the linked list containing 8 5 2 7,
//    assuming that node* begin_ptr points to its head,
//       then list_head_remove(begin_ptr) results in the linked
//          list 5 2 7,
//       and list_length(begin_ptr) == 3,
//       and begin_ptr->get_data() == 5.
//    for the linked list containing 13,
//    assuming that begin_ptr2 points to its head,
//       then list_head_remove(begin_ptr2) results in an empty list,
//       and list_length(begin_ptr) == 0,
//       and begin_ptr == NULL
//
void list_head_remove(node*& head_ptr)
{
    node *remove_ptr;

    remove_ptr = head_ptr;
    head_ptr = head_ptr->get_next( );
    delete remove_ptr;
}

//---------------------------------------------------------------------
// function: list_remove
//
// preconditions: previous_ptr points to a node in a linked list, and this
//    is NOT the tail node of the list.
//
// postconditions: The node *after* previous_ptr has been removed from
//    the linked list.
//
// Examples: for the linked list containing 8 5 2 7 8 10,
//    assuming that node* begin_ptr points to its head,
//       then list_remove(begin_ptr) results in the linked
//          list 8 2 7 8 10,
//       and list_length(begin_ptr) == 5,
//       and begin_ptr->get_next()->get_data() == 2;
//    for the linked list containing 8 2 7 8 10,
//    assuming that prev_ptr2 points to the node containing 7,
//    and begin_ptr points to its head,
//       then list_remove(prev_ptr2) results in the list 8 2 7 10,
//       and list_length(begin_ptr) == 4,
//       and prev_ptr2->get_next()->get_data() == 10;
//    for the linked list containing 8 2 7 10,    
//    assuming that prev_ptr2 points to the node containing 7,
//    and begin_ptr points to its head,
//       then list_remove(prev_ptr2) results in the list 8 2 7,
//       and list_length(begin_ptr) == 3,
//       and prev_ptr2->get_next() == NULL.
//
void list_remove(node* previous_ptr)
{
    node *remove_ptr;

    remove_ptr = previous_ptr->get_next( );
    previous_ptr->set_next( remove_ptr->get_next( ) );
    delete remove_ptr;
}

//---------------------------------------------------------------------
// function: list_clear
//
// preconditions: head_ptr is the head pointer of a linked list.
//
// postconditions: 
//    *   all nodes of the list have been returned to the heap;
//    *   head_ptr is now NULL
//
// Examples: for the linked list containing 8 5 2 7 8 10,
//    assuming that node* begin_ptr points to its head,
//       then list_clear(begin_ptr) results in an empty linked list,
//       and list_length(begin_ptr) == 0,
//       and begin_ptr == NULL.
//    for an empty linked list,
//    assuming that node* begin_ptr2 == NULL,
//       then list_clear(begin_ptr2) results in an empty linked list,
//       and list_length(begin_ptr2) == 0,
//       and begin_ptr2 == NULL.
//    
void list_clear(node*& head_ptr)
{
    while (head_ptr != NULL)
    {
        list_head_remove(head_ptr);
    }
}

//---------------------------------------------------------------------
// function: list_copy
//
// preconditions: source_ptr is the head_ptr of a linked list
//      
// postconditions:
//    *   head_ptr and tail_ptr are the head and tail pointers for a
//        a new list that contains the same items as the list pointed
//        to by source_ptr.
//    *   the original list is unaltered.
//
// Examples: for the linked list containing 8 5 2 7,
//    assuming that node* begin_ptr points to its head,
//    and node* new_head, node* new_tail have been declared,
//       then list_copy(begin_ptr, new_head, new_tail) results in 
//          a new linked list copy containing 8 5 2 7,
//       and list_length(new_head) == 4,
//       and new_head->get_data() == 8,
//       and new_tail->get_data() == 7;
//    for an empty linked list,
//    assuming that node* begin_ptr2 == NULL,
//    and node* new_head2, node* new_tail2 have been declared,
//       then list_copy(begin_ptr2, new_head2, new_tail2) results in 
//          a new empty linked list,
//       and list_length(begin_ptr2) == 0,
//       and new_head2 == NULL,
//       and new_tail2 == NULL;
//    for a linked list containing 13,
//    assuming that node* begin_ptr3 points to the beginning of this list,
//    and node* new_head3, node* new_tail3 have been declared,
//       then list_copy(begin_ptr3, new_head3, new_tail3) results in
//          a new linked list containing 13,
//       and list_length(begin_ptr3) == 1,
//       and new_head3->get_data() = 13, 
//       and new_tail3->get_data() = 13;
//    
void list_copy(const node* source_ptr, 
               node*& head_ptr, node*& tail_ptr)
{
    head_ptr = NULL;
    tail_ptr = NULL;

    // Handle the case of the empty list.
    if (source_ptr == NULL)
    {
        return;
    }
    
    // Make the head node for the newly created list, and put data in it.
    list_head_insert(head_ptr, source_ptr->get_data( ));
    tail_ptr = head_ptr;
    
    // Copy the rest of the nodes one at a time, adding at the tail 
    //    of new list.
    source_ptr = source_ptr->get_next( ); 
    while (source_ptr != NULL)
    {
        list_insert(tail_ptr, source_ptr->get_data( ));
        tail_ptr = tail_ptr->get_next( );
        source_ptr = source_ptr->get_next( );
    }
}