From 01d2d7f2cf9d1902e5da6affab8a09cbb24fa869 Mon Sep 17 00:00:00 2001 From: Iurii Tatishchev Date: Fri, 3 May 2024 17:08:04 -0700 Subject: [PATCH] 8.14 Lab*: BT <--- BST ADT (Park) - Modify the Park class from previous assignments. - Rewrite the private insert as a recursive function. - Write the buildBST() function (similar to buildList() in the doubly-linked list lab). - Display the number of nodes in the tree as shown below: - Display the tree in inorder, preorder or postorder - Display the tree as an indented list - Display the inner nodes of the BST (including its root), in alphabetical order by code - Write the searchManager() function (similar to searchManager() in the doubly-linked list lab). It calls search BST in a loop. - Search the BST (implement the recursive private search function). --- 05-trees/.idea/.gitignore | 8 + 05-trees/.idea/.name | 1 + 05-trees/.idea/05-trees.iml | 2 + .../inspectionProfiles/Project_Default.xml | 6 + 05-trees/.idea/misc.xml | 4 + 05-trees/.idea/modules.xml | 8 + 05-trees/.idea/vcs.xml | 6 + 05-trees/BinarySearchTree.h | 52 ++--- 05-trees/BinaryTree.h | 38 ++-- 05-trees/CMakeLists.txt | 4 +- 05-trees/Park.cpp | 80 ++++++++ 05-trees/Park.h | 88 ++++++++ 05-trees/main.cpp | 193 ++++++++++++------ 05-trees/national_parks.txt | 20 ++ 14 files changed, 409 insertions(+), 101 deletions(-) create mode 100644 05-trees/.idea/.gitignore create mode 100644 05-trees/.idea/.name create mode 100644 05-trees/.idea/05-trees.iml create mode 100644 05-trees/.idea/inspectionProfiles/Project_Default.xml create mode 100644 05-trees/.idea/misc.xml create mode 100644 05-trees/.idea/modules.xml create mode 100644 05-trees/.idea/vcs.xml create mode 100644 05-trees/Park.cpp create mode 100644 05-trees/Park.h create mode 100644 05-trees/national_parks.txt diff --git a/05-trees/.idea/.gitignore b/05-trees/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/05-trees/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/05-trees/.idea/.name b/05-trees/.idea/.name new file mode 100644 index 0000000..304a90d --- /dev/null +++ b/05-trees/.idea/.name @@ -0,0 +1 @@ +05_trees \ No newline at end of file diff --git a/05-trees/.idea/05-trees.iml b/05-trees/.idea/05-trees.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/05-trees/.idea/05-trees.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/05-trees/.idea/inspectionProfiles/Project_Default.xml b/05-trees/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/05-trees/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/05-trees/.idea/misc.xml b/05-trees/.idea/misc.xml new file mode 100644 index 0000000..79b3c94 --- /dev/null +++ b/05-trees/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/05-trees/.idea/modules.xml b/05-trees/.idea/modules.xml new file mode 100644 index 0000000..772ded0 --- /dev/null +++ b/05-trees/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/05-trees/.idea/vcs.xml b/05-trees/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/05-trees/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/05-trees/BinarySearchTree.h b/05-trees/BinarySearchTree.h index 242d1fc..d3b8f95 100644 --- a/05-trees/BinarySearchTree.h +++ b/05-trees/BinarySearchTree.h @@ -14,7 +14,7 @@ public: bool insert(const ItemType &item); // remove a node if found - //bool remove(const ItemType &item); + // bool remove(const ItemType &item); // find a target node bool search(const ItemType &target, ItemType &returnedItem) const; @@ -41,10 +41,10 @@ private: // BinaryNode* _remove(BinaryNode* nodePtr, const ItemType target, bool &success); // delete target node from tree, called by internal remove node - // BinaryNode* _removeNode(BinaryNode* targetNodePtr); + // BinaryNode* _removeNode(BinaryNode* targetNodePtr); // remove the leftmost node in the left subtree of nodePtr - // BinaryNode* _removeLeftmostNode(BinaryNode* nodePtr, ItemType &successor); + // BinaryNode* _removeLeftmostNode(BinaryNode* nodePtr, ItemType &successor); }; @@ -52,8 +52,9 @@ private: // Wrapper for _insert - Inserting items within a tree template bool BinarySearchTree::insert(const ItemType &newEntry) { - BinaryNode *newNodePtr = new BinaryNode(newEntry); + auto *newNodePtr = new BinaryNode(newEntry); this->rootPtr = _insert(this->rootPtr, newNodePtr); + this->count++; return true; } @@ -92,31 +93,31 @@ bool BinarySearchTree::search(const ItemType &anEntry, ItemType &retur //////////////////////////// private functions //////////////////////////////////////////// -// Implementation of the insert operation: iterative algorithm +// Recursive implementation of the insert operation template BinaryNode *BinarySearchTree::_insert(BinaryNode *nodePtr, BinaryNode *newNodePtr) { - BinaryNode *pWalk = nodePtr, *parent = nullptr; + // Base case: tree is empty + if (nodePtr == nullptr) return newNodePtr; - if (!nodePtr) // == NULL - { - nodePtr = newNodePtr; - return nodePtr; - } else { - while (pWalk) // != NULL - { - parent = pWalk; - if (pWalk->getItem() > newNodePtr->getItem()) - pWalk = pWalk->getLeftPtr(); - else - pWalk = pWalk->getRightPtr(); - } - if (parent->getItem() > newNodePtr->getItem()) - parent->setLeftPtr(newNodePtr); - else - parent->setRightPtr(newNodePtr); + // Inserting larger item to the right: + if (nodePtr->getItem() < newNodePtr->getItem()) { + // Recurse if right child is not null + if (nodePtr->getRightPtr() != nullptr) + _insert(nodePtr->getRightPtr(), newNodePtr); + // Otherwise, insert the new node + else nodePtr->setRightPtr(newNodePtr); + } + // Inserting smaller item to the left: + else { + // Recurse if left child is not null + if (nodePtr->getLeftPtr() != nullptr) + _insert(nodePtr->getLeftPtr(), newNodePtr); + // Otherwise, insert the new node + else nodePtr->setLeftPtr(newNodePtr); } + // Return the root node return nodePtr; } @@ -141,7 +142,7 @@ BinaryNode *BinarySearchTree::_findLargest(BinaryNodegetRightPtr(), biggest); } -// Implementation for the search operation: recursive algorithm +// Recursive implementation of the search operation // - return NULL if target not found, otherwise // - returns a pointer to the node that matched the target template @@ -154,6 +155,9 @@ BinaryNode *BinarySearchTree::_search(BinaryNode * // Recursive cases, search either left or right subtree based on the target if (target < nodePtr->getItem()) return _search(nodePtr->getLeftPtr(), target); if (target > nodePtr->getItem()) return _search(nodePtr->getRightPtr(), target); + + // To prevent compiler warning + return nullptr; } #endif diff --git a/05-trees/BinaryTree.h b/05-trees/BinaryTree.h index f910bda..7c6fdbb 100644 --- a/05-trees/BinaryTree.h +++ b/05-trees/BinaryTree.h @@ -35,13 +35,15 @@ public: count = 0; } - void preOrder(void visit(ItemType &)) const { _preorder(visit, rootPtr); } + void preOrder(void visit(const ItemType &)) const { _preorder(visit, rootPtr); } - void inOrder(void visit(ItemType &)) const { _inorder(visit, rootPtr); } + void inOrder(void visit(const ItemType &)) const { _inorder(visit, rootPtr); } - void postOrder(void visit(ItemType &)) const { _postorder(visit, rootPtr); } + void postOrder(void visit(const ItemType &)) const { _postorder(visit, rootPtr); } - void printTree(void visit(ItemType &, int)) const { _printTree(visit, rootPtr, 1); } + void printTree(void visit(const ItemType &, int)) const { _printTree(visit, rootPtr, 1); } + + void printInnerNodes(void visit(const ItemType &)) const { _printInnerNodes(visit, rootPtr); } // abstract functions to be implemented by derived class virtual bool insert(const ItemType &newData) = 0; @@ -54,14 +56,15 @@ private: void destroyTree(BinaryNode *nodePtr); // internal traverse - void _preorder(void visit(ItemType &), BinaryNode *nodePtr) const; + void _preorder(void visit(const ItemType &), BinaryNode *nodePtr) const; - void _inorder(void visit(ItemType &), BinaryNode *nodePtr) const; + void _inorder(void visit(const ItemType &), BinaryNode *nodePtr) const; - void _postorder(void visit(ItemType &), BinaryNode *nodePtr) const; + void _postorder(void visit(const ItemType &), BinaryNode *nodePtr) const; - void _printTree(void visit(ItemType &, int), BinaryNode *nodePtr, int level) const; + void _printTree(void visit(const ItemType &, int), BinaryNode *nodePtr, int level) const; + void _printInnerNodes(void visit(const ItemType &), BinaryNode *nodePtr) const; }; // Destroy the entire tree @@ -78,7 +81,7 @@ void BinaryTree::destroyTree(BinaryNode *nodePtr) { // Preorder Traversal template -void BinaryTree::_preorder(void visit(ItemType &), BinaryNode *nodePtr) const { +void BinaryTree::_preorder(void visit(const ItemType &), BinaryNode *nodePtr) const { if (nodePtr == nullptr) return; ItemType item = nodePtr->getItem(); @@ -90,7 +93,7 @@ void BinaryTree::_preorder(void visit(ItemType &), BinaryNode -void BinaryTree::_inorder(void visit(ItemType &), BinaryNode *nodePtr) const { +void BinaryTree::_inorder(void visit(const ItemType &), BinaryNode *nodePtr) const { if (nodePtr) // != NULL { ItemType item = nodePtr->getItem(); @@ -102,7 +105,7 @@ void BinaryTree::_inorder(void visit(ItemType &), BinaryNode // Postorder Traversal template -void BinaryTree::_postorder(void visit(ItemType &), BinaryNode *nodePtr) const { +void BinaryTree::_postorder(void visit(const ItemType &), BinaryNode *nodePtr) const { if (nodePtr == nullptr) return; _postorder(visit, nodePtr->getLeftPtr()); @@ -113,7 +116,7 @@ void BinaryTree::_postorder(void visit(ItemType &), BinaryNode -void BinaryTree::_printTree(void visit(ItemType &, int), BinaryNode *nodePtr, int level) const { +void BinaryTree::_printTree(void visit(const ItemType &, int), BinaryNode *nodePtr, int level) const { if (nodePtr == nullptr) return; ItemType item = nodePtr->getItem(); @@ -122,4 +125,15 @@ void BinaryTree::_printTree(void visit(ItemType &, int), BinaryNodegetLeftPtr(), level + 1); } +// Prints inner nodes +template +void BinaryTree::_printInnerNodes(void visit(const ItemType &), BinaryNode *nodePtr) const { + if (nodePtr == nullptr || nodePtr->isLeaf()) return; + + ItemType item = nodePtr->getItem(); + _printInnerNodes(visit, nodePtr->getLeftPtr()); + visit(item); + _printInnerNodes(visit, nodePtr->getRightPtr()); +} + #endif diff --git a/05-trees/CMakeLists.txt b/05-trees/CMakeLists.txt index c5e6975..26f8b12 100644 --- a/05-trees/CMakeLists.txt +++ b/05-trees/CMakeLists.txt @@ -6,4 +6,6 @@ set(CMAKE_CXX_STANDARD 20) add_executable(05_trees main.cpp BinaryTree.h BinaryNode.h - BinarySearchTree.h) + BinarySearchTree.h + Park.cpp + Park.h) diff --git a/05-trees/Park.cpp b/05-trees/Park.cpp new file mode 100644 index 0000000..e7bf157 --- /dev/null +++ b/05-trees/Park.cpp @@ -0,0 +1,80 @@ +// Implementation file for the Park class +// Written By: Iurii Tatishchev +// Reviewed By: Iurii Tatishchev +// IDE: CLion + +#include +#include +#include + +#include "Park.h" + +using namespace std; + +// ************************************************** +// Constructor +// ************************************************** +Park::Park() { + code = ""; + state = ""; + name = ""; + description = ""; + year = -1; +} + +// ************************************************** +// Overloaded Constructor +// ************************************************** +Park::Park(string cd, string st, string nm, string dsc, int yr) { + code = cd; + state = st; + name = nm; + description = dsc; + year = yr; +} + +// Friend Functions Definitions + +// *********************************************************** +// hDisplay +// Displays code, state, and year data members of a Park object +// on one line (horizontal display) +// *********************************************************** +void hDisplay(const Park &item) { + cout << item.code << " "; + cout << item.state << " "; + cout << item.year << " "; + cout << endl; +} + +// *********************************************************** +// vDisplay +// Displays name, description, state, and year of a Park object +// one per line (vertical display) +// *********************************************************** +void vDisplay(const Park &item) { + cout << " Name: " << item.name << endl; + cout << "Description: " << item.description << endl; + cout << " State: " << item.state << endl; + cout << " Year: " << item.year << endl; +} + +// *********************************************************** +// iDisplay +// on one line, including the level number and +// ".." for each indentation level +// *********************************************************** +void iDisplay(const Park &item, int level) { + for (int i = 1; i < level; i++) + cout << ".."; + cout << level << "). " << item.code << endl; +} + +// *********************************************************** +// kDisplay +// Displays the key: code of a Park object +// on one line (key display) +// *********************************************************** +void kDisplay(const Park &park) { + cout << park.code << "\n"; +} diff --git a/05-trees/Park.h b/05-trees/Park.h new file mode 100644 index 0000000..98421db --- /dev/null +++ b/05-trees/Park.h @@ -0,0 +1,88 @@ +// Specification file for the Park class +// Written By: Iurii Tatishchev +// Reviewed by: Iurii Tatishchev +// IDE: CLion + +#ifndef PARK_H +#define PARK_H + +// #include +#include +// #include + +// using namespace std; +// ^^^^^ This statement +// in a header file of a complex project could create +// namespace management problems for the entire project +// (such as name collisions). +// Do not write using namespace at the top level in a header file! + +using std::string; + +class Park { +private: + string code; // the unique park identifier + string state; + string name; + string description; + int year; + +public: + // constructors + Park(); + + Park(string, string, string, string, int); + + // setters + void setCode(string cd) { code = cd; } + + void setState(string st) { state = st; } + + void setName(string nm) { name = nm; } + + void setDesc(int dsc) { description = dsc; } + + void setYear(int yr) { year = yr; } + + // getters + string getCode() const { return code; } + + string getState() const { return state; } + + string getName() const { return name; } + + string getDesc() const { return description; } + + int getYear() const { return year; } + + /* overloaded operators + - the stream insertion operator ( << ) + - the relational operators (<, >, == ) + */ + friend std::ostream &operator<<(std::ostream &out, const Park &park); + + bool operator<(const Park &park) const { return code < park.code; } + + bool operator>(const Park &park) const { return code > park.code; } + + bool operator==(const Park &park) const { return code == park.code; } + + // friend functions + friend void hDisplay(const Park &); + + friend void vDisplay(const Park &); + + friend void iDisplay(const Park &item, int level); + + friend void kDisplay(const Park &item); +}; + +void hDisplay(const Park &); + +void vDisplay(const Park &); + +void iDisplay(const Park &item, int level); + +void kDisplay(const Park &item); + +#endif diff --git a/05-trees/main.cpp b/05-trees/main.cpp index 1e09de9..8f7a4bc 100644 --- a/05-trees/main.cpp +++ b/05-trees/main.cpp @@ -1,87 +1,152 @@ // BST ADT -// Name: Iurii Tatishchev +// Created by Iurii Tatishchev +// Modified by: Iurii Tatishchev #include "BinarySearchTree.h" +#include "Park.h" #include +#include +#include #include +#include using namespace std; -void buildBST(int n, BinarySearchTree &); +void displayManager(const BinarySearchTree &bst); -void hDisplay(int &); +void buildBST(const string &filename, BinarySearchTree &bst); -void vDisplay(int &); - -void iDisplay(int &, int); +void searchManager(const BinarySearchTree &bst); int main() { - BinarySearchTree bst; + string filename; + BinarySearchTree bst; - int n; - - cout << "What is the number of nodes in the BST? " << endl; - cin >> n; - - buildBST(n, bst); - - cout << "Inorder: "; - bst.inOrder(hDisplay); - cout << endl; - cout << "Search Section:" << endl; - int searchCount = n / 2; - int target, item; - while (searchCount--) { - target = rand() % 30 + 10; - cout << target; - if (bst.search(target, item)) { - cout << " FOUND! Data contains: " - << item << endl; - } else - cout << " NOT FOUND!\n"; - } + cout << "What is the input file's name? "; + getline(cin, filename); + buildBST(filename, bst); + displayManager(bst); + searchManager(bst); return 0; } /* - buildBST: builds a binary search tree - of integers +Display manager: traversals, count, indented tree, and inner nodes +Input Parameter: bst */ -void buildBST(int n, BinarySearchTree &bst) { - bool duplicate[41] = {false}; // all are set to 0 (false) - int item; +void displayManager(const BinarySearchTree &bst) { - while (n > 0) { - item = rand() % 31 + 10; - if (duplicate[item] == false) { // not a duplicate - bst.insert(item); - n--; - duplicate[item] = true; + string option; + + // count + cout << "Display count [Y/N]?" << endl; + getline(cin, option); + option[0] = toupper(option[0]); + if (option == "Y") { + cout << "The number of nodes in the BST is "; + cout << bst.getCount() << endl; + } + + // traversals + cout << "Display Tree [In/Pre/posT/N]?" << endl; + getline(cin, option); // I, P, T or N + option[0] = toupper(option[0]); + switch (option[0]) { + case 'I': + cout << endl << "Inorder:" << endl; + bst.inOrder(hDisplay); + cout << endl; + break; + case 'P': + cout << endl << "Preorder:" << endl; + bst.preOrder(hDisplay); + cout << endl; + break; + case 'T': + cout << endl << "Postorder:" << endl; + bst.postOrder(hDisplay); + cout << endl; + break; + case 'N': + break; + default: + cout << "Invalid option!" << endl; + break; + } + + // Indented Tree + cout << "Display Indented List [Y/N]?" << endl; + getline(cin, option); + option[0] = toupper(option[0]); + if (option == "Y") { + cout << "Indented List:" << endl; + bst.printTree(iDisplay); + cout << endl; + } + + // Inner Nodes + cout << "Display Inner Nodes [Y/N]?" << endl; + getline(cin, option); + option[0] = toupper(option[0]); + if (option == "Y") { + cout << "Inner Nodes:" << endl; + bst.printInnerNodes(kDisplay); + cout << endl; + } + +} + +void buildBST(const string &filename, BinarySearchTree &bst) { + ifstream inputFile(filename); + cout << "Reading data from \"" << filename << "\"" << endl; + + if (!inputFile) { + cout << "Error opening the input file: \"" << filename << "\"" << endl; + exit(EXIT_FAILURE); + } + + string line; + while (getline(inputFile, line)) { + int year; + string code, name, state, dsc; + + stringstream temp(line); // create temp with data from line + temp >> code; // read from temp + temp >> state; + temp >> year; + temp.ignore(); // to ignore space in front of name + getline(temp, name, ';'); // stop reading name at ';' + temp.ignore(); // to ignore space in front of description + getline(temp, dsc); + // create a Park object and initialize it with data from file + Park aPark(code, state, name, dsc, year); + bst.insert(aPark); + } + + inputFile.close(); +} + +void searchManager(const BinarySearchTree &bst) { + string targetCode = ""; + Park aPark; + + cout << endl << " Search" << endl; + cout << "=======" << endl; + + while (targetCode != "Q") { + cout << "Enter a park code (or Q to stop searching):" << endl; + getline(cin, targetCode); + // Convert targetCode to uppercase + for (char &c : targetCode) c = toupper(c); + if (targetCode != "Q") { + Park target; + target.setCode(targetCode); + if (bst.search(target, aPark)) + vDisplay(aPark); + else + cout << "Park \"" << targetCode << "\" was not found in this list." << endl; } } + cout << "___________________END SEARCH SECTION _____" << endl; } - -/* - horizontal display: all items on one line -*/ -void hDisplay(int &item) { - cout << item << " "; -} - -/* - vertical display: one item per line -*/ -void vDisplay(int &item) { - cout << item << endl; -} - -/* - indented tree display: one item per line, including the level number -*/ -void iDisplay(int &item, int level) { - for (int i = 1; i < level; i++) - cout << ".."; - cout << level << "). " << item << endl; - -} \ No newline at end of file diff --git a/05-trees/national_parks.txt b/05-trees/national_parks.txt new file mode 100644 index 0000000..8ecbe22 --- /dev/null +++ b/05-trees/national_parks.txt @@ -0,0 +1,20 @@ +MOJ CA 1994 Mojave National Preserve; Spectacular Landscape in Absolute Solitude +YOS CA 1890 Yosemite National Park; A Land of Giants +LAS CA 1916 Lassen Volcanic National Park; Bubbling Below the Surface +PRE CA 1962 Point Reyes National Seashore; Sky Above, Sea Beyond +BRC UT 1928 Bryce Canyon National Park; Pillars of Stone +DEV CA 1911 Devils Postpile National Monument; A Geologic Gem +MUW CA 1908 Muir Woods National Monument; John Muir’s Cathedral +CAL UT 1964 Canyonlands National Park; The Heart of the High Desert +GLA MT 1910 Glacier National Park; Reflections of the Past +ALC CA 1934 Alcatraz Island; Landmark Unlocked +YEL WY 1872 Yellowstone National Park; Otherworldly on Earth +ROC CO 1915 Rocky Mountain National Park; On Top of the World +CRA OR 1902 Crater Lake National Park; Deep and Pristine Waters +PIN CA 2013 Pinnacles National Park; Spectacular Remains of an Ancient Volcano +DEN AK 1980 Denali National Park and Preserve; Beyond the Mountain +ZIO UT 1919 Zion National Park; An Oasis Amidst the Desert +JOS CA 1994 Joshua Tree National Park; The Outer Limits of Reality +GRC AZ 1908 Grand Canyon National Park; A Sight Beyond Words +ARC UT 1929 Arches National Park; Windows to the Sky +DEA CA 1994 Death Valley National Park; A Land of Extremes \ No newline at end of file