C++ SparseArray class template with the LinkedList class template
#include <string> #include <iostream> #include <cctype> #include <memory> template<typename T> class LinkedList { class Node; // Declaration required because class is not yet defined using PNode = std::shared_ptr<Node>; private://from w ww. ja va2 s .c o m PNode pHead {}; // Pointer to first element node PNode pTail {}; // Pointer to last element node PNode pLast {}; // Pointer to last node accessed public: LinkedList() = default; // Constructor LinkedList(const LinkedList& list); // Copy constructor LinkedList& operator=(const LinkedList& list); // Assignment operator void addHead(T* pObj); // Add an object to the head void addTail(T* pObj); // Add an object to the tail T* getHead(); // Get the object at the head T* getTail(); // Get the object at the head T* getNext(); // Get the next object T* getPrevious(); // Get the previous object private: // Node class definition class Node { public: int index {}; // Index of element T* pObject {}; // Reference to object PNode pNext {}; // Pointer to next node PNode pPrevious {}; // Pointer to previous node Node(T* pObj) : pObject {new T {*pObj}} {} // 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> LinkedList<T>::LinkedList(const LinkedList& list) { if (list.pHead) { // If there is a first element pTail = pHead = std::make_shared<Node>(*list.pHead); // Duplicate it PNode pTemp; PNode pCurrent = list.pHead; while (pCurrent = pCurrent->pNext) { // Duplicate any further nodes pTemp = pTail; // Save the address of the last pTail = std::make_shared<Node>(*pCurrent); // Make the new one the last pTemp->pNext = pTail; // Set the next pointer of old last pTail->pPrevious = pTemp; // Set previous pointer of new last } } } // Assignment operator template template<typename T> LinkedList<T>& LinkedList<T>::operator=(const LinkedList& list) { if (this == &list) // Check for rhs same as lhs return *this; PNode pCurrent; if (list.pHead) { pTail = pHead = std::make_shared<Node>(*list.pHead); Node* pTemp {}; pCurrent = list.pHead; while (pCurrent = pCurrent->pNext) { pTemp = pTail; pTail = std::make_shared<Node>(*pCurrent); pTemp->pNext = pTail; pTail->pPrevious = pTemp; pTemp = pTail; } } return *this; } // Template function member to add an object to the head of the list template<typename T> void LinkedList<T>::addHead(T* pObj) { if (pHead) { pHead->pPrevious = std::make_shared<Node>(pObj); pHead->pPrevious->pNext = pHead; pHead = pHead->pPrevious; } else pHead = pTail = std::make_shared<Node>(pObj); pLast = pHead; } // Template function member to add an object to the tail of the list template<typename T> void LinkedList<T>::addTail(T* pObj) { if (pTail) { pTail->pNext = std::make_shared<Node>(pObj); pTail->pNext->pPrevious = pTail; pTail = pTail->pNext; } else pHead = pTail = std::make_shared<Node>(pObj); pLast = pTail; } // Template function member to get the object at the head of the list template<typename T> T* LinkedList<T>::getHead() { pLast = pHead; if (pHead) return pHead->pObject; else return nullptr; } // Template function member to get the object at the tail of the list template<typename T> T* LinkedList<T>::getTail() { pLast = pTail; if (pTail) return pTail->pObject; else return nullptr; } // Template function member to get the next object template<typename T> T* LinkedList<T>::getNext() { if (pLast) if (pLast = pLast->pNext) return pLast->pObject; return nullptr; } // Template function member to get the previous object template<typename T> T* LinkedList<T>::getPrevious() { if (pLast) if (pLast = pLast->pPrevious) return pLast->pObject; return nullptr; } template<typename T> class SparseArray { class Node; 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; } using std::string; using List = LinkedList <string>; int main() { string text {"this is a test"}; SparseArray<List> lists; // Sparse array of linked lists string letters {"ABCDEFGHIJKLMNOPQRSTUVWXYZ"}; string word; // Stores a word string separators {" \n\t,.\"?!;:"}; // Separators between words int start {}; // Start of a word int end {}; // separator position after a word while(string::npos != (start = text.find_first_not_of(separators, start))) { end = text.find_first_of(separators, start+1); word = text.substr(start,end-start); lists[letters.find(std::toupper(word[0]))].addTail(&word); start = end; } // List the words in order 5 to a line const int perline {5}; int count {}; // Word counter string* pStr; for (int i {}; i < 26; ++i) { if (!lists.element_exists(i)) continue; pStr = lists[i].getHead(); count = 0; while(pStr) { std::cout << *pStr << ' '; if(!(++count % perline)) std::cout << std::endl; pStr = lists[i].getNext(); } std::cout << std::endl; } std::cout << std::endl; }