Nyhoff, ADTs, Data Structures and Problem Solving with C++, Second Edition, 
2005 Pearson Education, Inc. All rights reserved. 0-13-140909-3 

 

 

Figure 6.1A List.h Using Static Array

/*-- List.h ---------------------------------------------------------------
 
  This header file defines the data type List for processing lists.
  Basic operations are:
     Constructor
     empty:    Check if list is empty
     insert:   Insert an item
     erase:    Remove an item
     display:  Output the list
     <<, >> :  input and output operators
-------------------------------------------------------------------------*/

#include <iostream>

#ifndef LIST
#define LIST

const int CAPACITY = 1024;
typedef int ElementType;

class List
{
 public:
 /******** Function Members ********/
   /***** Class constructor *****/
   List();
   /*----------------------------------------------------------------------
     Construct a List object.

     Precondition:  None
     Postcondition: An empty List object has been constructed;
         mySize is 0.
   -----------------------------------------------------------------------*/

   /***** empty operation *****/
   bool empty() const;
   /*----------------------------------------------------------------------
     Check if a list is empty.

     Precondition:  None
     Postcondition: true is returned if the list is empty, 
         false if not.
   -----------------------------------------------------------------------*/

   /***** insert and erase *****/
   void insert(ElementType item, int pos);
   /*----------------------------------------------------------------------
     Insert a value into the list at a given position.

     Precondition:  item is the value to be inserted; there is room in 
         the array (mySize < CAPACITY); and the position satisfies
         0 <= pos <= mySize. 
     Postcondition: item has been inserted into the list at the position
         determined by pos (provided there is room and pos is a legal
         position).
   -----------------------------------------------------------------------*/

   void erase(int pos);
   /*----------------------------------------------------------------------
     Remove a value from the list at a given position.

     Precondition:  The list is not empty and the position satisfies
         0 <= pos < mySize.
     Postcondition: element at the position determined by pos has been
         removed (provided pos is a legal position).
   ----------------------------------------------------------------------*/

   /***** output *****/
   void display(ostream & out) const;
   /*----------------------------------------------------------------------
     Display a list.

     Precondition:  out is a reference parameter 
     Postcondition: The list represented by this List object has been
         inserted into ostream out. 
   -----------------------------------------------------------------------*/

 private:
 /******** Data Members ********/
   int mySize;                     // current size of list stored in myArray
   ElementType myArray[CAPACITY];  // array to store list elements

}; //--- end of List class

//------ Prototype of output operator
ostream & operator<< (ostream & out, const List & aList);

#endif 

 

 

 

Figure 6.1B List.cpp Using Static Array

/*-- List.cpp------------------------------------------------------------
 
   This file implements List member functions.

-------------------------------------------------------------------------*/

#include <cassert>
using namespace std;

#include "List.h"

//--- Definition of class constructor
List::List()                 
: mySize(0)
{
}

//--- Definition of empty()
bool List::empty() const
{
   return mySize == 0;
}

//--- Definition of display()
void List::display(ostream & out) const
{
   for (int i = 0; i < mySize; i++)
     out << myArray[i] << "  ";
}

//--- Definition of output operator
ostream & operator<< (ostream & out, const List & aList)
{
   aList.display(out);
   return out;
}

//--- Definition of insert()
void List::insert(ElementType item, int pos)
{
   if (mySize == CAPACITY)
   {
      cerr << "*** No space for list element -- terminating "
              "execution ***\n";
      exit(1);
   }
   if (pos < 0 || pos > mySize)
   {
      cerr << "*** Illegal location to insert -- " << pos 
           << ".  List unchanged. ***\n";
      return;
   }

   // First shift array elements right to make room for item

   for(int i = mySize; i > pos; i--)
      myArray[i] = myArray[i - 1];

   // Now insert item at position pos and increase list size  
   myArray[pos] = item;
   mySize++;
}

// Definition of erase()
void List::erase(int pos)
{
   if (mySize == 0)
   {
      cerr << "*** List is empty ***\n";
      return;
   }
  if (pos < 0 || pos >= mySize)
   {
      cerr << "Illegal location to delete -- " << pos
           << ".  List unchanged. ***\n";
      return;
   }

   // Shift array elements left to close the gap
   for(int i = pos; i < mySize; i++)
       myArray[i] = myArray[i + 1];

   // Decrease list size
    mySize--;
} 

 

 

Figure 6.1C List Test Program

//--- Program to test List class.

#include <iostream>
using namespace std;

#include "List.h"

int main()
{
   // Test the class constructor
   List intList;
   cout << "Constructing intList\n";

   // Test empty() and output of empty list
   if (intList.empty())
      cout << "Empty List: \n"
           << intList << endl;       // Test output of empty list

   // Test insert()
   for (int i = 0; i < 9; i++)
   {
      cout << "Inserting " << i << " at position " << i/2 << endl;
      intList.insert(i, i/2);       //  -- Insert i at position i/2
      //Test output
      cout << intList << endl;
   }
   cout << "List empty? " << (intList.empty() ? "Yes" : "No") << endl;

   cout << "\nTry to insert at position -1" << endl;
   intList.insert(0, -1);
   cout << "\nTry to insert at position 10" << endl;
   intList.insert(0, 10);

   // Test erase
   int index;
   cout << endl;
   while (!intList.empty())
   {
      cout << "Give an index of a list element to remove: ";
      cin >> index;
      intList.erase(index);
      cout << intList << endl;
   }
   cout << "List is empty" << endl;

   cout << "\nInserting " << CAPACITY<< " integers\n";
   for (int i = 0; i < CAPACITY; i++)
     intList.insert(i, i);
   cout << "Attempting to insert one more integer:\n";
   intList.insert(-1, 0);

   return 0;
} 

 

 

 

Figure 6.2A List.h With Dynamic Allocation

/*-- List.h ---------------------------------------------------------------
 
  This header file defines the data type List for processing lists.
  Basic operations are:
     Constructor
     Destructor
     Copy constructor
     Assignment operator
     empty:    Check if list is empty
     insert:   Insert an item
     erase:    Remove an item
     display:  Output the list
     << :      Output operator
-------------------------------------------------------------------------*/

#include <iostream>

#ifndef LIST
#define LIST

typedef int ElementType;
class List
{
 public:
 /******** Function Members ********/
   /***** Class constructor *****/
   List(int maxSize = 1024);
   /*----------------------------------------------------------------------
     Construct a List object.

     Precondition:  maxSize is a positive integer with default value 1024.
     Postcondition: An empty List object is constructed; myCapacity ==
         maxSize (default value 1024); myArrayPtr points to a run-time
         array with myCapacity as its capacity; and mySize is 0.
   -----------------------------------------------------------------------*/


   /***** Class destructor *****/
   ~List();
   /*----------------------------------------------------------------------
     Destroys a List object.

     Precondition:  The life of a List object is over.
     Postcondition: The memory dynamically allocated by the constructor
         for the array pointed to by myArrayPtr has been returned to 
         the heap.
     ------------------------------------------------------------------*/

   /***** Copy constructor *****/
   List(const List & origList);
   /*----------------------------------------------------------------------
     Construct a copy of a List object.

     Precondition:  A copy of origList is needed; origList is a const
         reference parameter. 
     Postcondition: A copy of origList has been constructed.
   -----------------------------------------------------------------------*/

   /***** Assignment operator *****/
   List & operator=(const List & origList);
   /*----------------------------------------------------------------------
     Assign a copy of a List object to the current object.

     Precondition: none 
     Postcondition: A copy of origList has been assigned to this
          object.  A reference to this list is returned.
   -----------------------------------------------------------------------*/

   /***** empty operation *****/
   bool empty() const;
   /*----------------------------------------------------------------------
     Check if a list is empty.

     Precondition:  None
     Postcondition: true is returned if the list is empty, 
         false if not.
   -----------------------------------------------------------------------*/

   /***** insert and erase *****/
   void insert(ElementType item, int pos);
   /*----------------------------------------------------------------------
     Insert a value into the list at a given position.

     Precondition:  item is the value to be inserted; there is room in 
         the array (mySize < CAPACITY); and the position satisfies
         0 <= pos <= mySize. 
     Postcondition: item has been inserted into the list at the position
         determined by pos (provided there is room and pos is a legal
         position).
   -----------------------------------------------------------------------*/

   void erase(int pos);
   /*----------------------------------------------------------------------
     Remove a value from the list at a given position.

     Precondition:  The list is not empty and the position satisfies
         0 <= pos < mySize.
     Postcondition: element at the position determined by pos has been
         removed (provided pos is a legal position).
   ----------------------------------------------------------------------*/

   /***** output *****/
   void display(ostream & out) const;
   /*----------------------------------------------------------------------
     Display a list.

     Precondition:  The ostream out is open. 
     Postcondition: The list represented by this List object has been
         inserted into out. 
   -----------------------------------------------------------------------*/

 private:
 /******** Data Members ********/
   int mySize;                // current size of list stored in array
   int myCapacity;            // capacity of array
   ElementType * myArrayPtr;  // pointer to dynamically-allocated array

}; //--- end of List class

//------ Prototype of output operator
ostream & operator<< (ostream & out, const List & aList);

#endif 

 

 

 

Figure 6.2B List.cpp With Dynamic Allocation

/*-- List.cpp------------------------------------------------------------
 
   This file implements List member functions.

-------------------------------------------------------------------------*/

#include <cassert>
#include <new>
using namespace std;

#include "List.h"

//--- Definition of class constructor
List::List(int maxSize)
: mySize(0), myCapacity(maxSize)
{
   myArrayPtr = new(nothrow) ElementType[maxSize];
   assert(myArrayPtr != 0);
}

//--- Definition of class destructor
List::~List()
{
   delete [] myArrayPtr;
}

//--- Definition of the copy constructor
List::List(const List & origList)
: mySize(origList.mySize), myCapacity(origList.myCapacity)

{
  //--- Get new array for copy
   myArrayPtr = new(nothrow) ElementType[myCapacity];

   if (myArrayPtr != 0)                 // check if memory available
      //--- Copy origList's array into this new array
      for(int i = 0; i < myCapacity; i++)
         myArrayPtr[i] = origList.myArrayPtr[i];
   else
   {
      cerr << "*Inadequate memory to allocate stack ***\n";
      exit(1);
   }
}

//--- Definition of the assignment operator
List & List::operator=(const List & origList)
{
   if (this != &origList)    // check for list = list
   {
      mySize = origList.mySize;
      myCapacity = origList.myCapacity;

      //-- Allocate a new array if necessary
      if (myCapacity != origList.myCapacity) 
      {
         delete[] myArrayPtr;
         myArrayPtr = new(nothrow) ElementType[myCapacity];

         if (myArrayPtr == 0)   // check if memory available
         {
            cerr << "*Inadequate memory to allocate stack ***\n";
            exit(1);
         }
      }
      //--- Copy origList's array into this new array
      for(int i = 0; i < myCapacity; i++)
         myArrayPtr[i] = origList.myArrayPtr[i];
   }
   return *this;
}

//--- Definition of empty()
bool List::empty() const
{
   return mySize == 0;
}

//--- Definition of display()
void List::display(ostream & out) const
{
   for (int i = 0; i < mySize; i++)
     out << myArrayPtr[i] << "  ";
}

//--- Definition of output operator
ostream & operator<< (ostream & out, const List & aList)
{
   aList.display(out);
   return out;
}

//--- Definition of insert()
void List::insert(ElementType item, int pos)
{
   if (mySize == myCapacity)
   {
      cerr << "*** No space for list element -- terminating "
              "execution ***\n";
      exit(1);
   }
   if (pos < 0 || pos > mySize)
   {
      cerr << "*** Illegal location to insert -- " << pos 
           << ".  List unchanged. ***\n";
      return;
   }

   // First shift array elements right to make room for item

   for(int i = mySize; i > pos; i--)
      myArrayPtr[i] = myArrayPtr[i - 1];

   // Now insert item at position pos and increase list size  
   myArrayPtr[pos] = item;
   mySize++;
}

//--- Definition of erase()
void List::erase(int pos)
{
   if (mySize == 0)
   {
      cerr << "*** List is empty ***\n";
      return;
   }
  if (pos < 0 || pos >= mySize)
   {
      cerr << "Illegal location to delete -- " << pos
           << ".  List unchanged. ***\n";
      return;
   }

   // Shift array elements left to close the gap
   for(int i = pos; i < mySize; i++)
       myArrayPtr[i] = myArrayPtr[i + 1];

   // Decrease list size
    mySize--;
} 

 

 

 

Figure 6.2C List Testing Program

/* listtester.cpp is a program for testing class List. */

#include <iostream>
using namespace std;

#include "List.h"
                                  // f() is a function with 
void f(List aList)                // List value parameter
{                                 // to test the copy constructor
  for (int i = 1; i < 5; i++)
  {
     aList.insert(100*i, i);      // insert into the copy
     cout << aList << endl;       // output the copy
  }
}

int main()
{
   // Test the class constructor
   List intList;
   cout << "Constructing intList\n";

   // Test empty() and output of empty list
   if (intList.empty())
      cout << "Empty List: \n"
           << intList << endl;       // Test output of empty list


   // Test insert()
   for (int i = 0; i < 9; i++)
   {
      intList.insert(i, i/2);       //  -- Insert i at position i/2
      //Test output
      cout << intList << endl;
   }
   cout << "List empty? " << (intList.empty() ? "Yes" : "No") << endl;


   // Test destructor
   {
      List anotherList;
      for (int i = 0; i < 10; i++)
         anotherList.insert(100*i, i);
      cout << "\nHere's another list:\n" << anotherList << endl;
      cout << "Now destroying this list\n";
   }

   // Test the copy constructor
   cout << "\n\n";
   f(intList);

   cout << "\n\nOriginal list:";      // Output the original to make 
   cout << intList<< endl;            //  sure it hasn't been changed

   // Test erase
   int index;
   while (!intList.empty())
   {
      cout << "Give an index of list element to remove: ";
      cin >> index;
      intList.erase(index);
      cout << intList << endl;
   }
   cout << "List is empty" << endl;
} 

 

 

 

Figure 6.3 Calls to Constructors and Destructor

/*-------------------------------------------------------------------------
   This program demonstrates how often a class's constructor,
   destructor, and copy constructor can get called automatically
   by the compiler.  It uses the List class from Fig. 4.2 but with
   output statements inserted into the constructor, destructor, 
   and copy constructor to trace when they are called.
-------------------------------------------------------------------------*/

#include <iostream>
using namespace std;

#include "List.h"

void print (List aList)
/*-------------------------------------------------------------------------
   Function to print a list.

   Precondition:  aList is a value parameter
   Postcondition: Contents of aList have been displayed
-------------------------------------------------------------------------*/
{
   cout << aList << endl;
}

int main()
{
   int listLimit;
   cout << "Enter maximum number of list elements: ";
   cin >> listLimit;

   cout << "\n*** Next Statement:  List list1(listLimit);\n";
   List list1(listLimit);
   for (int i = 0; i <= 4; i++)
   {
      cout << "*** Next Statement:  list1.insert(i, i);\n";
      list1.insert(i, i);
   }
   cout << "\n*** Next Statement:  List list2 = list1;\n";
   List list2 = list1;
   cout << "\n*** Next Statement:  print(list2);\n";
   print(list2);
   cout << "\n*** Next Statement:  List list3;\n";
   List list3;
   cout << "\n*** Next Statement:  list3 = list2;\n";
   list3 = list2;
   cout << "\n*** Next Statement:  print(list3);\n";
   print(list3);

   cout << "\n*** Next Statement:  return 0;\n";
   return 0;
} 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure