C++ SparseArray class template
#include <cstdlib> #include <ctime> #include <string> #include <iostream> #include <iomanip> #include <memory> using std::string; template<typename T> class SparseArray { class Node;//from ww w .j a v a 2 s .c o m using PNode = std::shared_ptr < Node >; private: PNode pFirst; // Pointer to first element node PNode pLast; // Pointer to last element node public: SparseArray() = default; // Constructor SparseArray(const SparseArray& array); // Copy constructor SparseArray& operator=(const SparseArray& array); // Assignment operator T& operator[](int index); // Subscript SparseArray bool element_exists(int index); // Return true if element exists void show(); // display array elements private: // Node class definition class Node { public: int index {}; // Index of element T* pObject; // Address of object PNode pNext; // Pointer to next node PNode pPrevious; // Pointer to previous node Node(int newIndex) : index(newIndex), pObject(new T) {} // Constructor Node(const Node& node) : index(node.index), pObject(new T(*node.pObject)) {} // Copy constructor ~Node(){ delete pObject; } // Destructor }; }; // Copy constructor template template<typename T> SparseArray<T>::SparseArray(const SparseArray& array) { if (array.pFirst) { // If there is a first element pLast = pFirst = std::make_shared<Node>(*array.pFirst); // Duplicate it PNode pTemp; PNode pCurrent {array.pFirst}; while (pCurrent = pCurrent->pNext) { // Duplicate any further nodes pTemp = pLast; // Save the address of the last pLast = std::make_shared<Node>(*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 } } } // Assignment operator template template<typename T> SparseArray<T>& SparseArray<T>::operator=(const SparseArray& array) { if (this == &array) // Check for rhs same as lhs return *this; PNode pCurrent; if (array.pFirst) { pLast = pFirst = std::make_shared<Node>(*array.pFirst); Node* pTemp; pCurrent = array.pFirst; while (pCurrent = pCurrent->pNext) { pTemp = pLast; pLast = std::make_shared<Node>(*pCurrent); pTemp->pNext = pLast; pLast->pPrevious = pTemp; pTemp = pLast; } } return *this; } // Subscript operator for non-const objects template<typename T> T& SparseArray<T>::operator[](int index) { // Search the list for a node corresponding to index PNode pCurrent {pFirst}; while (pCurrent) { if (pCurrent->index == index) return *pCurrent->pObject; if (pCurrent->index > index) break; pCurrent = pCurrent->pNext; } // If we get to here, the element doesn't exist // so we must create one PNode pNode = std::make_shared<Node>(index); pNode->pObject = new T; if (pCurrent) // If its not the end of the list we must insert the element { if (pCurrent->pPrevious) // If current has a previous node just insert the new node { pCurrent->pPrevious->pNext = pNode; pNode->pPrevious = pCurrent->pPrevious; pCurrent->pPrevious = pNode; pNode->pNext = pCurrent; } else // Current must be the first so add new node as first { pNode->pNext = pCurrent; pCurrent->pPrevious = pNode; pFirst = pNode; } } else { // We must append the element if (pLast) { pLast->pNext = pNode; pNode->pPrevious = pLast; pLast = pNode; } else pFirst = pLast = pNode; } return *pNode->pObject; // Return the new element } // Display the elements of a SparseArray template<typename T> void SparseArray<T>::show() { PNode pCurrent {pFirst}; while (pCurrent) { std::cout << "\n[" << std::setw(2) << pCurrent->index << "] = " << *pCurrent->pObject; pCurrent = pCurrent->pNext; } std::cout << std::endl; } // Test for existence of element at index template<typename T> bool SparseArray<T>::element_exists(int index) { PNode p {pFirst}; while (p) { if (p->index == index) return true; p = p->pNext; } return false; } // Function to generate a random integer 0 to count-1 int random(int count) { return static_cast<int>((count*static_cast<unsigned long>(rand()))/(RAND_MAX+1UL)); } int main() { SparseArray<int> numbers; // Create sparse array const int count {20}; // Number of elements to be created int index {}; // Stores new index value srand((unsigned)time(0)); // Seed random number generator try { for (int i {}; i < count; ++i) // Create count entries in numbers array { // Must ensure that indexes after the first are not duplicates for(;;) { index = random(500); // Get a random index 0 to 499 if (numbers.element_exists(index)) continue; break; // We have a unique index } numbers[index] = 32+random(181); // Store value at new index position } } catch(std::exception& e) { std::cout << "\nException thrown " << e.what() << std::endl; } numbers.show(); }