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