C++ SparseArray class template with the LinkedList class template

Description

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



PreviousNext

Related