From a6320230691e52c2d4e1fd2250232a28552a522e Mon Sep 17 00:00:00 2001 From: TriantaTV Date: Mon, 6 Mar 2023 03:13:14 -0600 Subject: [PATCH] BST seems to fully work, moving on to RBT --- README.md | 34 +++-- include/sort_controller.hpp | 5 +- include/trees.hpp | 33 +++-- src/sort_controller.cpp | 45 ++++++ src/trees.cpp | 267 +++++++++++++++++------------------- 5 files changed, 214 insertions(+), 170 deletions(-) diff --git a/README.md b/README.md index 1a3a027..b673838 100644 --- a/README.md +++ b/README.md @@ -9,34 +9,48 @@ Run `make` to compile the project. Output files get placed into test/SORTED # Running -Run `bin/main.out` with chosen arguments to run program +Run the program with chosen arguments + +`bin/main.out [-f filename] [-s sort-type] [-l word]` # Commands -## bin/main.out [-a | -f filename | -d] -Ex: `bin/main.out -f test/PERM/perm15K.txt -s merge` + +## bin/main.out [-a | -f filename | -d | ] +Ex: `bin/main.out -f test/PERM/perm15K.txt -s bst -l apple` # Arguments + ## File selection -> -a OR --all -- Runs through all the original files (perm15K.txt - perm150K.txt) +> -a | --all + - Runs through all the original files (perm15K.txt - perm150K.txt) - *EX: bin/main.out -a* -> -f path/to/file.txt OR --filename path/to/file.txt -- Runs a specific file to sort +> -f path/to/file.txt | --filename path/to/file.txt + - Runs a specific file to sort - *EX: bin/main.out -f perm15K.txt* -> -d OR --default (**default**) -- Runs sort only on the default test file (perm15K.txt) +> -d | --default + - Runs sort only on the default test file (perm15K.txt) - *EX: bin/main.out -d* + ## Sorting type selection > -s | --sort-type - Selects a sort type - Options: + - binary search tree [***default***] + - *EX: bin/main.out -s bst* + - red-black tree + - *EX: bin/main.out -s rbt* - insertion - *EX: bin/main.out -s insertion* - merge - *EX: bin/main.out -s merge* - heap - *EX: bin/main.out -s heap* - - all (**default**) + - all (only runs insertion, merge, and heap sort) - *EX: bin/main.out -s all* +## Locating a word +> -l | --locate + - Locates a word and prints the output [***default***] + - Must be used with BST or RBT sort type + - *EX: bin/main.out -l apple* # Notes diff --git a/include/sort_controller.hpp b/include/sort_controller.hpp index 2bce6ad..c8ebba2 100644 --- a/include/sort_controller.hpp +++ b/include/sort_controller.hpp @@ -5,7 +5,7 @@ #include #include -enum SortType {INSERTION = 0, MERGE, HEAP}; +enum SortType {INSERTION = 0, MERGE, HEAP, BST, RBT, LAST}; class SortController { @@ -19,11 +19,12 @@ protected: private: std::string filename; SortType currentType; + std::string wordToLocate; std::chrono::duration sortTime; std::vector newWordList; std::vector originalWordList; int lineCount; - bool defaultFile, defaultOnly, fileGiven, allLists, sortGiven; + bool defaultFile, defaultOnly, fileGiven, allLists, sortGiven, locate; void Benchmarking(void); void BenchmarkingAll(void); void OutputResult(void); diff --git a/include/trees.hpp b/include/trees.hpp index 07b6187..fe06f57 100644 --- a/include/trees.hpp +++ b/include/trees.hpp @@ -13,20 +13,17 @@ namespace tree_implementation { std::string key; std::string color; - std::unique_ptr leftChild; - std::unique_ptr rightChild; - std::unique_ptr parent; + std::shared_ptr leftChild; + std::shared_ptr rightChild; + std::shared_ptr parent; TreeNode(std::string word); - ~TreeNode(void); - TreeNode(const TreeNode& rhs); - TreeNode& operator=(const TreeNode& rhs); }; // General list for Tree class TreeList { public: - std::unique_ptr head; + std::shared_ptr head; TreeList(void); void InsertAtStart(std::string word); void InsertAtEnd(std::string word); @@ -45,18 +42,18 @@ namespace tree_implementation public: TreeList tree; TreeInterface(void); - TreeNode* Search(std::string wordToFind); - bool IsSearchSuccessful(std::unique_ptr foundNode); - void InOrderTreeTraversal(std::unique_ptr viewedNode); + std::shared_ptr Search(std::string wordToFind); + bool IsSearchSuccessful(std::shared_ptr foundNode, std::string key); + void InOrderTreeTraversal(std::shared_ptr viewedNode); void PrintParentKey(std::string key); void PrintLeftChild(std::string key); void PrintRightChild(std::string key); protected: - virtual void Insert(std::unique_ptr z); + virtual void Insert(std::shared_ptr z); + virtual void InsertWordList(std::vector* newWordList) = 0; virtual void PrintPathToRoot(std::string key) = 0; private: - TreeNode* Insert(std::unique_ptr root, std::unique_ptr newNode); - TreeNode* Search(std::unique_ptr* viewedNode, std::string wordToFind); + std::shared_ptr Search(std::shared_ptr viewedNode, std::string wordToFind); }; // Binary Search Tree operations @@ -64,6 +61,7 @@ namespace tree_implementation { public: void Insert(std::string keyToInsert); + void InsertWordList(std::vector* newWordList); void PrintPathToRoot(std::string key); protected: ; @@ -76,6 +74,7 @@ namespace tree_implementation { public: void Insert(std::string keyToInsert); + void InsertWordList(std::vector* newWordList); void PrintPathToRoot(std::string key); void PrintColor(std::string key); void PrintParentColor(std::string key); @@ -83,10 +82,10 @@ namespace tree_implementation protected: ; private: - void InsertFixup(std::unique_ptr z); - std::unique_ptr GetUncleNode(std::unique_ptr startNode); - void LeftRotate(std::unique_ptr x); - void RightRotate(std::unique_ptr x); + void InsertFixup(std::shared_ptr z); + std::shared_ptr GetUncleNode(std::shared_ptr startNode); + void LeftRotate(std::shared_ptr x); + void RightRotate(std::shared_ptr x); }; } diff --git a/src/sort_controller.cpp b/src/sort_controller.cpp index 65e5b34..1182a3f 100644 --- a/src/sort_controller.cpp +++ b/src/sort_controller.cpp @@ -1,6 +1,7 @@ #include "sort_controller.hpp" #include "basic_sorts.hpp" #include "trees.hpp" +#include #include #include #include @@ -37,6 +38,12 @@ void SortController::CheckArguments(int argc, char* arguments[]) defaultOnly = 0; fileGiven = 1; } + if ((tempStr == "-l") || (tempStr == "--locate")) + { + wordToLocate = arguments[i + 1]; + std::transform(wordToLocate.begin(), wordToLocate.end(), wordToLocate.begin(), ::toupper); + locate = 1; + } if ((tempStr == "-d") || (tempStr == "--default")) { filename = "test/PERM/perm15K.txt"; @@ -46,6 +53,10 @@ void SortController::CheckArguments(int argc, char* arguments[]) { sortGiven = 1; tempStr = arguments[i + 1]; + if (tempStr == "bst") + currentType = BST; + if (tempStr == "rbt") + currentType = RBT; if (tempStr == "insertion") currentType = INSERTION; if (tempStr == "merge") @@ -129,6 +140,32 @@ void SortController::Benchmarking(void) sortTime = end - start; OutputResult(); } + if (currentType == BST) + { + newWordList = originalWordList; + tree_implementation::BinarySearchTree newTree; + auto start = std::chrono::system_clock::now(); + newTree.InsertWordList(&newWordList); + auto end = std::chrono::system_clock::now(); + sortTime = end - start; + OutputResult(); + start = std::chrono::system_clock::now(); + newTree.Search(wordToLocate); + end = std::chrono::system_clock::now(); + sortTime = end - start; + EchoSortTime("BST"); + newTree.PrintPathToRoot(wordToLocate); + } + if (currentType == RBT) + { + newWordList = originalWordList; + tree_implementation::RedBlackTree newTree; + auto start = std::chrono::system_clock::now(); + newTree.InsertWordList(&newWordList); + auto end = std::chrono::system_clock::now(); + sortTime = end - start; + OutputResult(); + } } // Sorts all default files if allLists is set @@ -167,6 +204,14 @@ void SortController::OutputResult(void) EchoSortTime("HS"); WriteOutputToFile("HS"); break; + case BST: + EchoSortTime("BST"); + WriteOutputToFile("BST"); + break; + case RBT: + EchoSortTime("RBT"); + WriteOutputToFile("RBT"); + break; default: break; } diff --git a/src/trees.cpp b/src/trees.cpp index e711f9f..9b6209f 100644 --- a/src/trees.cpp +++ b/src/trees.cpp @@ -17,26 +17,6 @@ namespace tree_implementation return; } - TreeNode::~TreeNode(void) - { - return; - } - - TreeNode::TreeNode(const TreeNode& rhs) - { - key = rhs.key; - color = rhs.color; - return; - } - - TreeNode& TreeNode::operator=(const TreeNode& rhs) - { - key = rhs.key; - color = rhs.color; - return *this; - } - - TreeList::TreeList(void) { head = nullptr; @@ -49,141 +29,146 @@ namespace tree_implementation } // Inserts a node into a BST - void TreeInterface::Insert(std::unique_ptr z) + void TreeInterface::Insert(std::shared_ptr z) { - // std::unique_ptr y(nullptr); - // std::unique_ptr x(tree.head.release()); - // while (x) - // { - // y = x.release(); - // if (z->key < x->key) - // x = x->leftChild.release(); - // else - // x = x->rightChild.release(); - // } - // z->parent = y.release(); - // if (!y) - // tree.head = z.release(); - // else if (z->key < y->key) - // y->leftChild = z.release(); - // else - // y->rightChild = z.release(); + std::shared_ptr y = nullptr; + std::shared_ptr x = tree.head; + while (x) + { + y = x; + if (z.get()->key < x.get()->key) + x = x.get()->leftChild; + else + x = x.get()->rightChild; + } + z.get()->parent = y; + if (!y) + tree.head = z; + else if (z.get()->key < y.get()->key) + y->leftChild = z; + else + y->rightChild = z; return; } // Searches for the given word in a tree - TreeNode* TreeInterface::Search(std::string wordToFind) + std::shared_ptr TreeInterface::Search(std::string wordToFind) { - return Search(&tree.head, wordToFind); + return Search(tree.head, wordToFind); } - bool TreeInterface::IsSearchSuccessful(std::unique_ptr foundNode) + bool TreeInterface::IsSearchSuccessful(std::shared_ptr foundNode, std::string key) { - // if (foundNode) - // return true; - // std::cout << "No node found with key '" << foundNode->key << "'\n"; + if (foundNode) + return true; + std::cout << "No node found with key " << key << std::endl; return false; } // Prints tree while traversing it - void TreeInterface::InOrderTreeTraversal(std::unique_ptr viewedNode) + void TreeInterface::InOrderTreeTraversal(std::shared_ptr viewedNode) { - // if (viewedNode) - // InOrderTreeTraversal(viewedNode->leftChild); - // std::cout << viewedNode.key << '\n'; - // InOrderTreeTraversal(viewedNode->rightChild); + if (viewedNode) + InOrderTreeTraversal(viewedNode->leftChild); + std::cout << viewedNode.get()->key << '\n'; + InOrderTreeTraversal(viewedNode->rightChild); return; } // Prints the given word's parent's word if found void TreeInterface::PrintParentKey(std::string key) { - // std::unique_ptr foundNode = std::move(Search(key)); - // if (!IsSearchSuccessful(foundNode)) return; - // std::cout << "The parent's word is " << foundNode->parent->key << '\n'; + std::shared_ptr foundNode = Search(key); + if (!IsSearchSuccessful(foundNode, key)) return; + std::cout << "The parent's word is " << foundNode->parent->key << '\n'; return; } // Prints the given word's left child's word if found void TreeInterface::PrintLeftChild(std::string key) { - // std::unique_ptr foundNode = std::move(Search(key)); - // if (!IsSearchSuccessful(foundNode)) return; - // std::cout << "The left child's word is " << foundNode->leftChild->key << '\n'; + std::shared_ptr foundNode = Search(key); + if (!IsSearchSuccessful(foundNode, key)) return; + std::cout << "The left child's word is " << foundNode->leftChild->key << '\n'; return; } // Prints the given word's right child's word if found void TreeInterface::PrintRightChild(std::string key) { - // std::unique_ptr foundNode = std::move(Search(key)); - // if (!IsSearchSuccessful(foundNode)) return; - // std::cout << "The right child's word is " << foundNode->rightChild->key << '\n'; + std::shared_ptr foundNode = Search(key); + if (!IsSearchSuccessful(foundNode, key)) return; + std::cout << "The right child's word is " << foundNode->rightChild->key << '\n'; return; } - - // Recursive insertion function for Insert() - TreeNode* TreeInterface::Insert(std::unique_ptr root, std::unique_ptr newNode) - { - // if (!tree.head) - // return newNode.release(); - // if (newNode->key < root->key) - // { - // root->leftChild = Insert(root->leftChild, newNode); - // root->leftChild->parent = root.release(); - // } else if (newNode->key > root->key) { - // root->rightChild = Insert(root->rightChild, newNode); - // root->rightChild->parent = root.release(); - // } - // return root.release(); - } // Recursive search function for Search() - TreeNode* TreeInterface::Search(std::unique_ptr* viewedNode, std::string wordToFind) + std::shared_ptr TreeInterface::Search(std::shared_ptr viewedNode, std::string wordToFind) { - // if ((!viewedNode) || (wordToFind == viewedNode->key)) - // return viewedNode.release(); - // if (wordToFind < viewedNode->key) - // return Search(viewedNode->leftChild, wordToFind); - // return Search(viewedNode->rightChild, wordToFind); + if ((!viewedNode) || (wordToFind == viewedNode.get()->key)) + return viewedNode; + if (wordToFind < viewedNode.get()->key) + return Search(viewedNode->leftChild, wordToFind); + return Search(viewedNode->rightChild, wordToFind); } // Insert a node into a BST void BinarySearchTree::Insert(std::string keyToInsert) { - // std::unique_ptr newNode = new TreeNode(keyToInsert); - // TreeInterface::Insert(newNode); + std::shared_ptr newNode = std::make_shared (keyToInsert); + TreeInterface::Insert(newNode); return; } + // Insert the entire vector word list into tree + void BinarySearchTree::InsertWordList(std::vector* newWordList) + { + for (int i = 0; i < newWordList->size(); i++) + { + Insert(newWordList->at(i)); + } + } + // Prints the path to root in a BST - // TODO: Implement printing path to root for BST void BinarySearchTree::PrintPathToRoot(std::string key) { - // std::unique_ptr selectedNode = std::move(Search(key)); - // if (!IsSearchSuccessful(selectedNode)) return; - // int timesPrintedOnLine = 0; - // std::cout << "Path:\n" << selectedNode->key; - // do - // { - // selectedNode = selectedNode->parent; - // std::cout << " -> " << selectedNode->parent->key; - // if (timesPrintedOnLine < 10) ++timesPrintedOnLine; - // else std::cout << "\n"; - // } while (selectedNode->parent); - + std::shared_ptr selectedNode = Search(key); + if (!IsSearchSuccessful(selectedNode, key)) return; + int timesPrintedOnLine = 0; + std::cout << "Path from:" << selectedNode->key << std::endl; + while (selectedNode = selectedNode.get()->parent) + { + std::cout << " -> " << selectedNode.get()->key; + if (timesPrintedOnLine < 5) + timesPrintedOnLine++; + else + { + timesPrintedOnLine = 0; + std::cout << std::endl; + } + } + std::cout << std::endl; return; } // Insert a node into a RBT void RedBlackTree::Insert(std::string keyToInsert) { - // std::unique_ptr newNode = new TreeNode(keyToInsert); - // TreeInterface::Insert(newNode); - // InsertFixup(newNode); + std::shared_ptr newNode = std::make_shared (keyToInsert); + TreeInterface::Insert(newNode); + InsertFixup(newNode); return; } + // Insert the entire vector word list into tree + void RedBlackTree::InsertWordList(std::vector* newWordList) + { + for (int i = 0; i < newWordList->size(); i++) + { + Insert(newWordList->at(i)); + } + } + // Print path to root in RBT // TODO: Implement printing path to root for RBT void RedBlackTree::PrintPathToRoot(std::string key) @@ -194,33 +179,33 @@ namespace tree_implementation // Print color of word if found in RBT void RedBlackTree::PrintColor(std::string key) { - // std::unique_ptr foundNode = std::move(Search(key)); - // if (!IsSearchSuccessful(foundNode)) return; - // std::cout << "The color is " << foundNode->color << '\n'; + std::shared_ptr foundNode = Search(key); + if (!IsSearchSuccessful(foundNode, key)) return; + std::cout << "The color is " << foundNode->color << '\n'; return; } // Print color of word's parent if found in RBT void RedBlackTree::PrintParentColor(std::string key) { - // std::unique_ptr foundNode = std::move(Search(key)); - // if (!IsSearchSuccessful(foundNode)) return; - // std::cout << "The color is " << foundNode->parent->color << '\n'; + std::shared_ptr foundNode = Search(key); + if (!IsSearchSuccessful(foundNode, key)) return; + std::cout << "The color is " << foundNode->parent->color << '\n'; return; } // Print color of word's uncle if found in RBT void RedBlackTree::PrintUncleColor(std::string key) { - // std::unique_ptr foundNode = std::move(Search(key)); - // if (!IsSearchSuccessful(foundNode)) return; - // std::cout << "The color is " << GetUncleNode(foundNode)->color << '\n'; + std::shared_ptr foundNode = Search(key); + if (!IsSearchSuccessful(foundNode, key)) return; + std::cout << "The color is " << GetUncleNode(foundNode).get()->color << '\n'; return; } - void RedBlackTree::InsertFixup(std::unique_ptr z) + void RedBlackTree::InsertFixup(std::shared_ptr z) { - // std::unique_ptr y; + // std::shared_ptr y; // while (z->parent->color == "red") // { // if (z->parent == z->parent->parent->leftChild) @@ -250,48 +235,48 @@ namespace tree_implementation } // Returns the uncle node in RBT - std::unique_ptr RedBlackTree::GetUncleNode(std::unique_ptr startNode) + std::shared_ptr RedBlackTree::GetUncleNode(std::shared_ptr startNode) { - // if (startNode->parent == startNode->parent->parent->leftChild) - // return std::move(startNode->parent->parent->rightChild); - // return std::move(startNode->parent->parent->leftChild); + if (startNode->parent == startNode->parent->parent->leftChild) + return startNode->parent->parent->rightChild; + return startNode->parent->parent->leftChild; } // Performs left rotate on a given node - void RedBlackTree::LeftRotate(std::unique_ptr x) + void RedBlackTree::LeftRotate(std::shared_ptr x) { - // std::unique_ptr y(std::move(x->rightChild)); - // x->rightChild = std::move(y->leftChild); - // if (y->rightChild) - // y->rightChild->parent = std::move(x); - // y->parent = std::move(x->parent); - // if (!x->parent) - // tree.head = std::move(y); - // else if (x == x->parent->leftChild) - // x->parent->leftChild = std::move(y); - // else - // x->parent->rightChild = std::move(y); - // y->leftChild = std::move(x); - // x->parent = std::move(y); + std::shared_ptr y = x->rightChild; + x->rightChild = y->leftChild; + if (y->rightChild) + y->rightChild->parent = x; + y->parent = x->parent; + if (!x->parent) + tree.head = y; + else if (x == x->parent->leftChild) + x->parent->leftChild = y; + else + x->parent->rightChild = y; + y->leftChild = x; + x->parent = y; return; } // Performs right rotate on a given node - void RedBlackTree::RightRotate(std::unique_ptr x) + void RedBlackTree::RightRotate(std::shared_ptr x) { - // std::unique_ptr y(std::move(x->rightChild)); - // x->rightChild = std::move(y->leftChild); - // if (y->leftChild) - // y->leftChild->parent = std::move(x); - // y->parent = std::move(x->parent); - // if (!x->parent) - // tree.head = std::move(y); - // else if (x == x->parent->leftChild) - // x->parent->leftChild = std::move(y); - // else - // x->parent->rightChild = std::move(y); - // y->leftChild = std::move(x); - // x->parent = std::move(y); + std::shared_ptr y = x->rightChild; + x->rightChild = y->leftChild; + if (y->leftChild) + y->leftChild->parent = x; + y->parent = x->parent; + if (!x->parent) + tree.head = y; + else if (x == x->parent->leftChild) + x->parent->leftChild = y; + else + x->parent->rightChild = y; + y->leftChild = x; + x->parent = y; return; } } \ No newline at end of file