Initial commit for starting work on templates

This commit is contained in:
Shaun Reed 2020-07-23 17:58:18 -04:00
parent a692a0f631
commit 2c6400cc87
24 changed files with 2357 additions and 0 deletions

View File

@ -0,0 +1,17 @@
###############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved ##
## About: A basic CMakeLists configuration to test BST implementation ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################
## CMakeLists.txt
#
cmake_minimum_required(VERSION 3.2)
# Define the project name
project(BinarySearchTree)
# Define source files
set(SRC driver.cpp bst.cpp)
# Build an executable
add_executable(BSTDriver ${SRC})

View File

@ -0,0 +1,342 @@
/*#############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved ##
## About: An example of a binary search tree implementation ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################
## bst.cpp
*/
#include "bst.h"
/********************************************************************************
* Constructors, Destructors, Operators
*********************************************************************************/
/** Copy Assignment Operator
* @brief Empty the calling object's root BinaryNode, and copy the rhs data
*
* @param rhs The BST to copy, beginning from its root BinaryNode
* @return const BinarySearchTree& The copied BinarySearchTree object
*/
const BinarySearchTree& BinarySearchTree::operator=(const BinarySearchTree& rhs)
{
// If the objects are already equal, do nothing
if (this == &rhs) return *this;
// Empty this->root
makeEmpty();
// Copy rhs to this->root
root = clone(rhs.root);
return *this;
}
/** Default Destructor
* @brief Destroy the Binary Search Tree:: Binary Search Tree object
*/
BinarySearchTree::~BinarySearchTree()
{
makeEmpty(root);
}
/********************************************************************************
* Public Member Functions
*********************************************************************************/
/** findMin
* @brief Find and return the minimum value of the calling BST object
* Calls to the private member findMin(BinaryNode* t)
*
* @return const int& The element of the BinaryNode that holds the lowest value in our tree
*/
const int & BinarySearchTree::findMin() const
{
return findMin(root)->element;
}
/** findMax
* @brief Find and return the maximum value of the calling BST object
* Calls to the private member findMax(BinaryNode* t)
*
* @return const int& The element of the BinaryNode that holds the highest value in our tree
*/
const int & BinarySearchTree::findMax() const
{
return findMax(root)->element;
}
/** contains
* @brief Determine whether or not a value exists within the calling BST object
* Calls to the private member contains(const int &x, BinaryNode* t)
*
* @param x The value to search for within our tree
* @return true If the value is found within any BinaryNode->element
* @return false If the value is not found within any BinaryNode->element
*/
bool BinarySearchTree::contains(const int &x) const
{
return contains(x, root);
}
/** isEmpty
* @brief Determine whether or not the calling BST object is empty
*
* @return true If this->root node points to an empty tree (NULL)
* @return false If this->root node points to a constructed BinaryNode
*/
bool BinarySearchTree::isEmpty() const
{
return root == NULL;
}
/** insert
* @brief Inserts a new value into the calling BST object
* Calls to the private member insert(const int &x, BinaryNode* t)
*
* @param x The new value to insert into our BinarySearchTree
*/
void BinarySearchTree::insert(const int & x)
{
insert(x, root);
}
/** remove
* @brief Remove a value from the calling BST object
* Calls to the private member remove(const int &x, BinaryNode* t)
*
* @param x The value to remove from our BST
*/
void BinarySearchTree::remove(const int &x)
{
remove(x, root);
}
/** makeEmpty
* @brief Delete the root BinaryNode and all of its children from the calling BST object
* Calls to the private member makeEmpty(BinaryNode* t)
*/
void BinarySearchTree::makeEmpty()
{
makeEmpty(root);
}
/** printInOrder
* @brief Output the element of each BinaryNode between their left and right subtrees
* Calls to the private member printInOrder(BinaryNode* t)
*/
void BinarySearchTree::printInOrder() const
{
printInOrder(root);
std::cout << std::endl;
}
/** printPostOrder
* @brief Output the element of each BinaryNode after their left and right subtrees
* Calls to the private member printPostOrder(BinaryNode* t)
*/
void BinarySearchTree::printPostOrder() const
{
printPostOrder(root);
std::cout << std::endl;
}
/** printPreOrder
* @brief Output the element of each BinaryNode before their left and right subtrees
* Calls to the private member printPreOrder(BinaryNode* t)
*/
void BinarySearchTree::printPreOrder() const
{
printPreOrder(root);
std::cout << std::endl;
}
/********************************************************************************
* Private Member Functions
*********************************************************************************/
/** clone
* @brief Clone a BST node and all its children
*
* @param t The node to begin cloning from
* @return BinarySearchTree::BinaryNode* The root node of the copied tree
*/
BinarySearchTree::BinaryNode * BinarySearchTree::clone(BinaryNode *t) const
{
// If there is nothing to copy
if (t == NULL) return NULL;
// Construct all child nodes through recursion, return root node
return new BinaryNode(t->element, clone(t->left), clone(t->right));
}
/** insert
* @brief Insert a value into the BST of the given BinaryNode
*
* @param x The value to be inserted
* @param t The BinaryNode to begin insertion
*/
void BinarySearchTree::insert(const int &x, BinarySearchTree::BinaryNode *&t) const
{
if (t == NULL)
t = new BinaryNode(x, NULL, NULL);
else if (x < t->element)
insert (x, t->left);
else if (x > t->element)
insert (x, t->right);
else
return;
}
/** remove
* @brief Removes a value from the BST of the given BinaryNode
*
* @param x The value to be removed
* @param t The BinaryNode to begin search and removal from
*/
void BinarySearchTree::remove(const int &x, BinarySearchTree::BinaryNode *&t) const
{
if (t == NULL)
return;
if (x < t->element)
remove(x, t->left);
else if (x > t->element)
remove(x, t->right);
else if (t->left != NULL && t->right != NULL) {
// If we found the node and there are two branches
t->element = findMin(t->right)->element;
std::cout << "Removing [" << t->element << "]...\n";
remove(t->element, t->right);
}
else {
// If we found the value and there is only one branch
BinaryNode *oldNode = t;
t = (t->left != NULL) ? t->left : t->right;
std::cout << "Removing [" << oldNode->element << "]...\n";
delete oldNode;
}
}
/** findMin
* @brief Find the minimum value within the BST of the given BinaryNode
*
* @param t The root BinaryNode to begin checking values
* @return BinarySearchTree::BinaryNode* The BinaryNode which contains the smallest value (returns NULL if BST is empty)
*/
BinarySearchTree::BinaryNode * BinarySearchTree::findMin(BinarySearchTree::BinaryNode *t) const
{
while (t != NULL)
t = t->left;
// If our tree is empty
if (t == NULL)
return NULL;
// If current node has no smaller children, it is min
if (t->left == NULL)
return t;
// Move down the left side of our tree and check again
return findMin(t->left);
}
/** findMax
* @brief Find the maximum value within the BST of the given BinaryNode
*
* @param t The root BinaryNode to begin checking values
* @return BinarySearchTree::BinaryNode* The BinaryNode which contains the largest value (returns NULL if BST is empty)
*/
BinarySearchTree::BinaryNode * BinarySearchTree::findMax(BinarySearchTree::BinaryNode *t) const
{
// If our tree is empty
if (t == NULL)
return NULL;
// If current node has no larger children, it is max
if (t->right == NULL)
return t;
// Move down the right side of our tree and check again
return findMax(t->right);
}
/** contains
* @brief Determines if the value exists within the given BinaryNode and its children
*
* @param x The value to search for within the BST
* @param t The root BinaryNode to begin the search
* @return true If the value is found within the root node or any of its children
* @return false If the value is not found within the root node or any of its children
*/
bool BinarySearchTree::contains(const int &x, BinarySearchTree::BinaryNode *t) const
{
if (t == NULL) // If tree is empty
return false;
else if (x < t->element) // If x is smaller than our current value
return contains(x, t->left);// Check left node
else if (x > t->element) // If x is larger than our current value
return contains(x, t->right); // Check right node
else
return true;
}
/** makeEmpty
* @brief Recursively delete the given root BinaryNode and all of its children
*
* @param t The root BinaryNode to delete, along with all child nodes
*/
void BinarySearchTree::makeEmpty(BinarySearchTree::BinaryNode * & t)
{
if (t != NULL) {
makeEmpty(t->left);
makeEmpty(t->right);
delete t;
}
t = NULL;
}
/** printInOrder
* @brief Output the element of the root nodes between printing their left and right subtrees
*
* @param t The root BinaryNode to begin the 'In Order' output
*/
void BinarySearchTree::printInOrder(BinaryNode *t) const
{
if(t != NULL) {
printInOrder(t->left);
std::cout << t->element << " ";
printInOrder(t->right);
}
}
/** printPostOrder
* @brief Output the value of the root nodes only after their subtrees
*
* @param t The root BinaryNode to begin the 'Post Order' output
*/
void BinarySearchTree::printPostOrder(BinaryNode *t) const
{
if (t != NULL) {
printPostOrder(t->left);
printPostOrder(t->right);
std::cout << t->element << " ";
}
}
/** printPreOrder
* @brief Output the value of the noot nodes before their subtrees
*
* @param t The root BinaryNode to begin the 'Pre Order' output
*/
void BinarySearchTree::printPreOrder(BinaryNode *t) const
{
if (t != NULL) {
std::cout << t->element << " ";
printPreOrder(t->left);
printPreOrder(t->right);
}
}

View File

@ -0,0 +1,56 @@
/*#############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved ##
## About: An example of a binary search tree implementation ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################
## bst.h
*/
#ifndef BST_H
#define BST_H
#include <iostream>
// TODO: Add balance() method to balance overweight branches
class BinarySearchTree {
public:
BinarySearchTree() : root(NULL) {};
BinarySearchTree(const BinarySearchTree &rhs) : root(rhs.clone(rhs.root)) {};
const BinarySearchTree& operator=(const BinarySearchTree& rhs);
~BinarySearchTree();
const int & findMin() const;
const int & findMax() const;
bool contains(const int &x) const;
bool isEmpty() const;
void insert(const int &x);
void remove(const int &x);
void makeEmpty();
void printInOrder() const;
void printPostOrder() const;
void printPreOrder() const;
private:
struct BinaryNode{
int element;
BinaryNode *left;
BinaryNode *right;
BinaryNode(const int &el, BinaryNode *lt, BinaryNode *rt)
:element(el), left(lt), right(rt) {};
};
BinaryNode *root;
BinaryNode * clone(BinaryNode *t) const;
void insert(const int &x, BinaryNode *&t) const;
void remove(const int &x, BinaryNode *&t) const;
BinaryNode * findMin(BinaryNode *t) const;
BinaryNode * findMax(BinaryNode *t) const;
bool contains(const int &x, BinaryNode *t) const;
void makeEmpty(BinaryNode * & t);
void printInOrder(BinaryNode *t) const;
void printPostOrder(BinaryNode *t) const;
void printPreOrder(BinaryNode *t) const;
};
#endif //BST_H

View File

@ -0,0 +1,91 @@
/*#############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved ##
## About: A driver program to test a binary search tree implementation ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################
## driver.cpp
*/
#include "bst.h"
#include <iostream>
enum OPS {
EXIT, INSERT, REMOVE, CONTAINS, INFIX, PREFIX, POSTFIX, EMPTY, MIN, MAX
};
int main()
{
std::cout << "Driver: \n";
BinarySearchTree testList;
bool exit = false;
int choice = -1;
int val;
while (!exit)
{
std::cout << "##### Binary Search Tree Menu #####\n\t0. Exit"
"\n\t1. Insert\n\t2. Remove\n\t3. Contains\n\t4. Infix\n\t5. Prefix"
<< "\n\t6. Postfix\n\t7. Empty\n\t8. Min\n\t9. Max\n";
std::cin >> choice;
std::cin.clear();
switch (choice) {
case EXIT:
exit = true;
break;
case INSERT:
std::cout << "Enter a value to insert to our tree: ";
std::cin >> val;
std::cin.clear();
testList.insert(val);
break;
case REMOVE:
std::cout << "Enter a value to remove from our tree: ";
std::cin >> val;
std::cin.clear();
testList.remove(val);
break;
case CONTAINS:
std::cout << "Enter a value to search for within our tree: ";
std::cin >> val;
std::cin.clear();
if (testList.contains(val))
std::cout << val << " exists within our tree\n";
else std::cout << val << " does not exist within our tree\n";
break;
case INFIX:
testList.printInOrder();
break;
case PREFIX:
testList.printPreOrder();
break;
case POSTFIX:
testList.printPostOrder();
break;
case EMPTY:
testList.makeEmpty();
break;
case MIN:
std::cout << "Min value within our tree: " << testList.findMin();
break;
case MAX:
std::cout << "Max value within our tree: " << testList.findMax();
break;
default:
std::cout << "Invalid entry...\n";
break;
}
}
}

View File

@ -0,0 +1,18 @@
###############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved ##
## About: An example of a doubly linked list implementation ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################
## CMakeLists.txt
#
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
# Define the project name
project(DoubleList)
# Define source files
set(SRC driver.cpp doublelist.cpp)
# Build an executable
add_executable(DoubleListDriver ${SRC})

View File

@ -0,0 +1,23 @@
CXX=g++
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
###############################################################################
# Clean
###############################################################################
clean:
rm -f *.o driver

View File

@ -0,0 +1,339 @@
/*#############################################################################
## 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
*/
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
*/
DoubleList DoubleList::operator=(DoubleList rhs)
{
if (this == &rhs) return *this;
std::swap(head, rhs.head);
return *this;
}
/** destructor
* @brief Destroy the DoubleList::DoubleList object
*/
DoubleList::~DoubleList()
{
makeEmpty();
}
/******************************************************************************
* Public Member Functions
*****************************************************************************/
/** insert
* @brief Inserts a value to the head of our linked list
*
* @param x The value to be inserted
*/
bool DoubleList::insert(int 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
*/
bool DoubleList::insert(int val, int 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
*/
bool DoubleList::remove(int 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
*/
bool DoubleList::replace(int val, int 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
*/
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
*/
bool DoubleList::isEmpty() const
{
return head == NULL;
}
/** peek
* @brief returns the value at the DoubleList::head
*
* @return int The value held at the Node pointed to by DoubleList::head
*/
int 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 : INT32_MIN;
}
/** print
* @brief Output the data held by the DoubleList object
* Calls to the private print()
*/
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
*/
bool DoubleList::find(int 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
*/
bool DoubleList::insert(int 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
*/
bool DoubleList::insert(int val, int 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);
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
*/
bool DoubleList::remove(int 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
*/
bool DoubleList::replace(int val, int 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
* @return DoubleList::Node* A pointer to the Node containing the search value
*/
DoubleList::Node* DoubleList::find(int 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
*/
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;
}

View File

@ -0,0 +1,48 @@
/*#############################################################################
## 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.h
*/
#ifndef DOUBLELIST_H
#define DOUBLELIST_H
#include <iostream>
class DoubleList {
public:
DoubleList() : head(NULL) {};
DoubleList(const DoubleList& rhs);
DoubleList operator=(DoubleList rhs);
~DoubleList();
bool insert(int val);
bool insert(int val, int key);
bool remove(int val);
bool replace(int val, int key);
void makeEmpty();
bool isEmpty() const;
int peek() const;
void print() const;
bool find(int val) const;
private:
struct Node {
int data;
Node *next, *prev;
Node(): data(), next(NULL), prev(NULL) {};
Node(int val): data(val), next(NULL), prev(NULL) {};
};
Node *head;
bool insert(int val, Node *&head);
bool insert(int val, int key, Node *&head);
bool remove(int val, Node *&head);
bool replace(int val, int key, Node *&head);
Node* find(int val, Node *start) const;
void print(Node *start) const;
};
#endif

View File

@ -0,0 +1,106 @@
/*#############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved ##
## About: A driver program to test a doubly linked list ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################
## driver.cpp
*/
#include "doublelist.h"
#include <iostream>
enum OPS {
EXIT, INSERT, INSERTAT, EMPTY, PEEK, PRINT, FIND, REMOVE, REPLACE
};
int main()
{
std::cout << "Driver: \n";
DoubleList testList;
bool exit = false;
int choice = -1;
int val, key;
while (!exit)
{
std::cout << "##### Doubly Linked List Menu #####\n\t0. Exit"
<< "\n\t1. Insert\n\t2. Insert at\n\t3. Empty list\n\t4. Peek top of list"
<< "\n\t5. Print list\n\t6. Find\n\t7. Remove\n\t8. Replace\n";
std::cin >> choice;
std::cin.clear();
switch (choice) {
case EXIT:
exit = true;
break;
case INSERT:
std::cout << "Enter a value to add to our list: ";
std::cin >> val;
std::cin.clear();
testList.insert(val);
break;
case INSERTAT:
std::cout << "Enter a new value to add to our list: ";
std::cin >> val;
std::cin.clear();
std::cout << "Enter an existing value to insert at within our list: ";
std::cin >> key;
std::cin.clear();
if (testList.insert(val, key)) {
std::cout << "List after inserting ["
<< val << "] at [" << key << "]: \n";
testList.print();
}
break;
case EMPTY:
testList.makeEmpty();
break;
case PEEK:
testList.peek();
break;
case PRINT:
testList.print();
break;
case FIND:
std::cout << "Enter an existing value to search for within our list: ";
std::cin >> val;
std::cin.clear();
testList.find(val);
break;
case REMOVE:
std::cout << "Enter an existing value to remove from our list: ";
std::cin >> val;
std::cin.clear();
testList.remove(val);
break;
case REPLACE:
std::cout << "Enter a new value to add to our list: ";
std::cin >> val;
std::cin.clear();
std::cout << "Enter an existing value to replace within our list: ";
std::cin >> key;
std::cin.clear();
if (testList.replace(val, key)) {
std::cout << "List after replacing ["
<< key << "] by [" << val << "]: \n";
testList.print();
}
break;
default:
std::cout << "Invalid entry...\n";
break;
}
}
}

View File

@ -0,0 +1,18 @@
###############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved ##
## About: An example of a queue implementation ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################
## CMakeLists.txt
#
cmake_minimum_required(VERSION 3.2)
# Define the project name
project(Queue)
# Define source files
set(SRC driver.cpp queuelist.cpp)
# Build an executable
add_executable(QueueDriver ${SRC})

View File

@ -0,0 +1,23 @@
CXX=g++
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
###############################################################################
# Clean
###############################################################################
clean:
rm -f *.o driver

View File

@ -0,0 +1,67 @@
/*#############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved ##
## About: A driver program to test a queue implementation using linked lists ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################
## driver.cpp
*/
#include "queuelist.h"
#include <iostream>
enum OPS {
EXIT, ENQUEUE, DEQUEUE, NEXT, PRINT, EMPTY
};
int main()
{
std::cout << "Driver: \n";
QueueList testList;
bool exit = false;
int choice = -1;
int val;
while (!exit)
{
std::cout << "##### Queues Using Linked Lists Menu #####\n\t0. Exit"
<< "\n\t1. Enqueue\n\t2. Dequeue\n\t3. Next\n\t4. Print"
<< "\n\t5. Empty\n\t";
std::cin >> choice;
std::cin.clear();
switch (choice) {
case EXIT:
exit = true;
break;
case ENQUEUE:
std::cout << "Enter a value to add to the end of our queue: ";
std::cin >> val;
std::cin.clear();
testList.enqueue(val);
break;
case DEQUEUE:
testList.dequeue();
break;
case NEXT:
testList.next();
break;
case PRINT:
testList.print();
break;
case EMPTY:
testList.makeEmpty();
break;
default:
std::cout << "Invalid entry...\n";
break;
}
}
}

View File

@ -0,0 +1,256 @@
/*#############################################################################
## 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
*/
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
*/
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
*/
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
*/
bool QueueList::enqueue(int 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 int The value held at the Node pointed to by QueueList::head
*/
int 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 : INT32_MIN;
}
/** next
* @brief returns the value at the QueueList::head
*
* @return int The value held at the Node pointed to by QueueList::head
*/
int 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 : INT32_MIN;
}
/** isEmpty
* @brief Determine if the QueueList is empty
*
* @return true If the QueueList::head is NULL
* @return false If the QueueList::head contains data
*/
bool QueueList::isEmpty() const
{
return head == NULL;
}
/** print
* @brief Output the data held by the QueueList object
* Calls to the private print()
*/
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
*/
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
*/
bool QueueList::enqueue(int 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 int The value held at the node removed
*/
int 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
int 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
*/
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
*
*/
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;
}
}
}

View File

@ -0,0 +1,44 @@
/*#############################################################################
## 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.h
*/
#ifndef QUEUELIST_H
#define QUEUELIST_H
#include <iostream>
class QueueList {
public:
QueueList() : head(NULL), tail(NULL){};
QueueList(const QueueList& rhs);
QueueList operator=(QueueList rhs);
~QueueList();
bool enqueue(int val);
int dequeue();
int next() const;
bool isEmpty() const;
void print() const;
void makeEmpty();
private:
struct Node {
int data;
Node *next;
Node(): data(), next(NULL) {};
Node(int val): data(val), next(NULL) {};
};
Node *head, *tail;
bool enqueue(int val, Node *&head);
int dequeue(Node *&tail);
void print(Node *start) const;
void makeEmpty(Node *&head);
};
#endif

View File

@ -0,0 +1,18 @@
###############################################################################
## 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 ##
##############################################################################
## CMakeLists.txt
#
cmake_minimum_required(VERSION 3.2)
# Define the project name
project(Stack)
# Define source files
set(SRC driver.cpp stacklist.cpp)
# Build an executable
add_executable(StackDriver ${SRC})

View File

@ -0,0 +1,23 @@
CXX=g++
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
###############################################################################
# Clean
###############################################################################
clean:
rm -f *.o driver

View File

@ -0,0 +1,67 @@
/*#############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved ##
## About: A driver program to test a stack implementation using linked lists ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################
## driver.cpp
*/
#include "stacklist.h"
#include <iostream>
enum OPS {
EXIT, PUSH, POP, TOP, PRINT, EMPTY
};
int main()
{
std::cout << "Driver: \n";
StackList testList;
bool exit = false;
int choice = -1;
int val;
while (!exit)
{
std::cout << "##### Stacks Using Linked Lists Menu #####\n\t0. Exit"
<< "\n\t1. Push\n\t2. Pop\n\t3. Top\n\t4. Print"
<< "\n\t5. Empty\n\t";
std::cin >> choice;
std::cin.clear();
switch (choice) {
case EXIT:
exit = true;
break;
case PUSH:
std::cout << "Enter a value to push to our stack: ";
std::cin >> val;
std::cin.clear();
testList.push(val);
break;
case POP:
testList.pop();
break;
case TOP:
testList.top();
break;
case PRINT:
testList.print();
break;
case EMPTY:
testList.makeEmpty();
break;
default:
std::cout << "Invalid entry...\n";
break;
}
}
}

View File

@ -0,0 +1,238 @@
/*#############################################################################
## 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
*/
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
*/
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
*/
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
*/
bool StackList::push(int 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 int The value held at the Node pointed to by StackList::head
*/
int 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 : INT32_MIN;
}
/** top
* @brief returns the value at the StackList::head
*
* @return int The value held at the Node pointed to by StackList::head
*/
int 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 : INT32_MIN;
}
/** makeEmpty
* @brief Empty this StackList object, deleting all associated Nodes
*/
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
*/
bool StackList::isEmpty() const
{
return head == NULL;
}
/** print
* @brief Output the data held by the StackList object
* Calls to the private print()
*/
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
*/
bool StackList::push(int 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 The last known value held at the head node before removal
*/
int StackList::pop(Node *&head)
{
// We already know the stack is not empty from public pop()
Node *temp = head;
int 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
*/
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
*
*/
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;
}
}
}

View File

@ -0,0 +1,44 @@
/*#############################################################################
## 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.h
*/
#ifndef STACKLIST_H
#define STACKLIST_H
#include <iostream>
class StackList {
public:
StackList() : head(NULL) {};
StackList(const StackList& rhs);
StackList operator=(StackList rhs);
~StackList();
bool push(int val);
int pop();
int top() const;
bool isEmpty() const;
void print() const;
void makeEmpty();
private:
struct Node {
int data;
Node *next;
Node(): data(), next(NULL) {};
Node(int val): data(val), next(NULL) {};
};
Node *head;
bool push(int val, Node *&head);
int pop(Node *&head);
void print(Node *start) const;
void makeEmpty(Node *&head);
};
#endif

View File

@ -0,0 +1,18 @@
###############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved ##
## About: A basic CMakeLists configuration to test Vector implementation ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################
## vector.cpp
#
cmake_minimum_required(VERSION 3.2)
# Define the project name
project(VectorDriver)
# Define source files
set(SRC driver.cpp vector.cpp)
# Build an executable
add_executable(VectorDriver ${SRC})

View File

@ -0,0 +1,23 @@
CXX=g++
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
###############################################################################
# Clean
###############################################################################
clean:
rm -f *.o driver

View File

@ -0,0 +1,111 @@
/*#############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved ##
## About: A driver program to test a vector implementation ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################
## driver.cpp
*/
#include "vector.h"
#include <iostream>
enum OPS {
EXIT, PUSH, POP, TOP, PRINT, EMPTY, CONSTRUCT, COPY, ASSIGN, DESTRUCT
};
int main()
{
std::cout << "Driver: \n";
Vector<std::string> testlist;
bool exit = false;
int choice = -1;
<typename T> T val;
while (!exit)
{
std::cout << "##### vectors menu #####\n\t0. exit"
<< "\n\t1. push\n\t2. pop\n\t3. peek\n\t4. print\n\t5. empty"
<< "\n\t6. construct\n\t7. copy\n\t8. assign\n\t9. destruct\n\t";
std::cin >> choice;
std::cin.clear();
switch (choice) {
case EXIT:
exit = true;
break;
case PUSH:
std::cout << "enter a value to push to our vector: ";
std::cin >> val;
std::cin.clear();
testlist.push(val);
break;
case POP:
testList.pop();
break;
case TOP:
testList.peek();
break;
case PRINT:
testList.print();
break;
case EMPTY:
testList.makeEmpty();
break;
// If this test is successful, we build a default empty Vector object
// Will 'have nothing to print' because a default Vector contains no values
case CONSTRUCT:
{
Vector<std::string> constrTest;
std::cout << "##### Constructor Test #####\n";
constrTest.print();
std::cout << "Deleting local constrTest Vector...\n";
break;
}
// If this is successful, we build a new Vector based on the existing Vector
// The new Vector output here should be identical to this session's Vector
case COPY:
{
Vector<std::string> copyTest(testList);
std::cout << "##### Copy Constructor Test #####\n";
copyTest.print();
std::cout << "Deleting local copyTest Vector...\n";
break;
}
// Test assignment operator, setting new Vector object equal to the existing
case ASSIGN:
{
Vector<std::string> assignTest;
assignTest = testList;
std::cout << "##### Assignment Test #####\n";
assignTest.print();
std::cout << "Deleting local assignTest Vector...\n";
break;
}
case DESTRUCT:
{
Vector<std::string> destrTest(testList);
std::cout << "Current destrTest Vector contents...\n";
destrTest.print();
std::cout << "Deleting local destrTest Vector...\n";
destrTest.~Vector(); // Implicitly called at the end of this scope {}
destrTest.print();
break;
}
default:
std::cout << "Invalid entry...\n";
break;
}
}
}

View File

@ -0,0 +1,319 @@
/*#############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved ##
## About: An example of a vector implementation ##
## ##
## 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<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];
for (int i = 0; i <= rhs.getSize(); 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<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 int 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 int The value held at the current data[index] of the vector
*/
template<typename T>
T Vector<T>::peek() const
{
T val = NULL;
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>
T 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>
T 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>
T 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 int The value held at the index given
*/
template<typename T>
T Vector<T>::getValue(T 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 int 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 int 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;
}
template class Vector<int>;
template class Vector<std::string>;

View File

@ -0,0 +1,48 @@
/*#############################################################################
## Author: Shaun Reed ##
## Legal: All Content (c) 2020 Shaun Reed, all rights reserved ##
## About: An example of a vector implementation ##
## ##
## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ##
##############################################################################
## vector.h
*/
#ifndef VECTOR_H
#define VECTOR_H
#include <iostream>
#include <string>
template <typename T>
class Vector {
public:
Vector() : maxSize(0), curIndex(-1), data(NULL) {};
Vector(const Vector& rhs);
Vector<T> operator=(Vector<T> rhs);
~Vector();
bool push(T val);
T pop();
void makeEmpty();
T peek() const;
bool isEmpty() const;
bool isFull() const;
void print() const;
T getMax() const;
T getSize() const;
T getIndex() const;
T getValue(T index) const;
private:
T maxSize;
T curIndex;
T *data;
bool push(T val, T *&data);
T pop(T *&data);
void makeEmpty(T *&data);
T peek(T *data) const;
void print(T *data) const;
};
#endif