diff --git a/cpp/datastructs/templates/doublelist/CMakeLists.txt b/cpp/datastructs/templates/doublelist/CMakeLists.txt index fbf5123..9b20ea9 100644 --- a/cpp/datastructs/templates/doublelist/CMakeLists.txt +++ b/cpp/datastructs/templates/doublelist/CMakeLists.txt @@ -13,6 +13,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.2) # Define the project name project(DoubleList) # Define source files -set(SRC driver.cpp doublelist.cpp) +set(SRC driver.cpp) # Build an executable add_executable(DoubleListDriver ${SRC}) diff --git a/cpp/datastructs/templates/doublelist/Makefile b/cpp/datastructs/templates/doublelist/Makefile index ac03db3..368915f 100644 --- a/cpp/datastructs/templates/doublelist/Makefile +++ b/cpp/datastructs/templates/doublelist/Makefile @@ -5,15 +5,8 @@ CXXFLAGS=-g -Wall # Driver ############################################################################### -driver: driver.cpp doublelist.o - ${CXX} ${CXXFLAGS} driver.cpp doublelist.o -o driver - -############################################################################### -# DoubleList -############################################################################### - -doublelist.o: doublelist.cpp doublelist.h - ${CXX} ${CXXFLAGS} -c doublelist.cpp -o doublelist.o +driver: driver.cpp + ${CXX} ${CXXFLAGS} driver.cpp -o driver ############################################################################### # Clean diff --git a/cpp/datastructs/templates/doublelist/doublelist.cpp b/cpp/datastructs/templates/doublelist/doublelist.cpp deleted file mode 100644 index 86a9918..0000000 --- a/cpp/datastructs/templates/doublelist/doublelist.cpp +++ /dev/null @@ -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 -DoubleList::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 -DoubleList DoubleList::operator=(DoubleList rhs) -{ - if (this == &rhs) return *this; - std::swap(head, rhs.head); - return *this; -} - -/** destructor - * @brief Destroy the DoubleList::DoubleList object - */ -template -DoubleList::~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 -bool DoubleList::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 -bool DoubleList::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 -bool DoubleList::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 -bool DoubleList::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 -void DoubleList::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 -bool DoubleList::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 -T DoubleList::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 -void DoubleList::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 -bool DoubleList::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 -bool DoubleList::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 -bool DoubleList::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 -bool DoubleList::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 -bool DoubleList::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 DoubleList::Node* DoubleList::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 -void DoubleList::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; diff --git a/cpp/datastructs/templates/doublelist/doublelist.h b/cpp/datastructs/templates/doublelist/doublelist.h index 360c0ea..33d61c1 100644 --- a/cpp/datastructs/templates/doublelist/doublelist.h +++ b/cpp/datastructs/templates/doublelist/doublelist.h @@ -49,4 +49,353 @@ class DoubleList { 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 +DoubleList::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 +DoubleList DoubleList::operator=(DoubleList rhs) +{ + if (this == &rhs) return *this; + std::swap(head, rhs.head); + return *this; +} + +/** destructor + * @brief Destroy the DoubleList::DoubleList object + */ +template +DoubleList::~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 +bool DoubleList::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 +bool DoubleList::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 +bool DoubleList::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 +bool DoubleList::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 +void DoubleList::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 +bool DoubleList::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 +T DoubleList::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 +void DoubleList::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 +bool DoubleList::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 +bool DoubleList::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 +bool DoubleList::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 +bool DoubleList::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 +bool DoubleList::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 DoubleList::Node* DoubleList::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 +void DoubleList::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 diff --git a/cpp/datastructs/templates/queuelist/CMakeLists.txt b/cpp/datastructs/templates/queuelist/CMakeLists.txt index d88a2ab..49fe96c 100644 --- a/cpp/datastructs/templates/queuelist/CMakeLists.txt +++ b/cpp/datastructs/templates/queuelist/CMakeLists.txt @@ -13,6 +13,6 @@ cmake_minimum_required(VERSION 3.2) # Define the project name project(Queue) # Define source files -set(SRC driver.cpp queuelist.cpp) +set(SRC driver.cpp) # Build an executable add_executable(QueueDriver ${SRC}) diff --git a/cpp/datastructs/templates/queuelist/Makefile b/cpp/datastructs/templates/queuelist/Makefile index 0197dd3..368915f 100644 --- a/cpp/datastructs/templates/queuelist/Makefile +++ b/cpp/datastructs/templates/queuelist/Makefile @@ -5,15 +5,8 @@ CXXFLAGS=-g -Wall # Driver ############################################################################### -driver: driver.cpp queuelist.o - ${CXX} ${CXXFLAGS} driver.cpp queuelist.o -o driver - -############################################################################### -# QueueList -############################################################################### - -queuelist.o: queuelist.cpp queuelist.h - ${CXX} ${CXXFLAGS} -c queuelist.cpp -o queuelist.o +driver: driver.cpp + ${CXX} ${CXXFLAGS} driver.cpp -o driver ############################################################################### # Clean diff --git a/cpp/datastructs/templates/queuelist/queuelist.cpp b/cpp/datastructs/templates/queuelist/queuelist.cpp deleted file mode 100644 index bf0f679..0000000 --- a/cpp/datastructs/templates/queuelist/queuelist.cpp +++ /dev/null @@ -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 -QueueList::QueueList(const QueueList& 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 -QueueList QueueList::operator=(QueueList 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 -QueueList::~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 -bool QueueList::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 -T QueueList::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 -T QueueList::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 -bool QueueList::isEmpty() const -{ - return head == NULL; -} - -/** print - * @brief Output the data held by the QueueList object - * Calls to the private print() - */ -template -void QueueList::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 -void QueueList::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 -bool QueueList::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 -T QueueList::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 -void QueueList::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 -void QueueList::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; diff --git a/cpp/datastructs/templates/queuelist/queuelist.h b/cpp/datastructs/templates/queuelist/queuelist.h index dfc3742..5dc4ae1 100644 --- a/cpp/datastructs/templates/queuelist/queuelist.h +++ b/cpp/datastructs/templates/queuelist/queuelist.h @@ -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 +QueueList::QueueList(const QueueList& 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 +QueueList QueueList::operator=(QueueList 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 +QueueList::~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 +bool QueueList::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 +T QueueList::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 +T QueueList::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 +bool QueueList::isEmpty() const +{ + return head == NULL; +} + +/** print + * @brief Output the data held by the QueueList object + * Calls to the private print() + */ +template +void QueueList::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 +void QueueList::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 +bool QueueList::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 +T QueueList::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 +void QueueList::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 +void QueueList::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 diff --git a/cpp/datastructs/templates/stacklist/CMakeLists.txt b/cpp/datastructs/templates/stacklist/CMakeLists.txt index bbb5d55..a1fb018 100644 --- a/cpp/datastructs/templates/stacklist/CMakeLists.txt +++ b/cpp/datastructs/templates/stacklist/CMakeLists.txt @@ -13,6 +13,6 @@ cmake_minimum_required(VERSION 3.2) # Define the project name project(Stack) # Define source files -set(SRC driver.cpp stacklist.cpp) +set(SRC driver.cpp) # Build an executable add_executable(StackDriver ${SRC}) diff --git a/cpp/datastructs/templates/stacklist/Makefile b/cpp/datastructs/templates/stacklist/Makefile index a0e74d6..368915f 100644 --- a/cpp/datastructs/templates/stacklist/Makefile +++ b/cpp/datastructs/templates/stacklist/Makefile @@ -5,15 +5,8 @@ CXXFLAGS=-g -Wall # Driver ############################################################################### -driver: driver.cpp stacklist.o - ${CXX} ${CXXFLAGS} driver.cpp stacklist.o -o driver - -############################################################################### -# StackList -############################################################################### - -stacklist.o: stacklist.cpp stacklist.h - ${CXX} ${CXXFLAGS} -c stacklist.cpp -o stacklist.o +driver: driver.cpp + ${CXX} ${CXXFLAGS} driver.cpp -o driver ############################################################################### # Clean diff --git a/cpp/datastructs/templates/stacklist/stacklist.cpp b/cpp/datastructs/templates/stacklist/stacklist.cpp deleted file mode 100644 index 40df1a8..0000000 --- a/cpp/datastructs/templates/stacklist/stacklist.cpp +++ /dev/null @@ -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 -StackList::StackList(const StackList& 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 -StackList StackList::operator=(StackList 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 -StackList::~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 -bool StackList::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 -T StackList::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 -T StackList::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 -void StackList::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 -bool StackList::isEmpty() const -{ - return head == NULL; -} - -/** print - * @brief Output the data held by the StackList object - * Calls to the private print() - */ -template -void StackList::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 -bool StackList::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 -T StackList::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 -void StackList::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 -void StackList::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; diff --git a/cpp/datastructs/templates/stacklist/stacklist.h b/cpp/datastructs/templates/stacklist/stacklist.h index 7d762c0..807cd0e 100644 --- a/cpp/datastructs/templates/stacklist/stacklist.h +++ b/cpp/datastructs/templates/stacklist/stacklist.h @@ -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 +StackList::StackList(const StackList& 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 +StackList StackList::operator=(StackList 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 +StackList::~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 +bool StackList::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 +T StackList::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 +T StackList::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 +void StackList::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 +bool StackList::isEmpty() const +{ + return head == NULL; +} + +/** print + * @brief Output the data held by the StackList object + * Calls to the private print() + */ +template +void StackList::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 +bool StackList::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 +T StackList::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 +void StackList::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 +void StackList::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 diff --git a/cpp/datastructs/templates/vector/CMakeLists.txt b/cpp/datastructs/templates/vector/CMakeLists.txt index bb20e44..6155f12 100644 --- a/cpp/datastructs/templates/vector/CMakeLists.txt +++ b/cpp/datastructs/templates/vector/CMakeLists.txt @@ -13,6 +13,6 @@ cmake_minimum_required(VERSION 3.2) # Define the project name project(VectorDriver) # Define source files -set(SRC driver.cpp vector.cpp) +set(SRC driver.cpp) # Build an executable add_executable(VectorDriver ${SRC}) diff --git a/cpp/datastructs/templates/vector/Makefile b/cpp/datastructs/templates/vector/Makefile index ddd71fd..368915f 100644 --- a/cpp/datastructs/templates/vector/Makefile +++ b/cpp/datastructs/templates/vector/Makefile @@ -5,15 +5,8 @@ CXXFLAGS=-g -Wall # Driver ############################################################################### -driver: driver.cpp vector.o - ${CXX} ${CXXFLAGS} driver.cpp vector.o -o driver - -############################################################################### -# Vector -############################################################################### - -vector.o: vector.cpp vector.h - ${CXX} ${CXXFLAGS} -c vector.cpp -o vector.o +driver: driver.cpp + ${CXX} ${CXXFLAGS} driver.cpp -o driver ############################################################################### # Clean diff --git a/cpp/datastructs/templates/vector/vector.cpp b/cpp/datastructs/templates/vector/vector.cpp deleted file mode 100644 index a329bb1..0000000 --- a/cpp/datastructs/templates/vector/vector.cpp +++ /dev/null @@ -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 object - */ -template -Vector::Vector(const Vector& 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 A deep copy of the rhs Vector object - */ -template -Vector Vector::operator=(Vector 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 -Vector::~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 -bool Vector::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 -T Vector::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 -void Vector::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 -T Vector::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 -bool Vector::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 -bool Vector::isFull() const -{ - return getSize() == getMax() || data == NULL; -} - -/** print - * @brief Output the data held by the Vector object - * Calls to the private print() - */ -template -void Vector::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 -int Vector::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 -int Vector::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 -int Vector::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 -T Vector::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 -bool Vector::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 -T Vector::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 -void Vector::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 -T Vector::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 -void Vector::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; diff --git a/cpp/datastructs/templates/vector/vector.h b/cpp/datastructs/templates/vector/vector.h index 834e2ca..b47aad8 100644 --- a/cpp/datastructs/templates/vector/vector.h +++ b/cpp/datastructs/templates/vector/vector.h @@ -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 object + */ +template +Vector::Vector(const Vector& 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 A deep copy of the rhs Vector object + */ +template +Vector Vector::operator=(Vector 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 +Vector::~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 +bool Vector::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 +T Vector::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 +void Vector::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 +T Vector::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 +bool Vector::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 +bool Vector::isFull() const +{ + return getSize() == getMax() || data == NULL; +} + +/** print + * @brief Output the data held by the Vector object + * Calls to the private print() + */ +template +void Vector::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 +int Vector::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 +int Vector::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 +int Vector::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 +T Vector::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 +bool Vector::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 +T Vector::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 +void Vector::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 +T Vector::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 +void Vector::print(T *data) const +{ + std::cout << "Vector Contents: "; + for (int i = 0; i <= curIndex; i++) { + std::cout << data[i] << " | "; + } + std::cout << std::endl; +} + + #endif