C++ SparseArray class using inner class

Description

C++ SparseArray class using inner class

 
#include <iostream>
#include <exception>
#include <stdexcept>
#include <string>
#include <iomanip>
#include <memory>
 
using std::string;
 
class SparseArray
{
class Element;//from  w  ww.  j  a va2  s.  c  o m
using PElement = std::shared_ptr<Element>;
private:
  PElement pFirst;                                                        // Pointer to first non-zero element element
  PElement pLast;                                                         // Pointer to last non-zero element element
  int maxElements {};
 
public:
  SparseArray(int n) : maxElements {n} {}                              // Constructor
  SparseArray(const SparseArray& array);                                  // Copy constructor
  SparseArray& operator=(const SparseArray& array);                       // Assignment operator
  Element& operator[](int index);                                      // Subscript SparseArray
  void show();                                                            // display array elements
 
private:
  // Element class definition
  class Element
  {
  public:
    int index {};                                                   // Index of element
    double value {};                                                   // Element value
    PElement pNext {};                                                 // Pointer to next element
    PElement pPrevious {};                                             // Pointer to previous element
 
    Element(int newIndex) : index(newIndex) {}                        // Constructor
    Element(const Element& element) : index(element.index), value {element.value} {}  // Copy constructor
 
    // Assign an Element to an Element
    Element& operator= (Element& element)
    {
      value = element.value;
      return *this;
    }
 
    // Assign a value to an element
    Element& operator= (double v)
    {
      value = v;
      return *this;
    }
 
    operator double() { return value; }
  };
};
 
// Copy constructor
SparseArray::SparseArray(const SparseArray& array)
{
  maxElements = array.maxElements;                                   // Copy max element count
 
  if(array.pFirst)                                                   // If there is a first element...
  {
    pLast = pFirst = std::make_shared<Element>(*array.pFirst);       //  ...duplicate it
 
    PElement pTemp;
    PElement pCurrent = array.pFirst;
    while(pCurrent = pCurrent->pNext)                                // Duplicate any further elements
    {
      pTemp = pLast;                                                 // Save the address of the last
      pLast = std::make_shared<Element>(*pCurrent);                  // Make the new one the last
      pTemp->pNext = pLast;                                          // Set the next pointer of old last
      pLast->pPrevious = pTemp;                                      // Set previous pointer of new last
    }
  }
  else
    pLast = pFirst = nullptr;
}
 
 
// Assignment operator
SparseArray& SparseArray::operator=(const SparseArray& array)
{
   if(this == &array)                                                // Check for rhs same as lhs
    return *this;
 
  maxElements = array.maxElements;
  PElement pCurrent;
  if(array.pFirst)
  {
    pLast = pFirst = std::make_shared<Element>(*array.pFirst);
    PElement pTemp;
    pCurrent = array.pFirst;
    while(pCurrent = pCurrent->pNext)
    {
      pTemp = pLast;
      pLast = std::make_shared<Element>(*pCurrent);
      pTemp->pNext = pLast;
      pLast->pPrevious = pTemp;
      pTemp = pLast;
    }
  }
  else
    pLast = pFirst = nullptr;
  return *this;
}
 
// Subscript operator for non-const objects
SparseArray::Element& SparseArray::operator[](int index)
{
  if(index >= maxElements)
  {      // Out of range index
    string message {"Invalid index in SparseArray: "};
    message = message + std::to_string(index) + "\nIndex limits are 0 to " + std::to_string(maxElements - 1);
    throw std::out_of_range(message);
  }
 
  // Search the list for a Element corresponding to index
  PElement pCurrent = pFirst;
  while(pCurrent)
  {
    if(pCurrent->index == index)
      return *pCurrent;
    if(pCurrent->index > index)
      break;
    pCurrent = pCurrent->pNext;
  }
 
  PElement pElement = std::make_shared<Element>(index);
  if(pCurrent)
  {
    if(pCurrent->pPrevious)
    {
      pCurrent->pPrevious->pNext = pElement;
      pElement->pPrevious = pCurrent->pPrevious;
      pCurrent->pPrevious = pElement;
      pElement->pNext = pCurrent;
    }
    else
    {
      pElement->pNext = pCurrent;
      pCurrent->pPrevious = pElement;
      pFirst = pElement;
    }
  }
  else
  {
    if(pLast)
    {
      pLast->pNext = pElement;
      pElement->pPrevious = pLast;
      pLast = pElement;
    }
    else
      pFirst = pLast = pElement;                                     // The list was empty
  }
  return *pElement;                                                  // Return the new element
}
 
// Display the elements of a SparseArray
void SparseArray::show()
{
  PElement pCurrent = pFirst;
  while(pCurrent)
  {
    std::cout << "\n[" << std::setw(2) << pCurrent->index << "] = "
              << std::fixed << std::setprecision(2) << pCurrent->value;
    pCurrent = pCurrent->pNext;
  }
  std::cout << std::endl;
}
 
int main(){
  SparseArray values {50};  // Create a sparse array with capacity for 50
 
  try{
    values[10] = 20;
    values[15] = 30;
    values[21] = 40;
    values[32] = 25;
    values[44] = 22;
    values[1] = values[10] + values[15];
    values[16] = values[15] + 1;
    values[17] = 2 + values[16];
    values[2] = values[21] + values[32];
    values[5] = values[1] + values[2] + values[44];
    std::cout << "values[2] = " << values[2] << std::endl;
    std::cout << "values[10] = " << values[10] << std::endl;
    std::cout << "Product of values[2] and values[10] is " << values[2] * values[10] << std::endl;
    values.show();
    values[14] = values[60];                         // Causes an exception to be thrown - out of range index
  }catch(std::exception& e){
    std::cout << "Exception caught: " << e.what() << std::endl;
  }
 
  // Exercise the copy constructor and assignment operator
  try
  {
    SparseArray copies {values};
    copies.show();
    copies[0] = values[5];
    values = copies;
    values.show();
  }
  catch(std::exception& e)
  {
    std::cout << "Exception caught: " << e.what() << std::endl;
  }
}



PreviousNext

Related