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

 

 

Polynomial Class Declaration

#ifndef POLYNOMIAL
#define POLYNOMIAL

template <typename CoefType>
class Polynomial
{
private:
   /*** Term class  ***/
   class Term
   {
   public:
   /*** Data members ***/
   CoefType coef:
      unsigned expo;
   }; // end class Term

   /*** Node Class ***/
   class Node
   {
   public:
      Term data;
      Node * next;

      // -- Node constructor
      // creates a node with given initial values
      Node (CoefType co = 0, int x = 0, Node * ptr = 0)
      {
         data.coef = co;
         data.expo = ex;
         next = ptr;
      }
   }; // end of Node class

   public:
   /*** Function members ***/
   // operations on polynomials

   private:
   /*** Data members ***/
   int myDegree;
   NodePointer myTerms; // a linked list with head node;
                        // its ElementType is Term
}; // end of Polynomial class template
#endif

 

 

 

Addition Operator for Polynomial Class

Polynomial <CoefType> operator+(
        const Polynomial <CoefType> & secondPoly)
/*------------------------------------------------
   Precondition: None
   Postcondition: A polynomial representing the sum of
      the current polynomial and secondPoly is returned.
--------------------------------------------------*/

{
   Polynomial <CoefType> polySum;
   Poly<CoefType>::NodePointer         // pointers to
      ptra = myTerms->next.            // thru 1st poly.
      ptrb = secondPoly.myTerms->next, // 2nd poly,
      ptrc = polySum.myTerms;          // sum poly
   int degree = 0;
   while (ptra != 0 || ptrb != 0)      // More nodes in
   {                                   // one of polys
      if ((ptrb == 0) ||               // Copy from 1st poly
          (ptra != 0 && ptra->data.expo < ptrb->data.expo))
      {
         ptrc->next = new Polynomial<coefTpe>::
            Node(ptra->data.coef, ptra->data.expo);
         degree = ptra->data.expo;
         ptra = ptra->next;
         ptrc = ptrc->next;
      }
      else if ((ptra == 0) ||          // Copy from 2nd poly
               (ptrb != 0 && ptrb->expo < ptra<expo))
      {
         ptrc->nwext = new Polynomial<CoefType>::
            Node(ptrb->data.coef, ptrb->data.expo);
         degree = ptrb->data.expo;
         ptrb = ptrb->next;
         ptrc = ptrc->next;
      }
      else                             // exponents match
      {
         CoefType sum = ptra->data.coef + ptrb.data.coef;
         if (sum != 0)                 // Nonzero sum --
         {                             // add to sum poly
            ptrc->next = new Polynomial<CoefType>::
               Node(sum, ptra->data.expo);
            degree = ptra->data.expo;
            ptrc = ptrc->next;
         }
         ptra = ptra->next;            // Move along in
         ptrb = ptrb->next;            //  1st and 2nd lists
      }
   }
   sumPoly.myDegree = degree;          // Wrapup
   return sumPoly;
} 

 

 

Figure 11.1 Demonstration of list Operations

#include <iostream>
#include <list>
#include <algorithm>
using namespace std;

//--- Overload output operator for list<T>
template <typename T>
ostream & operator<<(ostream & out, const list<T> & aList)
{
   for (list<T>::const_iterator it = aList.begin(); it != aList.end(); it++)
      out << *it << " ";
   return out;
}

int main()
{
   // Constructors
   //=============
   list<int> la, lb(4, 111), lc(6);
   int array[] = {2, 22, 222,2222};
   list<int> ld(array, array + 4);

   cout << "la: " << la << " -- size = " << la.size() << endl;
   cout << "lb: " << lb << " -- size = " << lb.size() << endl;
   cout << "lc: " << lc << " -- size = " << lc.size() << endl;
   cout << "ld: " << ld << " -- size = " << ld.size() << endl;

   // Assignment
   //===========
   cout << "\nAssignments la = ld and lc = ld:" << endl;
   la = ld;
   lc = ld;
   cout << "la = " << la << " -- size = " << la.size() << endl;
   cout << "lc = " << lc << " -- size = " << lc.size() << endl;
 
   // Ways to insert into a list
   //===========================
   cout << "\nInserts in lb:\n";
   list<int>::iterator i;
   i = lb.begin();
   i++; i++;
   lb.insert(i, 66666);
   cout << lb << endl;
   lb.insert(i,3, 555);
   cout << lb << endl;
   lb.insert(i, array, array + 3);
   cout << lb << endl;
   lb.push_back(888);
   lb.push_front(111);
   cout << lb << endl;
  
   // Ways to delete from a list
   //===========================
   cout << "\nErases in lb:\n";
   i = find(lb.begin(), lb.end(), 66666);  // find is an algorithm
   if (i != lb.end())
   {
      cout << "66666 found -- will erase it\n";
      lb.erase(i);
   }
   else
      cout << "66666 not found\n";
   cout << lb << endl;
   i = lb.begin(); i++;
   list<int>::iterator j = lb.end();
   --j; --j; i = --j; i --; i--;
   lb.erase(i,j);
   cout << lb << endl;
   lb.pop_back();
   lb.pop_front();
   cout << lb << endl;

   // Reversing a list
   //=================
   cout << "\nReverse ld:\n";
   ld.reverse();
   cout << ld << endl;
 
   // Sorting a list
   //===============
   cout << "\nSort lb and ld:\n";
   lb.sort();
   ld.sort();
   cout << "lb: " << lb << "\nld: " << ld << endl;
 
   // Merging two lists
   //==================
   cout << "\nMerge lb and ld:\n";
   lb.merge(ld);
   cout << "lb: " << lb << endl;
   cout << "ld: " << ld << endl;

   // Splicing a list into another list
   //==================================
   cout << "\nSplice lc into la at second position:\n";
   i=la.begin(); i++;
   la.splice(i, lc);
   cout << "la: " << la << endl;
   cout << "lc: " << lc << endl;

   // Global removal of a value
   //==========================
   cout << "\nRemove 22s from la:\n";
   la.remove(22);
   cout << la << endl;

   // Eliminating duplicates
   //=======================
   cout << "\nUnique applied to lb:\n";
   lb.unique();
   cout << lb << endl;
} 

 

 

 

Figure 11.2 Internet Addresses

/*-- Class AddressCounter --------------------------------------------------
             Models occurrences of IP addresses in a login file.
 -------------------------------------------------------------------------*/

#include <string>
#include <iostream>
using namespace std;

class AddressCounter
{
 public:
  /*** Function Members ***/
  AddressCounter();
  /*------------------------------------------------------------------------
    Precondition:  None.
    Postcondition: myAddress is an empty string and myCount is 0.
   -----------------------------------------------------------------------*/
  
  void read(istream & in);
  /*------------------------------------------------------------------------
    Precondition:  istream in is open.
    Postcondition: Value for AddressCounter has been read from in.
   -----------------------------------------------------------------------*/
 
  void print(ostream & out) const;
  /*------------------------------------------------------------------------
    Precondition:  ostream out is open.
    Postcondition: Value of AddressCounter has been output to out.
   -----------------------------------------------------------------------*/

  void tally();
  /*------------------------------------------------------------------------
    Precondition:  None.
    Postcondition: myCount has been incremented by 1.
   -----------------------------------------------------------------------*/

  bool operator==(const AddressCounter & addr);
  /*------------------------------------------------------------------------
    Precondition:  None.
    Postcondition: True is returned if this address and addr have the
        same address, and false otherwise.
   -----------------------------------------------------------------------*/

 private:
  /*** Data Members ***/
  string myAddress;
  int myCount;
}; // end of class declaration

//--- Definition of constructor
inline AddressCounter::AddressCounter()
: myAddress(""), myCount(0)
{ }

//--- Definition of read()
inline void AddressCounter::read(istream & in)
{
  in >> myAddress;
  myCount = 1;
}

//--- Definition of print()
inline void AddressCounter::print(ostream & out) const
{
  out << myAddress << "\t occurs " << myCount << " times\n";
}

//--- Definition of tally()
inline void AddressCounter::tally()
{
  myCount++;
}

//--- Definition of == operator
inline bool AddressCounter::operator==(const AddressCounter & addr)
{
  return myAddress == addr.myAddress;
}


/*--------------------------------------------------------------------------
  Program to read IP addresses from a file and produce a list of distinct
  addresses and a count of how many times each appeared in the file. 
 -------------------------------------------------------------------------*/

#include <fstream>
#include <cassert>
#include <list>
#include <algorithm>

int main()
{
   string fileName;                    // name of file of IP addresses
   ifstream inStream;                  // open stream to file of addresses
   cout << "Enter name of file containing IP addresses: ";
   cin >> fileName;
   inStream.open(fileName.data());
   assert(inStream.is_open());
 
   list<AddressCounter> addressList;   // list of AddressCounter objects
   AddressCounter addr;
   for (;;)                            // loop:
   {
      addr.read(inStream);             //   read an address

      if (inStream.eof()) break;       //   if eof, quit

      list<AddressCounter>::iterator   //   check if addr already in list
         it = find(addressList.begin(), addressList.end(), addr);
      if (it != addressList.end())     //   found
         (*it).tally();                //   increment its count
      else
         addressList.push_back(addr);  //   else add it to the list
   }                                   //   end loop
                                       //   output the list
   cout << "\nList of addresses:\n\n";
   for (list<AddressCounter>::iterator it = addressList.begin();
                                       it != addressList.end(); it++)
      (*it).print(cout);
} 

 

 

 

Figure 11.3A BigInt.h

/*-- BigInt.h -------------------------------------------------------------
 
  This header file defines the data type BigInt for processing 
  integers of any size.
  Basic operations are:
     Constructor
     +:         Addition operator
     read():    Read a BigInt object
     display(): Display a BigInt object
     <<, >> :   Input and output operators
-------------------------------------------------------------------------*/

#include <iostream>
#include <iomanip>       // setfill(), setw()
#include <list>

#ifndef BIGINT
#define BIGINT

const int DIGITS_PER_BLOCK = 3;
class BigInt
{
 public:
  /******** Function Members ********/
  /***** Constructor *****/
  // Let the list<short int> constructor take care of this.

  /***** read *****/
  void read(istream & in);
  /*-----------------------------------------------------------------------
    Read a BigInt.
    Precondition:  istream in is open anc cdntains blocks of nonnegative
        integers having at most DIGITS_PER_BLOCK digits per block.
    Postcondition: Blocks have been removed from in and added to myList.
   -----------------------------------------------------------------------*/

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

    Precondition:  ostream out is open.
    Postcondition: The large integer represented by this BigInt object
        has been formatted with the usual comma separators and inserted
        into ostream out. 
  ------------------------------------------------------------------------*/

  /***** addition operator *****/
  BigInt operator+(BigInt addend2);
  /*------------------------------------------------------------------------
    Add two BigInts.
    Precondition:  addend2 is the second addend.
    Postcondition: The BigInt representing the sum of the large integer
       represented by this BigInt object and addend2 is returned.
  ------------------------------------------------------------------------*/

 private:
  /*** Data Members ***/
  list<short int> myList;
};  // end of BigInt class declaration

//------ Input and output operators
inline istream & operator>>(istream & in, BigInt & number)
{
  number.read(in);
  return in;
}

inline ostream & operator<<(ostream & out, const BigInt & number)
{
  number.display(out);
  return out;
}

#endif 

 

 

 

Figure 11.3B BigInt.cpp

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

#include <iostream>
using namespace std;

#include "BigInt.h"

//--- Definition of read()
void BigInt::read(istream & in)
{
  static bool instruct = true;
  if (instruct)
  {
     cout << "Enter " << DIGITS_PER_BLOCK << "-digit blocks, separated by "
            "spaces.\nEnter a negative integer in last block to signal "
            "the end of input.\n\n";
    instruct = false;
  }
  short int block;
  const short int MAX_BLOCK = (short) pow(10.0, DIGITS_PER_BLOCK) - 1;
  for (;;)
  {
    in >> block;
    if (block < 0) return;

    if (block > MAX_BLOCK)
      cerr << "Illegal block -- " << block << " -- ignoring\n";
    else
      myList.push_back(block);
  }
}

//--- Definition of display()
void BigInt::display(ostream & out) const
{ 
   int blockCount = 0;
   const int BLOCKS_PER_LINE = 20;   // number of blocks to display per line

   for (list<short int>::const_iterator it = myList.begin(); ; )
   {
       out << setfill('0'); 
       if (blockCount == 0)
          out << setfill(' '); 
 
     if (it == myList.end())
         return;

      out << setw(3) << *it;
      blockCount++ ;

      it++;
      if (it != myList.end())
      {
         out << ',';
         if (blockCount > 0 && blockCount % BLOCKS_PER_LINE == 0)
            out << endl;
      }
   }
}

//--- Definition of operator+()
BigInt BigInt::operator+(BigInt addend2){
   BigInt sum;
   short int first,                  // a block of 1st addend (this object)
             second,                 // a block of 2nd addend (addend2)
             result,                 // a block in their sum
             carry = 0;              // the carry in adding two blocks

   list<short int>::reverse_iterator // to iterate right to left
      it1 = myList.rbegin(),         //   through 1st list, and
      it2 = addend2.myList.rbegin(); //   through 2nd list

   while (it1 != myList.rend() || it2 != addend2.myList.rend())
   {
      if (it1 != myList.rend())
      { 
         first = *it1;
         it1++ ;
      }
      else
         first = 0;
      if (it2 != addend2.myList.rend())
      {
         second = *it2;
         it2++ ;
      }
      else
         second = 0;

      short int temp = first + second + carry;
      result = temp % 1000;
      carry = temp / 1000;
      sum.myList.push_front(result);
   }

   if (carry > 0)
      sum.myList.push_front(carry);

   return sum;
} 

 

 

 

Figure 11.4 Driver Program for BigInt Class

//--- Program to test BigInt class.

#include <iostream>
using namespace std;

#include "BigInt.h"

int main()
{
   char response;
   do
   {
      BigInt number1, number2;
      cout <<"Enter a big integer:\n";
      cin >> number1;
      cout <<"Enter another big integer:\n";
      cin >> number2;

      cout << "The sum of\n\t"
           << number1 << "\nand\n\t" << number2
           << "\nis\n\t" << number1 + number2 << endl;

      cout << "\nAdd more integers (Y or N)? ";
      cin >> response;
   }
   while (response == 'y' || response == 'Y');
} 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure

 

 

 

 

Figure