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 |
|
|