Move datastruct template implementations to header files
This commit is contained in:
		
							parent
							
								
									e4e1fd09d6
								
							
						
					
					
						commit
						b9843a5d99
					
				@ -13,6 +13,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
 | 
				
			|||||||
# Define the project name
 | 
					# Define the project name
 | 
				
			||||||
project(DoubleList)
 | 
					project(DoubleList)
 | 
				
			||||||
# Define source files
 | 
					# Define source files
 | 
				
			||||||
set(SRC driver.cpp doublelist.cpp)
 | 
					set(SRC driver.cpp)
 | 
				
			||||||
# Build an executable
 | 
					# Build an executable
 | 
				
			||||||
add_executable(DoubleListDriver ${SRC})
 | 
					add_executable(DoubleListDriver ${SRC})
 | 
				
			||||||
 | 
				
			|||||||
@ -5,15 +5,8 @@ CXXFLAGS=-g -Wall
 | 
				
			|||||||
# Driver
 | 
					# Driver
 | 
				
			||||||
###############################################################################
 | 
					###############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
driver:	driver.cpp	doublelist.o
 | 
					driver:	driver.cpp
 | 
				
			||||||
	${CXX} ${CXXFLAGS} driver.cpp doublelist.o -o driver
 | 
						${CXX} ${CXXFLAGS} driver.cpp -o driver
 | 
				
			||||||
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
# DoubleList
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
doublelist.o:	doublelist.cpp doublelist.h
 | 
					 | 
				
			||||||
	${CXX} ${CXXFLAGS} -c doublelist.cpp -o doublelist.o
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
###############################################################################
 | 
					###############################################################################
 | 
				
			||||||
# Clean
 | 
					# Clean
 | 
				
			||||||
 | 
				
			|||||||
@ -1,360 +0,0 @@
 | 
				
			|||||||
/*#############################################################################
 | 
					 | 
				
			||||||
## Author: Shaun Reed                                                        ##
 | 
					 | 
				
			||||||
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved               ##
 | 
					 | 
				
			||||||
## About: An example of a doubly linked list                                 ##
 | 
					 | 
				
			||||||
##                                                                           ##
 | 
					 | 
				
			||||||
## Contact: shaunrd0@gmail.com  | URL: www.shaunreed.com | GitHub: shaunrd0  ##
 | 
					 | 
				
			||||||
##############################################################################
 | 
					 | 
				
			||||||
## doublelist.cpp
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "doublelist.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************************************************************************
 | 
					 | 
				
			||||||
 * Constructors, Destructors, Operators
 | 
					 | 
				
			||||||
 *****************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** copy constructor
 | 
					 | 
				
			||||||
 * @brief Construct a new DoubleList::DoubleList object from an existing one
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param rhs DoubleList object
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
DoubleList<T>::DoubleList(const DoubleList& rhs)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *cp = rhs.head;
 | 
					 | 
				
			||||||
  Node *tempHead;
 | 
					 | 
				
			||||||
  if (cp == NULL) head = NULL;
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    head = new Node(cp->data);
 | 
					 | 
				
			||||||
    tempHead = head;
 | 
					 | 
				
			||||||
    while (cp->next != NULL) {
 | 
					 | 
				
			||||||
      cp = cp->next;
 | 
					 | 
				
			||||||
      head->next = new Node(cp->data);
 | 
					 | 
				
			||||||
      head = head->next;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    head = tempHead;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** operator=
 | 
					 | 
				
			||||||
 * @brief Assign two DoubleList objects equal using copy constr and class destr
 | 
					 | 
				
			||||||
 *        Pass the rhs by value to create local copy, swap its contents
 | 
					 | 
				
			||||||
 *        Destructor called on previous DoubleList data at the end of this scope
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param rhs DoubleList object passed by value
 | 
					 | 
				
			||||||
 * @return DoubleList A deep copy of the rhs DoubleList object
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
DoubleList<T> DoubleList<T>::operator=(DoubleList<T> rhs)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (this == &rhs) return *this;
 | 
					 | 
				
			||||||
  std::swap(head, rhs.head);
 | 
					 | 
				
			||||||
  return *this;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** destructor
 | 
					 | 
				
			||||||
 * @brief Destroy the DoubleList::DoubleList object
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
DoubleList<T>::~DoubleList()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  makeEmpty();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************************************************************************
 | 
					 | 
				
			||||||
 * Public Member Functions
 | 
					 | 
				
			||||||
 *****************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** insert
 | 
					 | 
				
			||||||
 * @brief Inserts a value to the head of our linked list
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param val The value to be inserted
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
bool DoubleList<T>::insert(T val)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  bool inserted = insert(val, head);
 | 
					 | 
				
			||||||
  if (inserted)
 | 
					 | 
				
			||||||
    std::cout << "[" << val << "] was inserted into the list\n";
 | 
					 | 
				
			||||||
  else std::cout << "[" << val << "] could not be inserted into the list\n";
 | 
					 | 
				
			||||||
  return inserted;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** insert at
 | 
					 | 
				
			||||||
 * @brief Inserts a value in the place of a given key
 | 
					 | 
				
			||||||
 *        Key Node found is moved to the newNode->next position
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param key The value to search for to determine insert location
 | 
					 | 
				
			||||||
 * @param val The value to be inserted into the list
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
bool DoubleList<T>::insert(T val, T key)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  bool inserted = insert(val, key, head);
 | 
					 | 
				
			||||||
  if (inserted)
 | 
					 | 
				
			||||||
    std::cout << "[" << val << "] was inserted into the list\n";
 | 
					 | 
				
			||||||
  else std::cout << "[" << val << "] could not be inserted into the list\n";
 | 
					 | 
				
			||||||
  return inserted;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** remove
 | 
					 | 
				
			||||||
 * @brief Removes a value in the list by calling a private member and handling output
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param val Value to be removed from the list
 | 
					 | 
				
			||||||
 * @return true If the value was removed from the list
 | 
					 | 
				
			||||||
 * @return false If the value was not removed from the list
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
bool DoubleList<T>::remove(T val)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  bool removed = remove(val, head);
 | 
					 | 
				
			||||||
  if (removed)
 | 
					 | 
				
			||||||
    std::cout << "[" << val << "] was removed from the list\n";
 | 
					 | 
				
			||||||
  else std::cout << "[" << val << "] could not be removed from the list\n";
 | 
					 | 
				
			||||||
  return removed;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** replace
 | 
					 | 
				
			||||||
 * @brief Replaces a value in the list by calling a private member and handling output
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param val Value to insert into the list
 | 
					 | 
				
			||||||
 * @param key Value to be replaced within the list
 | 
					 | 
				
			||||||
 * @return true If the key has been replaced in the list by val
 | 
					 | 
				
			||||||
 * @return false If the key has not been replaced in the list by val
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
bool DoubleList<T>::replace(T val, T key)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  bool replaced = replace(val, key, head);
 | 
					 | 
				
			||||||
  if (replaced)
 | 
					 | 
				
			||||||
    std::cout << "[" << key << "] was replaced by [" << val << "] in the list\n";
 | 
					 | 
				
			||||||
  else std::cout << "[" << key << "] could not be replaced by [" << val << "] in the list\n";
 | 
					 | 
				
			||||||
  return replaced;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** makeEmpty
 | 
					 | 
				
			||||||
 * @brief Empty this DoubleList object, deleting all associated Nodes
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
void DoubleList<T>::makeEmpty()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *nextNode, *temp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (head == NULL) return;
 | 
					 | 
				
			||||||
  nextNode = head->next;
 | 
					 | 
				
			||||||
  delete head;
 | 
					 | 
				
			||||||
  head = NULL;
 | 
					 | 
				
			||||||
  while(nextNode != NULL) {
 | 
					 | 
				
			||||||
    temp = nextNode;
 | 
					 | 
				
			||||||
    nextNode = nextNode->next;
 | 
					 | 
				
			||||||
    delete temp;
 | 
					 | 
				
			||||||
    temp = NULL;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** isEmpty
 | 
					 | 
				
			||||||
 * @brief Determine if the DoubleList is empty
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return true If the DoubleList::head is NULL
 | 
					 | 
				
			||||||
 * @return false If the DoubleList::head contains data
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
bool DoubleList<T>::isEmpty() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  return head == NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** peek
 | 
					 | 
				
			||||||
 * @brief returns the value at the DoubleList::head
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return T The value held at the Node pointed to by DoubleList::head
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
T DoubleList<T>::peek() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (!isEmpty())
 | 
					 | 
				
			||||||
    std::cout << "[" << head->data << "] is at the top of our list\n";
 | 
					 | 
				
			||||||
  else std::cout << "Nothing to peek, our list is empty...\n";
 | 
					 | 
				
			||||||
  // If the list has data we return it, otherwise we return the smallest possible int (error)
 | 
					 | 
				
			||||||
  return (!isEmpty()) ? head->data : T();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** print
 | 
					 | 
				
			||||||
 * @brief Output the data held by the DoubleList object
 | 
					 | 
				
			||||||
 *        Calls to the private print()
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
void DoubleList<T>::print() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if(!isEmpty()) print(head);
 | 
					 | 
				
			||||||
  else std::cout << "Nothing to print, our list is empty...\n";
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** find
 | 
					 | 
				
			||||||
 * @brief Calls to the private member find() and handles return cases
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param val The value to search for within our DoubleList
 | 
					 | 
				
			||||||
 * @return true If the value was found in this DoubleList
 | 
					 | 
				
			||||||
 * @return false If the value was not found in this DoubleList
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
bool DoubleList<T>::find(T val) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *result = find(val, head);
 | 
					 | 
				
			||||||
  if( result == NULL) {
 | 
					 | 
				
			||||||
    std::cout << "[" << val << "] Was not found in our list\n";
 | 
					 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  std::cout << "[" << result->data << "] Was found in our list\n";
 | 
					 | 
				
			||||||
  return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************************************************************************
 | 
					 | 
				
			||||||
 * Private Member Functions
 | 
					 | 
				
			||||||
 *****************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** insert
 | 
					 | 
				
			||||||
 * @brief Private member to handle inserting value into the list
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param val Value to be inserted
 | 
					 | 
				
			||||||
 * @param head The head of the list to insert the value into
 | 
					 | 
				
			||||||
 * @return true If the value was inserted
 | 
					 | 
				
			||||||
 * @return false If the value could not be inserted
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
bool DoubleList<T>::insert(T val, Node *&head)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *newNode = new Node(val);
 | 
					 | 
				
			||||||
  // If the list is not empty, update next pointer to head node
 | 
					 | 
				
			||||||
  if (!isEmpty()) {
 | 
					 | 
				
			||||||
    newNode->next = head;
 | 
					 | 
				
			||||||
    // Create a prev ptr for the head node
 | 
					 | 
				
			||||||
    head->prev = newNode;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  // Always set head to our newNode
 | 
					 | 
				
			||||||
  head = newNode;
 | 
					 | 
				
			||||||
  return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** insert at
 | 
					 | 
				
			||||||
 * @brief Private member to handle inserting a value at a key within our list
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param val Value to be inserted
 | 
					 | 
				
			||||||
 * @param key Key value to search for within the list
 | 
					 | 
				
			||||||
 * @param head Head node of the list to insert to
 | 
					 | 
				
			||||||
 * @return true If the value was inserted
 | 
					 | 
				
			||||||
 * @return false If the value was not inserted
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
bool DoubleList<T>::insert(T val, T key, Node *&head)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *newNode = new Node(val);
 | 
					 | 
				
			||||||
  if (isEmpty()) return false;
 | 
					 | 
				
			||||||
  // Let insert() handle inserting at the head
 | 
					 | 
				
			||||||
  else if (head->data == key) return insert(val, head);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Node *keyNode = find(key, head);
 | 
					 | 
				
			||||||
  // If there was no keyNode found, the key does is not in our list
 | 
					 | 
				
			||||||
  // Don't insert anything, return false and let caller decide whats next
 | 
					 | 
				
			||||||
  if (keyNode == NULL) return false;
 | 
					 | 
				
			||||||
  // Insert the newNode infront of the previous to the keyNode
 | 
					 | 
				
			||||||
  newNode->prev = keyNode->prev;
 | 
					 | 
				
			||||||
  keyNode->prev->next = newNode;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Change the keyNode->prev ptr to newNode
 | 
					 | 
				
			||||||
  newNode->next = keyNode;
 | 
					 | 
				
			||||||
  keyNode->prev = newNode;
 | 
					 | 
				
			||||||
  return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** remove
 | 
					 | 
				
			||||||
 * @brief Private member to remove values from the list
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param val Value to be removed
 | 
					 | 
				
			||||||
 * @param head Head of the list to remove the value from
 | 
					 | 
				
			||||||
 * @return true If the value has been removed from the list
 | 
					 | 
				
			||||||
 * @return false If the value has not been removed from the list
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
bool DoubleList<T>::remove(T val, Node *&head)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (head == NULL) return false;
 | 
					 | 
				
			||||||
  else if (head->data == val) {
 | 
					 | 
				
			||||||
    head = head->next;
 | 
					 | 
				
			||||||
    return true;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Node *keyNode = find(val, head);
 | 
					 | 
				
			||||||
  if (keyNode == NULL) return false;
 | 
					 | 
				
			||||||
  Node *gtfo = keyNode;
 | 
					 | 
				
			||||||
  if (keyNode->next != NULL) keyNode->next->prev = keyNode->prev;
 | 
					 | 
				
			||||||
  if (keyNode->prev != NULL) keyNode->prev->next = keyNode->next;
 | 
					 | 
				
			||||||
  delete gtfo;
 | 
					 | 
				
			||||||
  gtfo = NULL;
 | 
					 | 
				
			||||||
  return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** replace
 | 
					 | 
				
			||||||
 * @brief Private member to replace values within the list
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param val Value to insert into the list
 | 
					 | 
				
			||||||
 * @param key Value to be replaced within the list
 | 
					 | 
				
			||||||
 * @param head Head of the list to replace the value
 | 
					 | 
				
			||||||
 * @return true If the key has been replaced by val within the list
 | 
					 | 
				
			||||||
 * @return false If the key has not been replaced by val within the list
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
bool DoubleList<T>::replace(T val, T key, Node *&head)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *replacee = find(key, head);
 | 
					 | 
				
			||||||
  if (replacee == NULL) return false;
 | 
					 | 
				
			||||||
  replacee->data = val;
 | 
					 | 
				
			||||||
  return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** find
 | 
					 | 
				
			||||||
 * @brief Find and return a Node which contains the given value
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param val The value to search for within our DoubleList
 | 
					 | 
				
			||||||
 * @param start The Node to begin the search from
 | 
					 | 
				
			||||||
 * @return DoubleList::Node* A pointer to the Node containing the search value
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
typename DoubleList<T>::Node* DoubleList<T>::find(T val, Node *start) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  // If given a NULL list, return NULL
 | 
					 | 
				
			||||||
  // If given a head which contains the requested value, return the foundNode
 | 
					 | 
				
			||||||
  if (start == NULL || start->data == val) return start;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Node *foundNode = start;
 | 
					 | 
				
			||||||
  while (foundNode->next != NULL) {
 | 
					 | 
				
			||||||
    foundNode = foundNode->next;
 | 
					 | 
				
			||||||
    if (foundNode->data == val) return foundNode;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  // If we have not yet returned a foundNode, the key is not in our list
 | 
					 | 
				
			||||||
  return NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** print
 | 
					 | 
				
			||||||
 * @brief Output the contents of a DoubleList from the given Node to NULL
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param start The Node to begin traversing output from
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
void DoubleList<T>::print(Node *start) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *temp = start;
 | 
					 | 
				
			||||||
  std::cout << "List Contents: ";
 | 
					 | 
				
			||||||
  while (temp != NULL) {
 | 
					 | 
				
			||||||
    std::cout << temp->data << " | ";
 | 
					 | 
				
			||||||
    temp = temp->next;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  std::cout << std::endl;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
template class DoubleList<TYPE>;
 | 
					 | 
				
			||||||
@ -49,4 +49,353 @@ class DoubleList {
 | 
				
			|||||||
    void print(Node *start) const;
 | 
					    void print(Node *start) const;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************************************************************************
 | 
				
			||||||
 | 
					 * Constructors, Destructors, Operators
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** copy constructor
 | 
				
			||||||
 | 
					 * @brief Construct a new DoubleList::DoubleList object from an existing one
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param rhs DoubleList object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					DoubleList<T>::DoubleList(const DoubleList& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *cp = rhs.head;
 | 
				
			||||||
 | 
					  Node *tempHead;
 | 
				
			||||||
 | 
					  if (cp == NULL) head = NULL;
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    head = new Node(cp->data);
 | 
				
			||||||
 | 
					    tempHead = head;
 | 
				
			||||||
 | 
					    while (cp->next != NULL) {
 | 
				
			||||||
 | 
					      cp = cp->next;
 | 
				
			||||||
 | 
					      head->next = new Node(cp->data);
 | 
				
			||||||
 | 
					      head = head->next;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    head = tempHead;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** operator=
 | 
				
			||||||
 | 
					 * @brief Assign two DoubleList objects equal using copy constr and class destr
 | 
				
			||||||
 | 
					 *        Pass the rhs by value to create local copy, swap its contents
 | 
				
			||||||
 | 
					 *        Destructor called on previous DoubleList data at the end of this scope
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param rhs DoubleList object passed by value
 | 
				
			||||||
 | 
					 * @return DoubleList A deep copy of the rhs DoubleList object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					DoubleList<T> DoubleList<T>::operator=(DoubleList<T> rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (this == &rhs) return *this;
 | 
				
			||||||
 | 
					  std::swap(head, rhs.head);
 | 
				
			||||||
 | 
					  return *this;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** destructor
 | 
				
			||||||
 | 
					 * @brief Destroy the DoubleList::DoubleList object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					DoubleList<T>::~DoubleList()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  makeEmpty();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************************************************************************
 | 
				
			||||||
 | 
					 * Public Member Functions
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** insert
 | 
				
			||||||
 | 
					 * @brief Inserts a value to the head of our linked list
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param val The value to be inserted
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool DoubleList<T>::insert(T val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  bool inserted = insert(val, head);
 | 
				
			||||||
 | 
					  if (inserted)
 | 
				
			||||||
 | 
					    std::cout << "[" << val << "] was inserted into the list\n";
 | 
				
			||||||
 | 
					  else std::cout << "[" << val << "] could not be inserted into the list\n";
 | 
				
			||||||
 | 
					  return inserted;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** insert at
 | 
				
			||||||
 | 
					 * @brief Inserts a value in the place of a given key
 | 
				
			||||||
 | 
					 *        Key Node found is moved to the newNode->next position
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param key The value to search for to determine insert location
 | 
				
			||||||
 | 
					 * @param val The value to be inserted into the list
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool DoubleList<T>::insert(T val, T key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  bool inserted = insert(val, key, head);
 | 
				
			||||||
 | 
					  if (inserted)
 | 
				
			||||||
 | 
					    std::cout << "[" << val << "] was inserted into the list\n";
 | 
				
			||||||
 | 
					  else std::cout << "[" << val << "] could not be inserted into the list\n";
 | 
				
			||||||
 | 
					  return inserted;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** remove
 | 
				
			||||||
 | 
					 * @brief Removes a value in the list by calling a private member and handling output
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param val Value to be removed from the list
 | 
				
			||||||
 | 
					 * @return true If the value was removed from the list
 | 
				
			||||||
 | 
					 * @return false If the value was not removed from the list
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool DoubleList<T>::remove(T val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  bool removed = remove(val, head);
 | 
				
			||||||
 | 
					  if (removed)
 | 
				
			||||||
 | 
					    std::cout << "[" << val << "] was removed from the list\n";
 | 
				
			||||||
 | 
					  else std::cout << "[" << val << "] could not be removed from the list\n";
 | 
				
			||||||
 | 
					  return removed;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** replace
 | 
				
			||||||
 | 
					 * @brief Replaces a value in the list by calling a private member and handling output
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param val Value to insert into the list
 | 
				
			||||||
 | 
					 * @param key Value to be replaced within the list
 | 
				
			||||||
 | 
					 * @return true If the key has been replaced in the list by val
 | 
				
			||||||
 | 
					 * @return false If the key has not been replaced in the list by val
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool DoubleList<T>::replace(T val, T key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  bool replaced = replace(val, key, head);
 | 
				
			||||||
 | 
					  if (replaced)
 | 
				
			||||||
 | 
					    std::cout << "[" << key << "] was replaced by [" << val << "] in the list\n";
 | 
				
			||||||
 | 
					  else std::cout << "[" << key << "] could not be replaced by [" << val << "] in the list\n";
 | 
				
			||||||
 | 
					  return replaced;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** makeEmpty
 | 
				
			||||||
 | 
					 * @brief Empty this DoubleList object, deleting all associated Nodes
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					void DoubleList<T>::makeEmpty()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *nextNode, *temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (head == NULL) return;
 | 
				
			||||||
 | 
					  nextNode = head->next;
 | 
				
			||||||
 | 
					  delete head;
 | 
				
			||||||
 | 
					  head = NULL;
 | 
				
			||||||
 | 
					  while(nextNode != NULL) {
 | 
				
			||||||
 | 
					    temp = nextNode;
 | 
				
			||||||
 | 
					    nextNode = nextNode->next;
 | 
				
			||||||
 | 
					    delete temp;
 | 
				
			||||||
 | 
					    temp = NULL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** isEmpty
 | 
				
			||||||
 | 
					 * @brief Determine if the DoubleList is empty
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return true If the DoubleList::head is NULL
 | 
				
			||||||
 | 
					 * @return false If the DoubleList::head contains data
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool DoubleList<T>::isEmpty() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return head == NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** peek
 | 
				
			||||||
 | 
					 * @brief returns the value at the DoubleList::head
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return T The value held at the Node pointed to by DoubleList::head
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					T DoubleList<T>::peek() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!isEmpty())
 | 
				
			||||||
 | 
					    std::cout << "[" << head->data << "] is at the top of our list\n";
 | 
				
			||||||
 | 
					  else std::cout << "Nothing to peek, our list is empty...\n";
 | 
				
			||||||
 | 
					  // If the list has data we return it, otherwise we return the smallest possible int (error)
 | 
				
			||||||
 | 
					  return (!isEmpty()) ? head->data : T();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** print
 | 
				
			||||||
 | 
					 * @brief Output the data held by the DoubleList object
 | 
				
			||||||
 | 
					 *        Calls to the private print()
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					void DoubleList<T>::print() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if(!isEmpty()) print(head);
 | 
				
			||||||
 | 
					  else std::cout << "Nothing to print, our list is empty...\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** find
 | 
				
			||||||
 | 
					 * @brief Calls to the private member find() and handles return cases
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param val The value to search for within our DoubleList
 | 
				
			||||||
 | 
					 * @return true If the value was found in this DoubleList
 | 
				
			||||||
 | 
					 * @return false If the value was not found in this DoubleList
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool DoubleList<T>::find(T val) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *result = find(val, head);
 | 
				
			||||||
 | 
					  if( result == NULL) {
 | 
				
			||||||
 | 
					    std::cout << "[" << val << "] Was not found in our list\n";
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  std::cout << "[" << result->data << "] Was found in our list\n";
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************************************************************************
 | 
				
			||||||
 | 
					 * Private Member Functions
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** insert
 | 
				
			||||||
 | 
					 * @brief Private member to handle inserting value into the list
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param val Value to be inserted
 | 
				
			||||||
 | 
					 * @param head The head of the list to insert the value into
 | 
				
			||||||
 | 
					 * @return true If the value was inserted
 | 
				
			||||||
 | 
					 * @return false If the value could not be inserted
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool DoubleList<T>::insert(T val, Node *&head)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *newNode = new Node(val);
 | 
				
			||||||
 | 
					  // If the list is not empty, update next pointer to head node
 | 
				
			||||||
 | 
					  if (!isEmpty()) {
 | 
				
			||||||
 | 
					    newNode->next = head;
 | 
				
			||||||
 | 
					    // Create a prev ptr for the head node
 | 
				
			||||||
 | 
					    head->prev = newNode;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  // Always set head to our newNode
 | 
				
			||||||
 | 
					  head = newNode;
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** insert at
 | 
				
			||||||
 | 
					 * @brief Private member to handle inserting a value at a key within our list
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param val Value to be inserted
 | 
				
			||||||
 | 
					 * @param key Key value to search for within the list
 | 
				
			||||||
 | 
					 * @param head Head node of the list to insert to
 | 
				
			||||||
 | 
					 * @return true If the value was inserted
 | 
				
			||||||
 | 
					 * @return false If the value was not inserted
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool DoubleList<T>::insert(T val, T key, Node *&head)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *newNode = new Node(val);
 | 
				
			||||||
 | 
					  if (isEmpty()) return false;
 | 
				
			||||||
 | 
					    // Let insert() handle inserting at the head
 | 
				
			||||||
 | 
					  else if (head->data == key) return insert(val, head);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Node *keyNode = find(key, head);
 | 
				
			||||||
 | 
					  // If there was no keyNode found, the key does is not in our list
 | 
				
			||||||
 | 
					  // Don't insert anything, return false and let caller decide whats next
 | 
				
			||||||
 | 
					  if (keyNode == NULL) return false;
 | 
				
			||||||
 | 
					  // Insert the newNode infront of the previous to the keyNode
 | 
				
			||||||
 | 
					  newNode->prev = keyNode->prev;
 | 
				
			||||||
 | 
					  keyNode->prev->next = newNode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Change the keyNode->prev ptr to newNode
 | 
				
			||||||
 | 
					  newNode->next = keyNode;
 | 
				
			||||||
 | 
					  keyNode->prev = newNode;
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** remove
 | 
				
			||||||
 | 
					 * @brief Private member to remove values from the list
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param val Value to be removed
 | 
				
			||||||
 | 
					 * @param head Head of the list to remove the value from
 | 
				
			||||||
 | 
					 * @return true If the value has been removed from the list
 | 
				
			||||||
 | 
					 * @return false If the value has not been removed from the list
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool DoubleList<T>::remove(T val, Node *&head)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (head == NULL) return false;
 | 
				
			||||||
 | 
					  else if (head->data == val) {
 | 
				
			||||||
 | 
					    head = head->next;
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Node *keyNode = find(val, head);
 | 
				
			||||||
 | 
					  if (keyNode == NULL) return false;
 | 
				
			||||||
 | 
					  Node *gtfo = keyNode;
 | 
				
			||||||
 | 
					  if (keyNode->next != NULL) keyNode->next->prev = keyNode->prev;
 | 
				
			||||||
 | 
					  if (keyNode->prev != NULL) keyNode->prev->next = keyNode->next;
 | 
				
			||||||
 | 
					  delete gtfo;
 | 
				
			||||||
 | 
					  gtfo = NULL;
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** replace
 | 
				
			||||||
 | 
					 * @brief Private member to replace values within the list
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param val Value to insert into the list
 | 
				
			||||||
 | 
					 * @param key Value to be replaced within the list
 | 
				
			||||||
 | 
					 * @param head Head of the list to replace the value
 | 
				
			||||||
 | 
					 * @return true If the key has been replaced by val within the list
 | 
				
			||||||
 | 
					 * @return false If the key has not been replaced by val within the list
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool DoubleList<T>::replace(T val, T key, Node *&head)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *replacee = find(key, head);
 | 
				
			||||||
 | 
					  if (replacee == NULL) return false;
 | 
				
			||||||
 | 
					  replacee->data = val;
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** find
 | 
				
			||||||
 | 
					 * @brief Find and return a Node which contains the given value
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param val The value to search for within our DoubleList
 | 
				
			||||||
 | 
					 * @param start The Node to begin the search from
 | 
				
			||||||
 | 
					 * @return DoubleList::Node* A pointer to the Node containing the search value
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					typename DoubleList<T>::Node* DoubleList<T>::find(T val, Node *start) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // If given a NULL list, return NULL
 | 
				
			||||||
 | 
					  // If given a head which contains the requested value, return the foundNode
 | 
				
			||||||
 | 
					  if (start == NULL || start->data == val) return start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Node *foundNode = start;
 | 
				
			||||||
 | 
					  while (foundNode->next != NULL) {
 | 
				
			||||||
 | 
					    foundNode = foundNode->next;
 | 
				
			||||||
 | 
					    if (foundNode->data == val) return foundNode;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  // If we have not yet returned a foundNode, the key is not in our list
 | 
				
			||||||
 | 
					  return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** print
 | 
				
			||||||
 | 
					 * @brief Output the contents of a DoubleList from the given Node to NULL
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param start The Node to begin traversing output from
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					void DoubleList<T>::print(Node *start) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *temp = start;
 | 
				
			||||||
 | 
					  std::cout << "List Contents: ";
 | 
				
			||||||
 | 
					  while (temp != NULL) {
 | 
				
			||||||
 | 
					    std::cout << temp->data << " | ";
 | 
				
			||||||
 | 
					    temp = temp->next;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  std::cout << std::endl;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,6 @@ cmake_minimum_required(VERSION 3.2)
 | 
				
			|||||||
# Define the project name
 | 
					# Define the project name
 | 
				
			||||||
project(Queue)
 | 
					project(Queue)
 | 
				
			||||||
# Define source files
 | 
					# Define source files
 | 
				
			||||||
set(SRC driver.cpp queuelist.cpp)
 | 
					set(SRC driver.cpp)
 | 
				
			||||||
# Build an executable
 | 
					# Build an executable
 | 
				
			||||||
add_executable(QueueDriver ${SRC})
 | 
					add_executable(QueueDriver ${SRC})
 | 
				
			||||||
 | 
				
			|||||||
@ -5,15 +5,8 @@ CXXFLAGS=-g -Wall
 | 
				
			|||||||
# Driver
 | 
					# Driver
 | 
				
			||||||
###############################################################################
 | 
					###############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
driver:	driver.cpp	queuelist.o
 | 
					driver:	driver.cpp
 | 
				
			||||||
	${CXX} ${CXXFLAGS} driver.cpp queuelist.o -o driver
 | 
						${CXX} ${CXXFLAGS} driver.cpp -o driver
 | 
				
			||||||
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
# QueueList
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
queuelist.o:	queuelist.cpp queuelist.h
 | 
					 | 
				
			||||||
	${CXX} ${CXXFLAGS} -c queuelist.cpp -o queuelist.o
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
###############################################################################
 | 
					###############################################################################
 | 
				
			||||||
# Clean
 | 
					# Clean
 | 
				
			||||||
 | 
				
			|||||||
@ -1,272 +0,0 @@
 | 
				
			|||||||
/*#############################################################################
 | 
					 | 
				
			||||||
## Author: Shaun Reed                                                        ##
 | 
					 | 
				
			||||||
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved               ##
 | 
					 | 
				
			||||||
## About: An example of a queue implementation using linked lists            ##
 | 
					 | 
				
			||||||
##                                                                           ##
 | 
					 | 
				
			||||||
## Contact: shaunrd0@gmail.com  | URL: www.shaunreed.com | GitHub: shaunrd0  ##
 | 
					 | 
				
			||||||
##############################################################################
 | 
					 | 
				
			||||||
## queuelist.cpp
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "queuelist.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************************************************************************
 | 
					 | 
				
			||||||
 * Constructors, Destructors, Operators
 | 
					 | 
				
			||||||
 *****************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** copy constructor
 | 
					 | 
				
			||||||
 * @brief Construct a new QueueList::QueueList object from an existing one
 | 
					 | 
				
			||||||
 *        Creates a new deep copy of a given QueueList
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param rhs QueueList object
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
QueueList<T>::QueueList(const QueueList<T>& rhs)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *cp = rhs.head;
 | 
					 | 
				
			||||||
  Node *tempHead;
 | 
					 | 
				
			||||||
  // If we are copying from an empty queue, create a new QueueList with a NULL head
 | 
					 | 
				
			||||||
  if (cp == NULL) head = NULL;
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    // If the queue has data, initialize a new queue with the head data
 | 
					 | 
				
			||||||
    head = new Node(cp->data);
 | 
					 | 
				
			||||||
    // Keep a temporary head node so we can return to it later
 | 
					 | 
				
			||||||
    tempHead = head;
 | 
					 | 
				
			||||||
    while (cp->next != NULL) {
 | 
					 | 
				
			||||||
      // Until we hit an end, create new nodes with the next node data
 | 
					 | 
				
			||||||
      cp = cp->next;
 | 
					 | 
				
			||||||
      head->next = new Node(cp->data);
 | 
					 | 
				
			||||||
      head = head->next;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    tail = head;
 | 
					 | 
				
			||||||
    head = tempHead;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** operator=
 | 
					 | 
				
			||||||
 * @brief Assign two QueueList objects equal using copy constr and class destr
 | 
					 | 
				
			||||||
 *        Pass the rhs by value to create local copy, swap its contents
 | 
					 | 
				
			||||||
 *        Destructor called on previous QueueList data at the end of this scope
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param rhs QueueList object passed by value
 | 
					 | 
				
			||||||
 * @return QueueList A deep copy of the rhs QueueList object
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
QueueList<T> QueueList<T>::operator=(QueueList<T> rhs)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (this == &rhs) return *this;
 | 
					 | 
				
			||||||
  // Swap the pointers, moving the previous head data to the local variable rhs 
 | 
					 | 
				
			||||||
  std::swap(head, rhs.head);
 | 
					 | 
				
			||||||
  return *this;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** destructor
 | 
					 | 
				
			||||||
 * @brief Destroy the QueueList::QueueList object
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
QueueList<T>::~QueueList()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  makeEmpty(head);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************************************************************************
 | 
					 | 
				
			||||||
 * Public Member Functions
 | 
					 | 
				
			||||||
 *****************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** enqueue
 | 
					 | 
				
			||||||
 * @brief Queue a value to the tail of our linked list
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param val The value to be inserted into the queue
 | 
					 | 
				
			||||||
 * @return true If the value was inserted in the queue
 | 
					 | 
				
			||||||
 * @return false If the value could not be queued
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
bool QueueList<T>::enqueue(T val)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  bool inserted = enqueue(val, tail);
 | 
					 | 
				
			||||||
  if (inserted)
 | 
					 | 
				
			||||||
    std::cout << "[" << val << "] was inserted into the queue\n";
 | 
					 | 
				
			||||||
  else std::cout << "[" << val << "] could not be inserted into the queue\n";
 | 
					 | 
				
			||||||
  return inserted;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** dequeue
 | 
					 | 
				
			||||||
 * @brief returns the value at the QueueList::head and moves head to the next in queue
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return T The value held at the Node pointed to by QueueList::head
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
T QueueList<T>::dequeue()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (!isEmpty())
 | 
					 | 
				
			||||||
    std::cout << "[" << dequeue(head) << "] has been removed from our queue\n";
 | 
					 | 
				
			||||||
  else std::cout << "Nothing to dequeue, our queue is empty...\n";
 | 
					 | 
				
			||||||
  // If the queue has data we return it, otherwise we return the smallest possible int (error)
 | 
					 | 
				
			||||||
  return (!isEmpty()) ? head->data : T();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** next
 | 
					 | 
				
			||||||
 * @brief returns the value at the QueueList::head
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return T The value held at the Node pointed to by QueueList::head
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
T QueueList<T>::next() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (!isEmpty())
 | 
					 | 
				
			||||||
    std::cout << "[" << head->data << "] is next in queue\n";
 | 
					 | 
				
			||||||
  else std::cout << "Our queue is empty...\n";
 | 
					 | 
				
			||||||
  // If the queue has data we return it, otherwise we return the smallest possible int (error)
 | 
					 | 
				
			||||||
  return (!isEmpty()) ? head->data : T();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** isEmpty
 | 
					 | 
				
			||||||
 * @brief Determine if the QueueList is empty
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return true If the QueueList::head is NULL
 | 
					 | 
				
			||||||
 * @return false If the QueueList::head contains data
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
bool QueueList<T>::isEmpty() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  return head == NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** print
 | 
					 | 
				
			||||||
 * @brief Output the data held by the QueueList object
 | 
					 | 
				
			||||||
 *        Calls to the private print()
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
void QueueList<T>::print() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if(!isEmpty()) print(head);
 | 
					 | 
				
			||||||
  else std::cout << "Nothing to print, our queue is empty...\n";
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** makeEmpty
 | 
					 | 
				
			||||||
 * @brief Empty this QueueList object, deleting all associated Nodes
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
void QueueList<T>::makeEmpty()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *nextNode, *temp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (head == NULL) std::cout << "Our queue is empty...\n";
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    nextNode = head->next;
 | 
					 | 
				
			||||||
    delete head;
 | 
					 | 
				
			||||||
    head = NULL;
 | 
					 | 
				
			||||||
    tail = NULL;
 | 
					 | 
				
			||||||
    while(nextNode != NULL) {
 | 
					 | 
				
			||||||
      temp = nextNode;
 | 
					 | 
				
			||||||
      nextNode = nextNode->next;
 | 
					 | 
				
			||||||
      delete temp;
 | 
					 | 
				
			||||||
      temp = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************************************************************************
 | 
					 | 
				
			||||||
 * Private Member Functions
 | 
					 | 
				
			||||||
 *****************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** queue
 | 
					 | 
				
			||||||
 * @brief Private member to handle inserting value into the back of the queue
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param val Value to be inserted
 | 
					 | 
				
			||||||
 * @param tail The tail of the queue to insert into
 | 
					 | 
				
			||||||
 * @return true If the value was inserted
 | 
					 | 
				
			||||||
 * @return false If the value could not be inserted
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
bool QueueList<T>::enqueue(T val, Node *&tail)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *newNode = new Node(val);
 | 
					 | 
				
			||||||
  // If the queue is not empty, update next pointer to tail node
 | 
					 | 
				
			||||||
  if (!isEmpty()) {
 | 
					 | 
				
			||||||
    tail->next = newNode;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else head = newNode;
 | 
					 | 
				
			||||||
  // Always set tail to our newNode
 | 
					 | 
				
			||||||
  tail = newNode;
 | 
					 | 
				
			||||||
  return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** dequeue
 | 
					 | 
				
			||||||
 * @brief Removes a node from the front of the queue
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * @param head The head of the queue to remove a node from
 | 
					 | 
				
			||||||
 * @return T The value held at the node removed
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
T QueueList<T>::dequeue(Node *&head)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  // We already know the queue is not empty from public dequeue()
 | 
					 | 
				
			||||||
  Node *temp = head;
 | 
					 | 
				
			||||||
  // Store the data at the front of the queue before we delete the node
 | 
					 | 
				
			||||||
  T data = head->data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // If there is only one item in the queue 
 | 
					 | 
				
			||||||
  if (temp == tail) {
 | 
					 | 
				
			||||||
    tail = head = NULL;
 | 
					 | 
				
			||||||
    delete temp;
 | 
					 | 
				
			||||||
    return data;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Move the front of the queue to the next node
 | 
					 | 
				
			||||||
  head = head->next;
 | 
					 | 
				
			||||||
  // tail->next = NULL;
 | 
					 | 
				
			||||||
  // Delete the previous head node
 | 
					 | 
				
			||||||
  delete temp;
 | 
					 | 
				
			||||||
  return data;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** print
 | 
					 | 
				
			||||||
 * @brief Output the contents of a QueueList from the given Node to NULL
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param start The Node to begin traversing output from
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
void QueueList<T>::print(Node *start) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *temp = start;
 | 
					 | 
				
			||||||
  std::cout << "Queue Contents: ";
 | 
					 | 
				
			||||||
  while (temp != NULL) {
 | 
					 | 
				
			||||||
    std::cout << temp->data << " | ";
 | 
					 | 
				
			||||||
    temp = temp->next;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  std::cout << std::endl;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** makeEmpty
 | 
					 | 
				
			||||||
 * @brief Private member to empty this QueueList object, deletes all Nodes in the queue
 | 
					 | 
				
			||||||
 *        Does not print any output. Avoids destructors printing to cout
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * @param head The head of the queue to be deleted
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
void QueueList<T>::makeEmpty(Node *&head)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *nextNode, *temp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (head == NULL) return;
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    nextNode = head->next;
 | 
					 | 
				
			||||||
    delete head;
 | 
					 | 
				
			||||||
    head = NULL;
 | 
					 | 
				
			||||||
    tail = NULL;
 | 
					 | 
				
			||||||
    while(nextNode != NULL) {
 | 
					 | 
				
			||||||
      temp = nextNode;
 | 
					 | 
				
			||||||
      nextNode = nextNode->next;
 | 
					 | 
				
			||||||
      delete temp;
 | 
					 | 
				
			||||||
      temp = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
template class QueueList<TYPE>;
 | 
					 | 
				
			||||||
@ -45,4 +45,265 @@ class QueueList {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************************************************************************
 | 
				
			||||||
 | 
					 * Constructors, Destructors, Operators
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** copy constructor
 | 
				
			||||||
 | 
					 * @brief Construct a new QueueList::QueueList object from an existing one
 | 
				
			||||||
 | 
					 *        Creates a new deep copy of a given QueueList
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param rhs QueueList object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					QueueList<T>::QueueList(const QueueList<T>& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *cp = rhs.head;
 | 
				
			||||||
 | 
					  Node *tempHead;
 | 
				
			||||||
 | 
					  // If we are copying from an empty queue, create a new QueueList with a NULL head
 | 
				
			||||||
 | 
					  if (cp == NULL) head = NULL;
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    // If the queue has data, initialize a new queue with the head data
 | 
				
			||||||
 | 
					    head = new Node(cp->data);
 | 
				
			||||||
 | 
					    // Keep a temporary head node so we can return to it later
 | 
				
			||||||
 | 
					    tempHead = head;
 | 
				
			||||||
 | 
					    while (cp->next != NULL) {
 | 
				
			||||||
 | 
					      // Until we hit an end, create new nodes with the next node data
 | 
				
			||||||
 | 
					      cp = cp->next;
 | 
				
			||||||
 | 
					      head->next = new Node(cp->data);
 | 
				
			||||||
 | 
					      head = head->next;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    tail = head;
 | 
				
			||||||
 | 
					    head = tempHead;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** operator=
 | 
				
			||||||
 | 
					 * @brief Assign two QueueList objects equal using copy constr and class destr
 | 
				
			||||||
 | 
					 *        Pass the rhs by value to create local copy, swap its contents
 | 
				
			||||||
 | 
					 *        Destructor called on previous QueueList data at the end of this scope
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param rhs QueueList object passed by value
 | 
				
			||||||
 | 
					 * @return QueueList A deep copy of the rhs QueueList object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					QueueList<T> QueueList<T>::operator=(QueueList<T> rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (this == &rhs) return *this;
 | 
				
			||||||
 | 
					  // Swap the pointers, moving the previous head data to the local variable rhs
 | 
				
			||||||
 | 
					  std::swap(head, rhs.head);
 | 
				
			||||||
 | 
					  return *this;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** destructor
 | 
				
			||||||
 | 
					 * @brief Destroy the QueueList::QueueList object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					QueueList<T>::~QueueList()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  makeEmpty(head);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************************************************************************
 | 
				
			||||||
 | 
					 * Public Member Functions
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** enqueue
 | 
				
			||||||
 | 
					 * @brief Queue a value to the tail of our linked list
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param val The value to be inserted into the queue
 | 
				
			||||||
 | 
					 * @return true If the value was inserted in the queue
 | 
				
			||||||
 | 
					 * @return false If the value could not be queued
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					bool QueueList<T>::enqueue(T val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  bool inserted = enqueue(val, tail);
 | 
				
			||||||
 | 
					  if (inserted)
 | 
				
			||||||
 | 
					    std::cout << "[" << val << "] was inserted into the queue\n";
 | 
				
			||||||
 | 
					  else std::cout << "[" << val << "] could not be inserted into the queue\n";
 | 
				
			||||||
 | 
					  return inserted;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** dequeue
 | 
				
			||||||
 | 
					 * @brief returns the value at the QueueList::head and moves head to the next in queue
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return T The value held at the Node pointed to by QueueList::head
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T QueueList<T>::dequeue()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!isEmpty())
 | 
				
			||||||
 | 
					    std::cout << "[" << dequeue(head) << "] has been removed from our queue\n";
 | 
				
			||||||
 | 
					  else std::cout << "Nothing to dequeue, our queue is empty...\n";
 | 
				
			||||||
 | 
					  // If the queue has data we return it, otherwise we return the smallest possible int (error)
 | 
				
			||||||
 | 
					  return (!isEmpty()) ? head->data : T();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** next
 | 
				
			||||||
 | 
					 * @brief returns the value at the QueueList::head
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return T The value held at the Node pointed to by QueueList::head
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T QueueList<T>::next() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!isEmpty())
 | 
				
			||||||
 | 
					    std::cout << "[" << head->data << "] is next in queue\n";
 | 
				
			||||||
 | 
					  else std::cout << "Our queue is empty...\n";
 | 
				
			||||||
 | 
					  // If the queue has data we return it, otherwise we return the smallest possible int (error)
 | 
				
			||||||
 | 
					  return (!isEmpty()) ? head->data : T();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** isEmpty
 | 
				
			||||||
 | 
					 * @brief Determine if the QueueList is empty
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return true If the QueueList::head is NULL
 | 
				
			||||||
 | 
					 * @return false If the QueueList::head contains data
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					bool QueueList<T>::isEmpty() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return head == NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** print
 | 
				
			||||||
 | 
					 * @brief Output the data held by the QueueList object
 | 
				
			||||||
 | 
					 *        Calls to the private print()
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					void QueueList<T>::print() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if(!isEmpty()) print(head);
 | 
				
			||||||
 | 
					  else std::cout << "Nothing to print, our queue is empty...\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** makeEmpty
 | 
				
			||||||
 | 
					 * @brief Empty this QueueList object, deleting all associated Nodes
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					void QueueList<T>::makeEmpty()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *nextNode, *temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (head == NULL) std::cout << "Our queue is empty...\n";
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    nextNode = head->next;
 | 
				
			||||||
 | 
					    delete head;
 | 
				
			||||||
 | 
					    head = NULL;
 | 
				
			||||||
 | 
					    tail = NULL;
 | 
				
			||||||
 | 
					    while(nextNode != NULL) {
 | 
				
			||||||
 | 
					      temp = nextNode;
 | 
				
			||||||
 | 
					      nextNode = nextNode->next;
 | 
				
			||||||
 | 
					      delete temp;
 | 
				
			||||||
 | 
					      temp = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************************************************************************
 | 
				
			||||||
 | 
					 * Private Member Functions
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** queue
 | 
				
			||||||
 | 
					 * @brief Private member to handle inserting value into the back of the queue
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param val Value to be inserted
 | 
				
			||||||
 | 
					 * @param tail The tail of the queue to insert into
 | 
				
			||||||
 | 
					 * @return true If the value was inserted
 | 
				
			||||||
 | 
					 * @return false If the value could not be inserted
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					bool QueueList<T>::enqueue(T val, Node *&tail)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *newNode = new Node(val);
 | 
				
			||||||
 | 
					  // If the queue is not empty, update next pointer to tail node
 | 
				
			||||||
 | 
					  if (!isEmpty()) {
 | 
				
			||||||
 | 
					    tail->next = newNode;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else head = newNode;
 | 
				
			||||||
 | 
					  // Always set tail to our newNode
 | 
				
			||||||
 | 
					  tail = newNode;
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** dequeue
 | 
				
			||||||
 | 
					 * @brief Removes a node from the front of the queue
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param head The head of the queue to remove a node from
 | 
				
			||||||
 | 
					 * @return T The value held at the node removed
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T QueueList<T>::dequeue(Node *&head)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // We already know the queue is not empty from public dequeue()
 | 
				
			||||||
 | 
					  Node *temp = head;
 | 
				
			||||||
 | 
					  // Store the data at the front of the queue before we delete the node
 | 
				
			||||||
 | 
					  T data = head->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // If there is only one item in the queue
 | 
				
			||||||
 | 
					  if (temp == tail) {
 | 
				
			||||||
 | 
					    tail = head = NULL;
 | 
				
			||||||
 | 
					    delete temp;
 | 
				
			||||||
 | 
					    return data;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Move the front of the queue to the next node
 | 
				
			||||||
 | 
					  head = head->next;
 | 
				
			||||||
 | 
					  // tail->next = NULL;
 | 
				
			||||||
 | 
					  // Delete the previous head node
 | 
				
			||||||
 | 
					  delete temp;
 | 
				
			||||||
 | 
					  return data;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** print
 | 
				
			||||||
 | 
					 * @brief Output the contents of a QueueList from the given Node to NULL
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param start The Node to begin traversing output from
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					void QueueList<T>::print(Node *start) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *temp = start;
 | 
				
			||||||
 | 
					  std::cout << "Queue Contents: ";
 | 
				
			||||||
 | 
					  while (temp != NULL) {
 | 
				
			||||||
 | 
					    std::cout << temp->data << " | ";
 | 
				
			||||||
 | 
					    temp = temp->next;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  std::cout << std::endl;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** makeEmpty
 | 
				
			||||||
 | 
					 * @brief Private member to empty this QueueList object, deletes all Nodes in the queue
 | 
				
			||||||
 | 
					 *        Does not print any output. Avoids destructors printing to cout
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param head The head of the queue to be deleted
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					void QueueList<T>::makeEmpty(Node *&head)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *nextNode, *temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (head == NULL) return;
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    nextNode = head->next;
 | 
				
			||||||
 | 
					    delete head;
 | 
				
			||||||
 | 
					    head = NULL;
 | 
				
			||||||
 | 
					    tail = NULL;
 | 
				
			||||||
 | 
					    while(nextNode != NULL) {
 | 
				
			||||||
 | 
					      temp = nextNode;
 | 
				
			||||||
 | 
					      nextNode = nextNode->next;
 | 
				
			||||||
 | 
					      delete temp;
 | 
				
			||||||
 | 
					      temp = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,6 @@ cmake_minimum_required(VERSION 3.2)
 | 
				
			|||||||
# Define the project name
 | 
					# Define the project name
 | 
				
			||||||
project(Stack)
 | 
					project(Stack)
 | 
				
			||||||
# Define source files
 | 
					# Define source files
 | 
				
			||||||
set(SRC driver.cpp stacklist.cpp)
 | 
					set(SRC driver.cpp)
 | 
				
			||||||
# Build an executable
 | 
					# Build an executable
 | 
				
			||||||
add_executable(StackDriver ${SRC})
 | 
					add_executable(StackDriver ${SRC})
 | 
				
			||||||
 | 
				
			|||||||
@ -5,15 +5,8 @@ CXXFLAGS=-g -Wall
 | 
				
			|||||||
# Driver
 | 
					# Driver
 | 
				
			||||||
###############################################################################
 | 
					###############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
driver:	driver.cpp	stacklist.o
 | 
					driver:	driver.cpp
 | 
				
			||||||
	${CXX} ${CXXFLAGS} driver.cpp stacklist.o -o driver
 | 
						${CXX} ${CXXFLAGS} driver.cpp -o driver
 | 
				
			||||||
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
# StackList
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
stacklist.o:	stacklist.cpp stacklist.h
 | 
					 | 
				
			||||||
	${CXX} ${CXXFLAGS} -c stacklist.cpp -o stacklist.o
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
###############################################################################
 | 
					###############################################################################
 | 
				
			||||||
# Clean
 | 
					# Clean
 | 
				
			||||||
 | 
				
			|||||||
@ -1,252 +0,0 @@
 | 
				
			|||||||
/*#############################################################################
 | 
					 | 
				
			||||||
## Author: Shaun Reed                                                        ##
 | 
					 | 
				
			||||||
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved               ##
 | 
					 | 
				
			||||||
## About: An example of a stack implementation using linked lists            ##
 | 
					 | 
				
			||||||
##                                                                           ##
 | 
					 | 
				
			||||||
## Contact: shaunrd0@gmail.com  | URL: www.shaunreed.com | GitHub: shaunrd0  ##
 | 
					 | 
				
			||||||
##############################################################################
 | 
					 | 
				
			||||||
## stacklist.cpp
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "stacklist.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************************************************************************
 | 
					 | 
				
			||||||
 * Constructors, Destructors, Operators
 | 
					 | 
				
			||||||
 *****************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** copy constructor
 | 
					 | 
				
			||||||
 * @brief Construct a new StackList::StackList object from an existing one
 | 
					 | 
				
			||||||
 *        Creates a new deep copy of a given StackList
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param rhs StackList object
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
StackList<T>::StackList(const StackList<T>& rhs)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *cp = rhs.head;
 | 
					 | 
				
			||||||
  Node *tempHead;
 | 
					 | 
				
			||||||
  // If we are copying from an empty stack, create a new StackList with a NULL head
 | 
					 | 
				
			||||||
  if (cp == NULL) head = NULL;
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    // If the stack has data, initialize a new stack with the head data
 | 
					 | 
				
			||||||
    head = new Node(cp->data);
 | 
					 | 
				
			||||||
    // Keep a temporary head node so we can return to it later
 | 
					 | 
				
			||||||
    tempHead = head;
 | 
					 | 
				
			||||||
    while (cp->next != NULL) {
 | 
					 | 
				
			||||||
      // Until we hit an end, create new nodes with the next node data
 | 
					 | 
				
			||||||
      cp = cp->next;
 | 
					 | 
				
			||||||
      head->next = new Node(cp->data);
 | 
					 | 
				
			||||||
      head = head->next;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    head = tempHead;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** operator=
 | 
					 | 
				
			||||||
 * @brief Assign two StackList objects equal using copy constr and class destr
 | 
					 | 
				
			||||||
 *        Pass the rhs by value to create local copy, swap its contents
 | 
					 | 
				
			||||||
 *        Destructor called on previous StackList data at the end of this scope
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param rhs StackList object passed by value
 | 
					 | 
				
			||||||
 * @return StackList A deep copy of the rhs StackList object
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
StackList<T> StackList<T>::operator=(StackList<T> rhs)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (this == &rhs) return *this;
 | 
					 | 
				
			||||||
  // Swap the pointers, moving the previous head data to the local variable rhs 
 | 
					 | 
				
			||||||
  std::swap(head, rhs.head);
 | 
					 | 
				
			||||||
  return *this;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** destructor
 | 
					 | 
				
			||||||
 * @brief Destroy the StackList::StackList object
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
StackList<T>::~StackList()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  makeEmpty(head);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************************************************************************
 | 
					 | 
				
			||||||
 * Public Member Functions
 | 
					 | 
				
			||||||
 *****************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** push
 | 
					 | 
				
			||||||
 * @brief Push a value to the head of our linked list
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param val The value to be inserted
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
bool StackList<T>::push(T val)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  bool inserted = push(val, head);
 | 
					 | 
				
			||||||
  if (inserted)
 | 
					 | 
				
			||||||
    std::cout << "[" << val << "] was inserted into the stack\n";
 | 
					 | 
				
			||||||
  else std::cout << "[" << val << "] could not be inserted into the stack\n";
 | 
					 | 
				
			||||||
  return inserted;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** pop
 | 
					 | 
				
			||||||
 * @brief returns the value at the StackList::head
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return T The value held at the Node pointed to by StackList::head
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
T StackList<T>::pop()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (!isEmpty())
 | 
					 | 
				
			||||||
    std::cout << "[" << pop(head) << "] has been popped from our stack\n";
 | 
					 | 
				
			||||||
  else std::cout << "Nothing to pop, our stack is empty...\n";
 | 
					 | 
				
			||||||
  // If the stack has data we return it, otherwise we return the smallest possible int (error)
 | 
					 | 
				
			||||||
  return (!isEmpty()) ? head->data : T();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** top
 | 
					 | 
				
			||||||
 * @brief returns the value at the StackList::head
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return T The value held at the Node pointed to by StackList::head
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
T StackList<T>::top() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (!isEmpty())
 | 
					 | 
				
			||||||
    std::cout << "[" << head->data << "] is at the top of our stack\n";
 | 
					 | 
				
			||||||
  else std::cout << "Our stack is empty...\n";
 | 
					 | 
				
			||||||
  // If the stack has data we return it, otherwise we return the smallest possible int (error)
 | 
					 | 
				
			||||||
  return (!isEmpty()) ? head->data : T();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** makeEmpty
 | 
					 | 
				
			||||||
 * @brief Empty this StackList object, deleting all associated Nodes
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
void StackList<T>::makeEmpty()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *nextNode, *temp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (head == NULL) std::cout << "Our stack is empty...\n";
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    nextNode = head->next;
 | 
					 | 
				
			||||||
    delete head;
 | 
					 | 
				
			||||||
    head = NULL;
 | 
					 | 
				
			||||||
    while(nextNode != NULL) {
 | 
					 | 
				
			||||||
      temp = nextNode;
 | 
					 | 
				
			||||||
      nextNode = nextNode->next;
 | 
					 | 
				
			||||||
      delete temp;
 | 
					 | 
				
			||||||
      temp = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** isEmpty
 | 
					 | 
				
			||||||
 * @brief Determine if the StackList is empty
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return true If the StackList::head is NULL
 | 
					 | 
				
			||||||
 * @return false If the StackList::head contains data
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
bool StackList<T>::isEmpty() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  return head == NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** print
 | 
					 | 
				
			||||||
 * @brief Output the data held by the StackList object
 | 
					 | 
				
			||||||
 *        Calls to the private print()
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
void StackList<T>::print() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if(!isEmpty()) print(head);
 | 
					 | 
				
			||||||
  else std::cout << "Nothing to print, our stack is empty...\n";
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************************************************************************
 | 
					 | 
				
			||||||
 * Private Member Functions
 | 
					 | 
				
			||||||
 *****************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** push
 | 
					 | 
				
			||||||
 * @brief Private member to handle inserting value into the stack
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param val Value to be inserted
 | 
					 | 
				
			||||||
 * @param head The head of the stack to push the value into
 | 
					 | 
				
			||||||
 * @return true If the value was inserted
 | 
					 | 
				
			||||||
 * @return false If the value could not be inserted
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
bool StackList<T>::push(T val, Node *&head)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *newNode = new Node(val);
 | 
					 | 
				
			||||||
  // If the stack is not empty, update next pointer to head node
 | 
					 | 
				
			||||||
  if (!isEmpty()) newNode->next = head;
 | 
					 | 
				
			||||||
  // Always set head to our newNode
 | 
					 | 
				
			||||||
  head = newNode;
 | 
					 | 
				
			||||||
  return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** pop
 | 
					 | 
				
			||||||
 * @brief Private member to handle removing the head node from the stack
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param head The head node of the stack
 | 
					 | 
				
			||||||
 * @return T The last known value held at the head node before removal
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
T StackList<T>::pop(Node *&head)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  // We already know the stack is not empty from public pop()
 | 
					 | 
				
			||||||
  Node *temp = head;
 | 
					 | 
				
			||||||
  T data = temp->data;
 | 
					 | 
				
			||||||
  head = head->next;
 | 
					 | 
				
			||||||
  delete temp;
 | 
					 | 
				
			||||||
  return data;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** print
 | 
					 | 
				
			||||||
 * @brief Output the contents of a StackList from the given Node to NULL
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param start The Node to begin traversing output from
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
void StackList<T>::print(Node *start) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *temp = start;
 | 
					 | 
				
			||||||
  std::cout << "Stack Contents: ";
 | 
					 | 
				
			||||||
  while (temp != NULL) {
 | 
					 | 
				
			||||||
    std::cout << temp->data << " | ";
 | 
					 | 
				
			||||||
    temp = temp->next;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  std::cout << std::endl;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** makeEmpty
 | 
					 | 
				
			||||||
 * @brief Private member to empty this StackList object, deleting all associated Nodes
 | 
					 | 
				
			||||||
 *        Does not print any output. Avoids destructors printing to cout
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * @param head The head of the stack to be deleted
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template <typename T>
 | 
					 | 
				
			||||||
void StackList<T>::makeEmpty(Node *&head)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  Node *nextNode, *temp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (head == NULL) return;
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    nextNode = head->next;
 | 
					 | 
				
			||||||
    delete head;
 | 
					 | 
				
			||||||
    head = NULL;
 | 
					 | 
				
			||||||
    while(nextNode != NULL) {
 | 
					 | 
				
			||||||
      temp = nextNode;
 | 
					 | 
				
			||||||
      nextNode = nextNode->next;
 | 
					 | 
				
			||||||
      delete temp;
 | 
					 | 
				
			||||||
      temp = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
template class StackList<TYPE>;
 | 
					 | 
				
			||||||
@ -45,4 +45,244 @@ class StackList {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************************************************************************
 | 
				
			||||||
 | 
					 * Constructors, Destructors, Operators
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** copy constructor
 | 
				
			||||||
 | 
					 * @brief Construct a new StackList::StackList object from an existing one
 | 
				
			||||||
 | 
					 *        Creates a new deep copy of a given StackList
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param rhs StackList object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					StackList<T>::StackList(const StackList<T>& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *cp = rhs.head;
 | 
				
			||||||
 | 
					  Node *tempHead;
 | 
				
			||||||
 | 
					  // If we are copying from an empty stack, create a new StackList with a NULL head
 | 
				
			||||||
 | 
					  if (cp == NULL) head = NULL;
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    // If the stack has data, initialize a new stack with the head data
 | 
				
			||||||
 | 
					    head = new Node(cp->data);
 | 
				
			||||||
 | 
					    // Keep a temporary head node so we can return to it later
 | 
				
			||||||
 | 
					    tempHead = head;
 | 
				
			||||||
 | 
					    while (cp->next != NULL) {
 | 
				
			||||||
 | 
					      // Until we hit an end, create new nodes with the next node data
 | 
				
			||||||
 | 
					      cp = cp->next;
 | 
				
			||||||
 | 
					      head->next = new Node(cp->data);
 | 
				
			||||||
 | 
					      head = head->next;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    head = tempHead;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** operator=
 | 
				
			||||||
 | 
					 * @brief Assign two StackList objects equal using copy constr and class destr
 | 
				
			||||||
 | 
					 *        Pass the rhs by value to create local copy, swap its contents
 | 
				
			||||||
 | 
					 *        Destructor called on previous StackList data at the end of this scope
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param rhs StackList object passed by value
 | 
				
			||||||
 | 
					 * @return StackList A deep copy of the rhs StackList object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					StackList<T> StackList<T>::operator=(StackList<T> rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (this == &rhs) return *this;
 | 
				
			||||||
 | 
					  // Swap the pointers, moving the previous head data to the local variable rhs
 | 
				
			||||||
 | 
					  std::swap(head, rhs.head);
 | 
				
			||||||
 | 
					  return *this;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** destructor
 | 
				
			||||||
 | 
					 * @brief Destroy the StackList::StackList object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					StackList<T>::~StackList()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  makeEmpty(head);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************************************************************************
 | 
				
			||||||
 | 
					 * Public Member Functions
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** push
 | 
				
			||||||
 | 
					 * @brief Push a value to the head of our linked list
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param val The value to be inserted
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool StackList<T>::push(T val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  bool inserted = push(val, head);
 | 
				
			||||||
 | 
					  if (inserted)
 | 
				
			||||||
 | 
					    std::cout << "[" << val << "] was inserted into the stack\n";
 | 
				
			||||||
 | 
					  else std::cout << "[" << val << "] could not be inserted into the stack\n";
 | 
				
			||||||
 | 
					  return inserted;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** pop
 | 
				
			||||||
 | 
					 * @brief returns the value at the StackList::head
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return T The value held at the Node pointed to by StackList::head
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					T StackList<T>::pop()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!isEmpty())
 | 
				
			||||||
 | 
					    std::cout << "[" << pop(head) << "] has been popped from our stack\n";
 | 
				
			||||||
 | 
					  else std::cout << "Nothing to pop, our stack is empty...\n";
 | 
				
			||||||
 | 
					  // If the stack has data we return it, otherwise we return the smallest possible int (error)
 | 
				
			||||||
 | 
					  return (!isEmpty()) ? head->data : T();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** top
 | 
				
			||||||
 | 
					 * @brief returns the value at the StackList::head
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return T The value held at the Node pointed to by StackList::head
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					T StackList<T>::top() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!isEmpty())
 | 
				
			||||||
 | 
					    std::cout << "[" << head->data << "] is at the top of our stack\n";
 | 
				
			||||||
 | 
					  else std::cout << "Our stack is empty...\n";
 | 
				
			||||||
 | 
					  // If the stack has data we return it, otherwise we return the smallest possible int (error)
 | 
				
			||||||
 | 
					  return (!isEmpty()) ? head->data : T();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** makeEmpty
 | 
				
			||||||
 | 
					 * @brief Empty this StackList object, deleting all associated Nodes
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					void StackList<T>::makeEmpty()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *nextNode, *temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (head == NULL) std::cout << "Our stack is empty...\n";
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    nextNode = head->next;
 | 
				
			||||||
 | 
					    delete head;
 | 
				
			||||||
 | 
					    head = NULL;
 | 
				
			||||||
 | 
					    while(nextNode != NULL) {
 | 
				
			||||||
 | 
					      temp = nextNode;
 | 
				
			||||||
 | 
					      nextNode = nextNode->next;
 | 
				
			||||||
 | 
					      delete temp;
 | 
				
			||||||
 | 
					      temp = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** isEmpty
 | 
				
			||||||
 | 
					 * @brief Determine if the StackList is empty
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return true If the StackList::head is NULL
 | 
				
			||||||
 | 
					 * @return false If the StackList::head contains data
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool StackList<T>::isEmpty() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return head == NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** print
 | 
				
			||||||
 | 
					 * @brief Output the data held by the StackList object
 | 
				
			||||||
 | 
					 *        Calls to the private print()
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					void StackList<T>::print() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if(!isEmpty()) print(head);
 | 
				
			||||||
 | 
					  else std::cout << "Nothing to print, our stack is empty...\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************************************************************************
 | 
				
			||||||
 | 
					 * Private Member Functions
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** push
 | 
				
			||||||
 | 
					 * @brief Private member to handle inserting value into the stack
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param val Value to be inserted
 | 
				
			||||||
 | 
					 * @param head The head of the stack to push the value into
 | 
				
			||||||
 | 
					 * @return true If the value was inserted
 | 
				
			||||||
 | 
					 * @return false If the value could not be inserted
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool StackList<T>::push(T val, Node *&head)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *newNode = new Node(val);
 | 
				
			||||||
 | 
					  // If the stack is not empty, update next pointer to head node
 | 
				
			||||||
 | 
					  if (!isEmpty()) newNode->next = head;
 | 
				
			||||||
 | 
					  // Always set head to our newNode
 | 
				
			||||||
 | 
					  head = newNode;
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** pop
 | 
				
			||||||
 | 
					 * @brief Private member to handle removing the head node from the stack
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param head The head node of the stack
 | 
				
			||||||
 | 
					 * @return T The last known value held at the head node before removal
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					T StackList<T>::pop(Node *&head)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // We already know the stack is not empty from public pop()
 | 
				
			||||||
 | 
					  Node *temp = head;
 | 
				
			||||||
 | 
					  T data = temp->data;
 | 
				
			||||||
 | 
					  head = head->next;
 | 
				
			||||||
 | 
					  delete temp;
 | 
				
			||||||
 | 
					  return data;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** print
 | 
				
			||||||
 | 
					 * @brief Output the contents of a StackList from the given Node to NULL
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param start The Node to begin traversing output from
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					void StackList<T>::print(Node *start) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *temp = start;
 | 
				
			||||||
 | 
					  std::cout << "Stack Contents: ";
 | 
				
			||||||
 | 
					  while (temp != NULL) {
 | 
				
			||||||
 | 
					    std::cout << temp->data << " | ";
 | 
				
			||||||
 | 
					    temp = temp->next;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  std::cout << std::endl;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** makeEmpty
 | 
				
			||||||
 | 
					 * @brief Private member to empty this StackList object, deleting all associated Nodes
 | 
				
			||||||
 | 
					 *        Does not print any output. Avoids destructors printing to cout
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param head The head of the stack to be deleted
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					void StackList<T>::makeEmpty(Node *&head)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  Node *nextNode, *temp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (head == NULL) return;
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    nextNode = head->next;
 | 
				
			||||||
 | 
					    delete head;
 | 
				
			||||||
 | 
					    head = NULL;
 | 
				
			||||||
 | 
					    while(nextNode != NULL) {
 | 
				
			||||||
 | 
					      temp = nextNode;
 | 
				
			||||||
 | 
					      nextNode = nextNode->next;
 | 
				
			||||||
 | 
					      delete temp;
 | 
				
			||||||
 | 
					      temp = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,6 @@ cmake_minimum_required(VERSION 3.2)
 | 
				
			|||||||
# Define the project name
 | 
					# Define the project name
 | 
				
			||||||
project(VectorDriver)
 | 
					project(VectorDriver)
 | 
				
			||||||
# Define source files
 | 
					# Define source files
 | 
				
			||||||
set(SRC driver.cpp vector.cpp)
 | 
					set(SRC driver.cpp)
 | 
				
			||||||
# Build an executable
 | 
					# Build an executable
 | 
				
			||||||
add_executable(VectorDriver ${SRC})
 | 
					add_executable(VectorDriver ${SRC})
 | 
				
			||||||
 | 
				
			|||||||
@ -5,15 +5,8 @@ CXXFLAGS=-g -Wall
 | 
				
			|||||||
# Driver
 | 
					# Driver
 | 
				
			||||||
###############################################################################
 | 
					###############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
driver:	driver.cpp	vector.o
 | 
					driver:	driver.cpp
 | 
				
			||||||
	${CXX} ${CXXFLAGS} driver.cpp vector.o -o driver
 | 
						${CXX} ${CXXFLAGS} driver.cpp -o driver
 | 
				
			||||||
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
# Vector
 | 
					 | 
				
			||||||
###############################################################################
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
vector.o:	vector.cpp vector.h
 | 
					 | 
				
			||||||
	${CXX} ${CXXFLAGS} -c vector.cpp -o vector.o
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
###############################################################################
 | 
					###############################################################################
 | 
				
			||||||
# Clean
 | 
					# Clean
 | 
				
			||||||
 | 
				
			|||||||
@ -1,319 +0,0 @@
 | 
				
			|||||||
/*#############################################################################
 | 
					 | 
				
			||||||
## Author: Shaun Reed                                                        ##
 | 
					 | 
				
			||||||
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved               ##
 | 
					 | 
				
			||||||
## About: An example of a vector implementation using templates              ##
 | 
					 | 
				
			||||||
##                                                                           ##
 | 
					 | 
				
			||||||
## Contact: shaunrd0@gmail.com  | URL: www.shaunreed.com | GitHub: shaunrd0  ##
 | 
					 | 
				
			||||||
##############################################################################
 | 
					 | 
				
			||||||
## vector.cpp
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "vector.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************************************************************************
 | 
					 | 
				
			||||||
 * Constructors, Destructors, Operators
 | 
					 | 
				
			||||||
 *****************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** copy constructor
 | 
					 | 
				
			||||||
 * @brief Construct a new Vector::Vector object from an existing one
 | 
					 | 
				
			||||||
 *        Creates a new deep copy of a given Vector
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param rhs Vector<T> object
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
Vector<T>::Vector(const Vector<T>& rhs)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (rhs.getIndex() >= 0) {
 | 
					 | 
				
			||||||
    curIndex = rhs.getIndex();
 | 
					 | 
				
			||||||
    // Avoid copying over unused indices from parent Vector
 | 
					 | 
				
			||||||
    maxSize = rhs.getSize();
 | 
					 | 
				
			||||||
    data = new T[curIndex+1];
 | 
					 | 
				
			||||||
    for (int i = 0; i <= rhs.getIndex(); i++) {
 | 
					 | 
				
			||||||
      data[i] = rhs.getValue(i);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  } 
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    curIndex = -1;
 | 
					 | 
				
			||||||
    maxSize = 0;
 | 
					 | 
				
			||||||
    data = NULL;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** operator=
 | 
					 | 
				
			||||||
 * @brief Assign two Vector objects equal using copy constr and class destr
 | 
					 | 
				
			||||||
 *        Pass the rhs by value to create local copy, swap its contents
 | 
					 | 
				
			||||||
 *        Destructor called on previous Vector data at the end of this scope
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param rhs Vector object passed by value, creating a local variable
 | 
					 | 
				
			||||||
 * @return Vector<T> A deep copy of the rhs Vector object
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
Vector<T> Vector<T>::operator=(Vector<T> rhs)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (this == &rhs) return *this;
 | 
					 | 
				
			||||||
  // Swap the pointers, moving the previous head data to the local variable rhs
 | 
					 | 
				
			||||||
  std::swap(data, rhs.data);
 | 
					 | 
				
			||||||
  curIndex = rhs.getIndex();
 | 
					 | 
				
			||||||
  // Use the current size of the vector we are equal to
 | 
					 | 
				
			||||||
  // Avoids copying over unused indices
 | 
					 | 
				
			||||||
  maxSize = rhs.getSize();
 | 
					 | 
				
			||||||
  return *this;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** destructor
 | 
					 | 
				
			||||||
 * @brief Destroy the Vector::Vector object
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
Vector<T>::~Vector()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (!isEmpty()) makeEmpty();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************************************************************************
 | 
					 | 
				
			||||||
 * Public Member Functions
 | 
					 | 
				
			||||||
 *****************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** push
 | 
					 | 
				
			||||||
 * @brief Push a value to the end of our Vector
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param val The value to be inserted
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
bool Vector<T>::push(T val)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  bool inserted = push(val, data);
 | 
					 | 
				
			||||||
  if (inserted)
 | 
					 | 
				
			||||||
    std::cout << "[" << val << "] was inserted into the vector\n";
 | 
					 | 
				
			||||||
  else std::cout << "[" << val << "] could not be inserted into the vector\n";
 | 
					 | 
				
			||||||
  return inserted;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** pop
 | 
					 | 
				
			||||||
 * @brief returns the value at the Vector::data[curIndex] if it exists
 | 
					 | 
				
			||||||
 *        Once returned, the curIndex is decremented via data[curIndex--]
 | 
					 | 
				
			||||||
 *        If the vector is empty, returns INT32_MIN
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return T The value held at the Node pointed to by Vector::data[index]
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
T Vector<T>::pop()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  T val;
 | 
					 | 
				
			||||||
  if (!isEmpty()) {
 | 
					 | 
				
			||||||
    val = pop(data);
 | 
					 | 
				
			||||||
    std::cout << "[" << val << "] has been popped from our Vector\n";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else std::cout << "Nothing to pop, our Vector is empty...\n";
 | 
					 | 
				
			||||||
  return val;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** makeEmpty
 | 
					 | 
				
			||||||
 * @brief Empty this Vector object, deleting all associated data
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
void Vector<T>::makeEmpty()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (isEmpty()) {
 | 
					 | 
				
			||||||
    std::cout << "Cannot makeEmpty, our Vector is already empty...\n";
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else makeEmpty(data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** peek
 | 
					 | 
				
			||||||
 * @brief returns the value at the end of the vector
 | 
					 | 
				
			||||||
 *  If the vector is empty, returns INT32_MIN
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return T The value held at the current data[index] of the vector
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
T Vector<T>::peek() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  T val;
 | 
					 | 
				
			||||||
  if (!isEmpty()) {
 | 
					 | 
				
			||||||
    val = peek(data);
 | 
					 | 
				
			||||||
    std::cout << "[" << peek(data) << "] is at the end of our vector\n";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else std::cout << "Nothing to peek, our vector is empty...\n";
 | 
					 | 
				
			||||||
  return val;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** isEmpty
 | 
					 | 
				
			||||||
 * @brief Determine if the Vector is empty
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return true If the Vector::data is NULL
 | 
					 | 
				
			||||||
 * @return false If the Vector::data contains any values
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
bool Vector<T>::isEmpty() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  return data == NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** isFull
 | 
					 | 
				
			||||||
 * @brief Determine if the Vector is full
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return true If the Vector::size is equal to the current index
 | 
					 | 
				
			||||||
 * @return false If the Vector::size is greater than the current index
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
bool Vector<T>::isFull() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  return getSize() == getMax() || data == NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** print
 | 
					 | 
				
			||||||
 * @brief Output the data held by the Vector object
 | 
					 | 
				
			||||||
 *        Calls to the private print()
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
void Vector<T>::print() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if(!isEmpty()) print(data);
 | 
					 | 
				
			||||||
  else std::cout << "Nothing to print, our vector is empty...\n";
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** getMax
 | 
					 | 
				
			||||||
 * @brief Returns the literal maximum size of the vector
 | 
					 | 
				
			||||||
 *        Not offset to match any index - Vector with max size 3 has indices 0-2
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return int at this->maxSize
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
int Vector<T>::getMax() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  return maxSize;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** getSize
 | 
					 | 
				
			||||||
 * @brief Returns the current size of the vector
 | 
					 | 
				
			||||||
 *        AKA the current number of indices being used, NOT the max indices
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * @return int at this->curIndex + 1
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
int Vector<T>::getSize() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  return curIndex + 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** getIndex
 | 
					 | 
				
			||||||
 * @brief Returns the current index of the vector
 | 
					 | 
				
			||||||
 *        AKA the last index the vector wrote to
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return int at this->curIndex
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
int Vector<T>::getIndex() const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  return curIndex;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TODO: use operator[](){...} instead
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** getValue
 | 
					 | 
				
			||||||
 * @brief Get the value stored at a given index within the vector
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * @param index The index containing the value to be returned
 | 
					 | 
				
			||||||
 * @return T The value held at the index given
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
T Vector<T>::getValue(int index) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  return data[index];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************************************************************************
 | 
					 | 
				
			||||||
 * Private Member Functions
 | 
					 | 
				
			||||||
 *****************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** push
 | 
					 | 
				
			||||||
 * @brief Private member to handle inserting value into the vector
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param val Value to be inserted
 | 
					 | 
				
			||||||
 * @param data The data of the vector to push the value into
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return true If the value was inserted
 | 
					 | 
				
			||||||
 * @return false If the value could not be inserted
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
bool Vector<T>::push(T val, T *&data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  T *temp;
 | 
					 | 
				
			||||||
  if (isFull()) {
 | 
					 | 
				
			||||||
    if (maxSize <= 0) maxSize = 1;
 | 
					 | 
				
			||||||
    else maxSize *= 2;
 | 
					 | 
				
			||||||
    temp = new T[maxSize];
 | 
					 | 
				
			||||||
    for (int i = 0; i <= curIndex; i++) {
 | 
					 | 
				
			||||||
      temp[i] = data[i];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    std::swap(data, temp);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  curIndex += 1;
 | 
					 | 
				
			||||||
  data[curIndex] = val;
 | 
					 | 
				
			||||||
  return data[curIndex] == val;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** pop
 | 
					 | 
				
			||||||
 * @brief Returns the value held at the last index within the Vector
 | 
					 | 
				
			||||||
 *        Decrements the curIndex after storing the value to be returned
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * @param data The Vector data to modify
 | 
					 | 
				
			||||||
 * @return T The value stored at the index removed from the end of the Vector
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
T Vector<T>::pop(T *&data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  // We already know the vector is not empty from public pop()
 | 
					 | 
				
			||||||
  T val = data[curIndex--];
 | 
					 | 
				
			||||||
  if (curIndex < 0) makeEmpty(data);
 | 
					 | 
				
			||||||
  return val;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** makeEmpty
 | 
					 | 
				
			||||||
 * @brief Private member to empty Vector object, deleting all associated data
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * @param data The data of the Vector to be deleted
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
void Vector<T>::makeEmpty(T *&data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  delete[] data;
 | 
					 | 
				
			||||||
  maxSize = 0;
 | 
					 | 
				
			||||||
  curIndex = -1;
 | 
					 | 
				
			||||||
  data = NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** peek
 | 
					 | 
				
			||||||
 * @brief Private member to display the value at the end of our Vector
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * @param data The Vector data to peek
 | 
					 | 
				
			||||||
 * @return T The value stored at the end of the Vector
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
T Vector<T>::peek(T *data) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  // We already know the vector is not empty from public peek()
 | 
					 | 
				
			||||||
  return data[curIndex];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** print
 | 
					 | 
				
			||||||
 * @brief Output the contents of a Vector from the beginning to the end
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param data The data within the Vector to output
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
template<typename T>
 | 
					 | 
				
			||||||
void Vector<T>::print(T *data) const
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  std::cout << "Vector Contents: ";
 | 
					 | 
				
			||||||
  for (int i = 0; i <= curIndex; i++) {
 | 
					 | 
				
			||||||
    std::cout << data[i] << " | ";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  std::cout << std::endl;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Instantiate relevant type templates for this class
 | 
					 | 
				
			||||||
template class Vector<TYPE>;
 | 
					 | 
				
			||||||
@ -48,4 +48,309 @@ class Vector {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************************************************************************
 | 
				
			||||||
 | 
					 * Constructors, Destructors, Operators
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** copy constructor
 | 
				
			||||||
 | 
					 * @brief Construct a new Vector::Vector object from an existing one
 | 
				
			||||||
 | 
					 *        Creates a new deep copy of a given Vector
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param rhs Vector<T> object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					Vector<T>::Vector(const Vector<T>& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (rhs.getIndex() >= 0) {
 | 
				
			||||||
 | 
					    curIndex = rhs.getIndex();
 | 
				
			||||||
 | 
					    // Avoid copying over unused indices from parent Vector
 | 
				
			||||||
 | 
					    maxSize = rhs.getSize();
 | 
				
			||||||
 | 
					    data = new T[curIndex+1];
 | 
				
			||||||
 | 
					    for (int i = 0; i <= rhs.getIndex(); i++) {
 | 
				
			||||||
 | 
					      data[i] = rhs.getValue(i);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else {
 | 
				
			||||||
 | 
					    curIndex = -1;
 | 
				
			||||||
 | 
					    maxSize = 0;
 | 
				
			||||||
 | 
					    data = NULL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** operator=
 | 
				
			||||||
 | 
					 * @brief Assign two Vector objects equal using copy constr and class destr
 | 
				
			||||||
 | 
					 *        Pass the rhs by value to create local copy, swap its contents
 | 
				
			||||||
 | 
					 *        Destructor called on previous Vector data at the end of this scope
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param rhs Vector object passed by value, creating a local variable
 | 
				
			||||||
 | 
					 * @return Vector<T> A deep copy of the rhs Vector object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					Vector<T> Vector<T>::operator=(Vector<T> rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (this == &rhs) return *this;
 | 
				
			||||||
 | 
					  // Swap the pointers, moving the previous head data to the local variable rhs
 | 
				
			||||||
 | 
					  std::swap(data, rhs.data);
 | 
				
			||||||
 | 
					  curIndex = rhs.getIndex();
 | 
				
			||||||
 | 
					  // Use the current size of the vector we are equal to
 | 
				
			||||||
 | 
					  // Avoids copying over unused indices
 | 
				
			||||||
 | 
					  maxSize = rhs.getSize();
 | 
				
			||||||
 | 
					  return *this;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** destructor
 | 
				
			||||||
 | 
					 * @brief Destroy the Vector::Vector object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					Vector<T>::~Vector()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!isEmpty()) makeEmpty();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************************************************************************
 | 
				
			||||||
 | 
					 * Public Member Functions
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** push
 | 
				
			||||||
 | 
					 * @brief Push a value to the end of our Vector
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param val The value to be inserted
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					bool Vector<T>::push(T val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  bool inserted = push(val, data);
 | 
				
			||||||
 | 
					  if (inserted)
 | 
				
			||||||
 | 
					    std::cout << "[" << val << "] was inserted into the vector\n";
 | 
				
			||||||
 | 
					  else std::cout << "[" << val << "] could not be inserted into the vector\n";
 | 
				
			||||||
 | 
					  return inserted;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** pop
 | 
				
			||||||
 | 
					 * @brief returns the value at the Vector::data[curIndex] if it exists
 | 
				
			||||||
 | 
					 *        Once returned, the curIndex is decremented via data[curIndex--]
 | 
				
			||||||
 | 
					 *        If the vector is empty, returns INT32_MIN
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return T The value held at the Node pointed to by Vector::data[index]
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T Vector<T>::pop()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  T val;
 | 
				
			||||||
 | 
					  if (!isEmpty()) {
 | 
				
			||||||
 | 
					    val = pop(data);
 | 
				
			||||||
 | 
					    std::cout << "[" << val << "] has been popped from our Vector\n";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else std::cout << "Nothing to pop, our Vector is empty...\n";
 | 
				
			||||||
 | 
					  return val;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** makeEmpty
 | 
				
			||||||
 | 
					 * @brief Empty this Vector object, deleting all associated data
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					void Vector<T>::makeEmpty()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (isEmpty()) {
 | 
				
			||||||
 | 
					    std::cout << "Cannot makeEmpty, our Vector is already empty...\n";
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else makeEmpty(data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** peek
 | 
				
			||||||
 | 
					 * @brief returns the value at the end of the vector
 | 
				
			||||||
 | 
					 *  If the vector is empty, returns INT32_MIN
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return T The value held at the current data[index] of the vector
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T Vector<T>::peek() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  T val;
 | 
				
			||||||
 | 
					  if (!isEmpty()) {
 | 
				
			||||||
 | 
					    val = peek(data);
 | 
				
			||||||
 | 
					    std::cout << "[" << peek(data) << "] is at the end of our vector\n";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  else std::cout << "Nothing to peek, our vector is empty...\n";
 | 
				
			||||||
 | 
					  return val;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** isEmpty
 | 
				
			||||||
 | 
					 * @brief Determine if the Vector is empty
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return true If the Vector::data is NULL
 | 
				
			||||||
 | 
					 * @return false If the Vector::data contains any values
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					bool Vector<T>::isEmpty() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return data == NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** isFull
 | 
				
			||||||
 | 
					 * @brief Determine if the Vector is full
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return true If the Vector::size is equal to the current index
 | 
				
			||||||
 | 
					 * @return false If the Vector::size is greater than the current index
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					bool Vector<T>::isFull() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return getSize() == getMax() || data == NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** print
 | 
				
			||||||
 | 
					 * @brief Output the data held by the Vector object
 | 
				
			||||||
 | 
					 *        Calls to the private print()
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					void Vector<T>::print() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if(!isEmpty()) print(data);
 | 
				
			||||||
 | 
					  else std::cout << "Nothing to print, our vector is empty...\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** getMax
 | 
				
			||||||
 | 
					 * @brief Returns the literal maximum size of the vector
 | 
				
			||||||
 | 
					 *        Not offset to match any index - Vector with max size 3 has indices 0-2
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return int at this->maxSize
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					int Vector<T>::getMax() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return maxSize;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** getSize
 | 
				
			||||||
 | 
					 * @brief Returns the current size of the vector
 | 
				
			||||||
 | 
					 *        AKA the current number of indices being used, NOT the max indices
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return int at this->curIndex + 1
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					int Vector<T>::getSize() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return curIndex + 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** getIndex
 | 
				
			||||||
 | 
					 * @brief Returns the current index of the vector
 | 
				
			||||||
 | 
					 *        AKA the last index the vector wrote to
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return int at this->curIndex
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					int Vector<T>::getIndex() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return curIndex;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: use operator[](){...} instead
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** getValue
 | 
				
			||||||
 | 
					 * @brief Get the value stored at a given index within the vector
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param index The index containing the value to be returned
 | 
				
			||||||
 | 
					 * @return T The value held at the index given
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T Vector<T>::getValue(int index) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return data[index];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************************************************************************
 | 
				
			||||||
 | 
					 * Private Member Functions
 | 
				
			||||||
 | 
					 *****************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** push
 | 
				
			||||||
 | 
					 * @brief Private member to handle inserting value into the vector
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param val Value to be inserted
 | 
				
			||||||
 | 
					 * @param data The data of the vector to push the value into
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return true If the value was inserted
 | 
				
			||||||
 | 
					 * @return false If the value could not be inserted
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					bool Vector<T>::push(T val, T *&data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  T *temp;
 | 
				
			||||||
 | 
					  if (isFull()) {
 | 
				
			||||||
 | 
					    if (maxSize <= 0) maxSize = 1;
 | 
				
			||||||
 | 
					    else maxSize *= 2;
 | 
				
			||||||
 | 
					    temp = new T[maxSize];
 | 
				
			||||||
 | 
					    for (int i = 0; i <= curIndex; i++) {
 | 
				
			||||||
 | 
					      temp[i] = data[i];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    std::swap(data, temp);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  curIndex += 1;
 | 
				
			||||||
 | 
					  data[curIndex] = val;
 | 
				
			||||||
 | 
					  return data[curIndex] == val;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** pop
 | 
				
			||||||
 | 
					 * @brief Returns the value held at the last index within the Vector
 | 
				
			||||||
 | 
					 *        Decrements the curIndex after storing the value to be returned
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param data The Vector data to modify
 | 
				
			||||||
 | 
					 * @return T The value stored at the index removed from the end of the Vector
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T Vector<T>::pop(T *&data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // We already know the vector is not empty from public pop()
 | 
				
			||||||
 | 
					  T val = data[curIndex--];
 | 
				
			||||||
 | 
					  if (curIndex < 0) makeEmpty(data);
 | 
				
			||||||
 | 
					  return val;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** makeEmpty
 | 
				
			||||||
 | 
					 * @brief Private member to empty Vector object, deleting all associated data
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param data The data of the Vector to be deleted
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					void Vector<T>::makeEmpty(T *&data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  delete[] data;
 | 
				
			||||||
 | 
					  maxSize = 0;
 | 
				
			||||||
 | 
					  curIndex = -1;
 | 
				
			||||||
 | 
					  data = NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** peek
 | 
				
			||||||
 | 
					 * @brief Private member to display the value at the end of our Vector
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param data The Vector data to peek
 | 
				
			||||||
 | 
					 * @return T The value stored at the end of the Vector
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T Vector<T>::peek(T *data) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // We already know the vector is not empty from public peek()
 | 
				
			||||||
 | 
					  return data[curIndex];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** print
 | 
				
			||||||
 | 
					 * @brief Output the contents of a Vector from the beginning to the end
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param data The data within the Vector to output
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					void Vector<T>::print(T *data) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  std::cout << "Vector Contents: ";
 | 
				
			||||||
 | 
					  for (int i = 0; i <= curIndex; i++) {
 | 
				
			||||||
 | 
					    std::cout << data[i] << " | ";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  std::cout << std::endl;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user