From a864342974b1118e92811e2f0982e356879d4799 Mon Sep 17 00:00:00 2001 From: Shaun Reed Date: Sat, 4 Jul 2020 20:58:14 -0400 Subject: [PATCH] Add RD of Binary Search Tree implementation + Update .gitignore to exclude .idea configs --- .gitignore | 1 + .../binarysearchtree/CMakeLists.txt | 17 + cpp/datastructs/binarysearchtree/bst.cpp | 339 ++++++++++++++++++ cpp/datastructs/binarysearchtree/bst.h | 56 +++ cpp/datastructs/binarysearchtree/driver.cpp | 91 +++++ 5 files changed, 504 insertions(+) create mode 100644 cpp/datastructs/binarysearchtree/CMakeLists.txt create mode 100644 cpp/datastructs/binarysearchtree/bst.cpp create mode 100644 cpp/datastructs/binarysearchtree/bst.h create mode 100644 cpp/datastructs/binarysearchtree/driver.cpp diff --git a/.gitignore b/.gitignore index 5730a57..14db6e9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ build/ **/.vscode +**/.idea/** **/driver **/*.o **/cmake-build-debug/** diff --git a/cpp/datastructs/binarysearchtree/CMakeLists.txt b/cpp/datastructs/binarysearchtree/CMakeLists.txt new file mode 100644 index 0000000..fc1f748 --- /dev/null +++ b/cpp/datastructs/binarysearchtree/CMakeLists.txt @@ -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 ## +############################################################################## +## vector.cpp +# + +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}) diff --git a/cpp/datastructs/binarysearchtree/bst.cpp b/cpp/datastructs/binarysearchtree/bst.cpp new file mode 100644 index 0000000..d1b651a --- /dev/null +++ b/cpp/datastructs/binarysearchtree/bst.cpp @@ -0,0 +1,339 @@ +/*############################################################################# +## 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 +*********************************************************************************/ + +/** Default Destructor + * @brief Destroy the Binary Search Tree:: Binary Search Tree object + */ +BinarySearchTree::~BinarySearchTree() +{ + makeEmpty(root); +} + +/** 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; +} + + +/******************************************************************************** +* 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 wheter 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); +} + +/** 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); +} + +/** 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); +} + + +/******************************************************************************** +* 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 beign 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 Te 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 beign 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); + } +} \ No newline at end of file diff --git a/cpp/datastructs/binarysearchtree/bst.h b/cpp/datastructs/binarysearchtree/bst.h new file mode 100644 index 0000000..8d8e880 --- /dev/null +++ b/cpp/datastructs/binarysearchtree/bst.h @@ -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 + +// 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(); + 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 diff --git a/cpp/datastructs/binarysearchtree/driver.cpp b/cpp/datastructs/binarysearchtree/driver.cpp new file mode 100644 index 0000000..f1c85f0 --- /dev/null +++ b/cpp/datastructs/binarysearchtree/driver.cpp @@ -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 + +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; + } + } +} +