diff --git a/Project10/Project10.cpp b/Project10/Project10.cpp new file mode 100644 index 0000000..0f1454e --- /dev/null +++ b/Project10/Project10.cpp @@ -0,0 +1,149 @@ +// Corey Williams +// COP3530 01Z +// Project 10 + +/* +Extend the application developed for Project 9 by adding features to “Display all Binary Tree Objects (preorder traversal), +“Display all Binary Tree Objects (inorder traversal), “Display all Binary Tree Objects (postorder traversal), and “Delete a Node”. +The application must provide a menu for all tasks. + + Add Circle Object to Binary Tree + Search for Circle Object in Binary Tree + Display all Binary Tree Circle Objects (preorder traversal) + Display all Binary Tree Circle Objects (inorder traversal) + Display all Binary Tree Circle Objects (postorder traversal) + Delete a Node + Exit + +*/ + +using namespace std; + +#include +#include "circle10.h" +#include "genBST10.h" +#include + +void menu_addObj(BST& circleTree) { + string s; + + system("cls"); + cout << "Enter a number to add a circle of that radius to the tree" << endl + << "or enter q to return to the main menu." << endl; + + while (s != "q" and s != "Q") { + cout << endl << "Input: "; + cin >> s; + + try { + Circle tmp(stod(s)); + circleTree.insert(tmp); + cout << "Circle of radius " << s << " added to tree." << endl; + } + catch (...) { + cout << "Not a valid entry, please try again. " << endl; + continue; + } + } +} + +void menu_search(BST& circleTree) { + string s; + + system("cls"); + cout << "Enter a radius, and a search will be conducted to find a matching element" << endl + << "or enter q to return to the main menu." << endl; + + while (s != "q" and s != "Q") { + cout << endl << "Search Criteria: "; + cin >> s; + + try { + Circle tmp(stod(s)); + if (circleTree.search(tmp)) + cout << "A circle of radius " << s << " exists in the tree." << endl; + else + cout << "No objects with radius " << s << " exist in the tree." << endl; + } + catch (...) { + cout << "Not a valid entry, please try again. " << endl; + continue; + } + } +} + +void menu_displayTreePreorder(BST& circleTree) { + system("cls"); + cout << "Tree Objects in Preorder Traversal are:" << endl; + circleTree.preorder(); + system("pause"); +} + +void menu_displayTreeInorder(BST& circleTree) { + system("cls"); + cout << "Tree Objects in Inorder Traversal are:" << endl; + circleTree.inorder(); + system("pause"); +} + +void menu_displayTreePostorder(BST& circleTree) { + system("cls"); + cout << "Tree Objects in Postorder Traversal are:" << endl; + circleTree.postorder(); + system("pause"); +} + +void menu_deleteNode(BST& circleTree) { + string s; + + system("cls"); + cout << "Enter a radius for a circle that you would like to delete from the tree" << endl + << "or enter q to return to the main menu." << endl; + + while (s != "q" and s != "Q") { + cout << endl << "Radius for circle to delete: "; + cin >> s; + + try { + Circle tmp(stod(s)); + circleTree.findAndDeleteByCopying(tmp); + } + catch (...) { + cout << "Not a valid entry, please try again. " << endl; + continue; + } + } +} + +int main() +{ + BST circleTree; + string menuOpt; + + while (true) { + system("cls"); + //Display main options menu + cout << "Main Menu" << endl + << "1. Add Circle Object to Binary Tree" << endl + << "2. Search for Circle Object in Binary Tree" << endl + << "3. Display All Binary Tree Circle Objects (preorder traversal)" << endl + << "4. Display All Binary Tree Circle Objects (inorder traversal)" << endl + << "5. Display All Binary Tree Circle Objects (postorder traversal)" << endl + << "6. Delete a node" << endl + << "7. Exit Application" << endl << endl + << "Enter an Option: "; + cin >> menuOpt; + + if (menuOpt == "1") menu_addObj(circleTree); + else if (menuOpt == "2") menu_search(circleTree); + else if (menuOpt == "3") menu_displayTreePreorder(circleTree); + else if (menuOpt == "4") menu_displayTreeInorder(circleTree); + else if (menuOpt == "5") menu_displayTreePostorder(circleTree); + else if (menuOpt == "6") menu_deleteNode(circleTree); + else if (menuOpt == "7" or menuOpt == "q") return 0; + else { + cout << endl << "Not a valid selection. "; + system("pause"); + } + } +} \ No newline at end of file diff --git a/Project10/Project10.sln b/Project10/Project10.sln new file mode 100644 index 0000000..db4a9a1 --- /dev/null +++ b/Project10/Project10.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33801.468 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Project10", "Project10.vcxproj", "{4B1BD4AB-6B88-4B70-BEFF-F6C348C29EE4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4B1BD4AB-6B88-4B70-BEFF-F6C348C29EE4}.Debug|x64.ActiveCfg = Debug|x64 + {4B1BD4AB-6B88-4B70-BEFF-F6C348C29EE4}.Debug|x64.Build.0 = Debug|x64 + {4B1BD4AB-6B88-4B70-BEFF-F6C348C29EE4}.Debug|x86.ActiveCfg = Debug|Win32 + {4B1BD4AB-6B88-4B70-BEFF-F6C348C29EE4}.Debug|x86.Build.0 = Debug|Win32 + {4B1BD4AB-6B88-4B70-BEFF-F6C348C29EE4}.Release|x64.ActiveCfg = Release|x64 + {4B1BD4AB-6B88-4B70-BEFF-F6C348C29EE4}.Release|x64.Build.0 = Release|x64 + {4B1BD4AB-6B88-4B70-BEFF-F6C348C29EE4}.Release|x86.ActiveCfg = Release|Win32 + {4B1BD4AB-6B88-4B70-BEFF-F6C348C29EE4}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {22738737-339B-4480-9BD6-6FDC27660C86} + EndGlobalSection +EndGlobal diff --git a/Project10/Project10.vcxproj b/Project10/Project10.vcxproj new file mode 100644 index 0000000..d8697e6 --- /dev/null +++ b/Project10/Project10.vcxproj @@ -0,0 +1,139 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {4b1bd4ab-6b88-4b70-beff-f6c348c29ee4} + Project10 + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/Project10/Project10.vcxproj.filters b/Project10/Project10.vcxproj.filters new file mode 100644 index 0000000..34b15e7 --- /dev/null +++ b/Project10/Project10.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/Project10/circle10.h b/Project10/circle10.h new file mode 100644 index 0000000..778f2a0 --- /dev/null +++ b/Project10/circle10.h @@ -0,0 +1,34 @@ +#ifndef CIRCLE_HEADER +#define CIRCLE_HEADER + +#define _USE_MATH_DEFINES + +#include + +class Circle { +private: + double radius; + +public: + Circle() { + radius = 0; + } + + Circle(double r) { + radius = r; + } + + double getRadius() const { + return radius; + } + + void setRadius(double r) { + radius = r; + } + + double calculateArea() const { + return M_PI * radius * radius; + } +}; + +#endif \ No newline at end of file diff --git a/Project10/genBST10.h b/Project10/genBST10.h new file mode 100644 index 0000000..1febe46 --- /dev/null +++ b/Project10/genBST10.h @@ -0,0 +1,459 @@ +//************************ genBST.h ************************** +// generic binary search tree + +#include +#include + +#ifndef BINARY_SEARCH_TREE +#define BINARY_SEARCH_TREE + +template +class Stack : public stack { +public: + T pop() { + T tmp = stack::pop(); + return tmp; + } +}; + +template +class Queue : public queue { +public: + T dequeue() { + T tmp = queue::pop(); + return tmp; + } + void enqueue(const T& el) { + push(el); + } +}; +template class BST; + +template +class BSTNode { +public: + BSTNode() { + left = right = 0; + } + BSTNode(const T& e, BSTNode *l = 0, BSTNode *r = 0) { + el = e; left = l; right = r; + } + T el; + BSTNode *left, *right; +}; + +template +class BST { +public: + BST() { + root = 0; + } + ~BST() { + clear(); + } + void clear() { + clear(root); + root = 0; + } + bool isEmpty() const { + return root == 0; + } + void preorder() { + preorder(root); + } + void inorder() { + inorder(root); + } + void postorder() { + postorder(root); + } + void insert(const T&); + void recursiveInsert(const T& el) { + recursiveInsert(root,el); + } + T* search(const T& el) const { + return search(root,el); + } + T* recursiveSearch(const T& el) const { + return recursiveSearch(root,el); + } + void deleteByCopying(BSTNode*&); + void findAndDeleteByCopying(const T&); + void deleteByMerging(BSTNode*&); + void findAndDeleteByMerging(const T&); + void iterativePreorder(); + void iterativeInorder(); + void iterativePostorder(); + void breadthFirst(); + void MorrisPreorder(); + void MorrisInorder(); + void MorrisPostorder(); + void balance(T*,int,int); +protected: + BSTNode* root; + void clear(BSTNode*); + void recursiveInsert(BSTNode*&, const T&); + T* search(BSTNode*, const T&) const; + T* recursiveSearch(BSTNode*, const T&) const; + void preorder(BSTNode*); + void inorder(BSTNode*); + void postorder(BSTNode*); + virtual void visit(BSTNode* p) { + cout << "R: " << p->el.getRadius() << endl + << "A: " << p->el.calculateArea() << endl << endl; + } +}; + +template +void BST::clear(BSTNode *p) { + if (p != 0) { + clear(p->left); + clear(p->right); + delete p; + } +} + +template +void BST::insert(const T& el) { + BSTNode *p = root, *prev = 0; + while (p != 0) { // find a place for inserting new node; + prev = p; + if (el.getRadius() < p->el.getRadius()) + p = p->left; + else p = p->right; + } + if (root == 0) // tree is empty; + root = new BSTNode(el); + else if (el.getRadius() < prev->el.getRadius()) + prev->left = new BSTNode(el); + else prev->right = new BSTNode(el); +} + +template +void BST::recursiveInsert(BSTNode*& p, const T& el) { + if (p == 0) + p = new BSTNode(el); + else if (el < p->el) + recursiveInsert(p->left, el); + else recursiveInsert(p->right,el); +} + +template +T* BST::search(BSTNode* p, const T& el) const { + while (p != 0) + if (el.getRadius() == p->el.getRadius()) + return &p->el; + else if (el.getRadius() < p->el.getRadius()) + p = p->left; + else p = p->right; + return 0; +} + +template +T* BST::recursiveSearch(BSTNode* p, const T& el) const { + if (p != 0) + if (el == p->el) + return &p->el; + else if (el < p->el) + return recursiveSearch(p->left,el); + else return recursiveSearch(p->right,el); + else return 0; +} + +template +void BST::inorder(BSTNode *p) { + if (p != 0) { + inorder(p->left); + visit(p); + inorder(p->right); + } +} + +template +void BST::preorder(BSTNode *p) { + if (p != 0) { + visit(p); + preorder(p->left); + preorder(p->right); + } +} + +template +void BST::postorder(BSTNode* p) { + if (p != 0) { + postorder(p->left); + postorder(p->right); + visit(p); + } +} + +template +void BST::deleteByCopying(BSTNode*& node) { + BSTNode *previous, *tmp = node; + if (node->right == 0) // node has no right child; + node = node->left; + else if (node->left == 0) // node has no left child; + node = node->right; + else { + tmp = node->left; // node has both children; + previous = node; // 1. + while (tmp->right != 0) { // 2. + previous = tmp; + tmp = tmp->right; + } + node->el = tmp->el; // 3. + if (previous == node) + previous->left = tmp->left; + else previous->right = tmp->left; // 4. + } + delete tmp; // 5. +} + +// findAndDeleteByCopying() searches the tree to locate the node containing +// el. If the node is located, the function DeleteByCopying() is called. + +template +void BST::findAndDeleteByCopying(const T& el) { + BSTNode *p = root, *prev = 0; + while (p != 0 && !(p->el.getRadius() == el.getRadius())) { + prev = p; + if (el.getRadius() < p->el.getRadius()) + p = p->left; + else p = p->right; + } + if (p != 0 && p->el.getRadius() == el.getRadius()) + if (p == root) { + deleteByCopying(root); + cout << "Circle of radius " << el.getRadius() << " deleted.\n"; + } + else if (prev->left == p) { + deleteByCopying(prev->left); + cout << "Circle of radius " << el.getRadius() << " deleted.\n"; + } + else { + deleteByCopying(prev->right); + cout << "Circle of radius " << el.getRadius() << " deleted.\n"; + } + else if (root != 0) + cout << "Circle of radius " << el.getRadius() << " is not in the tree\n"; + else cout << "the tree is empty\n"; +} + +template +void BST::deleteByMerging(BSTNode*& node) { + BSTNode *tmp = node; + if (node != 0) { + if (!node->right) // node has no right child: its left + node = node->left; // child (if any) is attached to its parent; + else if (node->left == 0) // node has no left child: its right + node = node->right; // child is attached to its parent; + else { // be ready for merging subtrees; + tmp = node->left; // 1. move left + while (tmp->right != 0)// 2. and then right as far as possible; + tmp = tmp->right; + tmp->right = // 3. establish the link between the + node->right; // the rightmost node of the left + // subtree and the right subtree; + tmp = node; // 4. + node = node->left; // 5. + } + delete tmp; // 6. + } +} + +template +void BST::findAndDeleteByMerging(const T& el) { + BSTNode *node = root, *prev = 0; + while (node != 0) { + if (node->el == el) + break; + prev = node; + if (el < node->el) + node = node->left; + else node = node->right; + } + if (node != 0 && node->el == el) + if (node == root) + deleteByMerging(root); + else if (prev->left == node) + deleteByMerging(prev->left); + else deleteByMerging(prev->right); + else if (root != 0) + cout << "el " << el << " is not in the tree\n"; + else cout << "the tree is empty\n"; +} + +template +void BST::iterativePreorder() { + Stack*> travStack; + BSTNode *p = root; + if (p != 0) { + travStack.push(p); + while (!travStack.empty()) { + p = travStack.pop(); + visit(p); + if (p->right != 0) + travStack.push(p->right); + if (p->left != 0) // left child pushed after right + travStack.push(p->left); // to be on the top of the stack; + } + } +} + +template +void BST::iterativeInorder() { + Stack*> travStack; + BSTNode *p = root; + while (p != 0) { + while (p != 0) { // stack the right child (if any) + if (p->right) // and the node itself when going + travStack.push(p->right); // to the left; + travStack.push(p); + p = p->left; + } + p = travStack.pop(); // pop a node with no left child + while (!travStack.empty() && p->right == 0) { // visit it and all nodes + visit(p); // with no right child; + p = travStack.pop(); + } + visit(p); // visit also the first node with + if (!travStack.empty()) // a right child (if any); + p = travStack.pop(); + else p = 0; + } +} + +template +void BST::iterativePostorder() { + Stack*> travStack; + BSTNode* p = root, *q = root; + while (p != 0) { + for ( ; p->left != 0; p = p->left) + travStack.push(p); + while (p->right == 0 || p->right == q) { + visit(p); + q = p; + if (travStack.empty()) + return; + p = travStack.pop(); + } + travStack.push(p); + p = p->right; + } +} + +template +void BST::breadthFirst() { + Queue*> queue; + BSTNode *p = root; + if (p != 0) { + queue.enqueue(p); + while (!queue.empty()) { + p = queue.dequeue(); + visit(p); + if (p->left != 0) + queue.enqueue(p->left); + if (p->right != 0) + queue.enqueue(p->right); + } + } +} + +template +void BST::MorrisInorder() { + BSTNode *p = root, *tmp; + while (p != 0) + if (p->left == 0) { + visit(p); + p = p->right; + } + else { + tmp = p->left; + while (tmp->right != 0 &&// go to the rightmost node of + tmp->right != p) // the left subtree or + tmp = tmp->right; // to the temporary parent of p; + if (tmp->right == 0) { // if 'true' rightmost node was + tmp->right = p; // reached, make it a temporary + p = p->left; // parent of the current root, + } + else { // else a temporary parent has been + visit(p); // found; visit node p and then cut + tmp->right = 0; // the right pointer of the current + p = p->right; // parent, whereby it ceases to be + } // a parent; + } +} + +template +void BST::MorrisPreorder() { + BSTNode *p = root, *tmp; + while (p != 0) { + if (p->left == 0) { + visit(p); + p = p->right; + } + else { + tmp = p->left; + while (tmp->right != 0 &&// go to the rightmost node of + tmp->right != p) // the left subtree or + tmp = tmp->right; // to the temporary parent of p; + if (tmp->right == 0) { // if 'true' rightmost node was + visit(p); // reached, visit the root and + tmp->right = p; // make the rightmost node a temporary + p = p->left; // parent of the current root, + } + else { // else a temporary parent has been + tmp->right = 0; // found; cut the right pointer of + p = p->right; // the current parent, whereby it ceases + } // to be a parent; + } + } +} + +template +void BST::MorrisPostorder() { + BSTNode *p = new BSTNode(), *tmp, *q, *r, *s; + p->left = root; + while (p != 0) + if (p->left == 0) + p = p->right; + else { + tmp = p->left; + while (tmp->right != 0 &&// go to the rightmost node of + tmp->right != p) // the left subtree or + tmp = tmp->right; // to the temporary parent of p; + if (tmp->right == 0) { // if 'true' rightmost node was + tmp->right = p; // reached, make it a temporary + p = p->left; // parent of the current root, + } + else { // else a temporary parent has been found; + // process nodes between p->left (included) and p (excluded) + // extended to the right in modified tree in reverse order; + // the first loop descends this chain of nodes and reverses + // right pointers; the second loop goes back, visits nodes, + // and reverses right pointers again to restore the pointers + // to their original setting; + for (q = p->left, r = q->right, s = r->right; + r != p; q = r, r = s, s = s->right) + r->right = q; + for (s = q->right; q != p->left; + q->right = r, r = q, q = s, s = s->right) + visit(q); + visit(p->left); // visit node p->left and then cut + tmp->right = 0; // the right pointer of the current + p = p->right; // parent, whereby it ceases to be + } // a parent; + } +} + +template +void BST::balance (T data[], int first, int last) { + if (first <= last) { + int middle = (first + last)/2; + insert(data[middle]); + balance(data,first,middle-1); + balance(data,middle+1,last); + } +} + +#endif diff --git a/Project11/Project11.cpp b/Project11/Project11.cpp new file mode 100644 index 0000000..411430c --- /dev/null +++ b/Project11/Project11.cpp @@ -0,0 +1,32 @@ +// Corey Williams +// COP3530 01Z +// Project 11 + +/* + Write an application, that calls a recursive method, “shortestBranch” (i.e., must be written) + and displays the depth to the shallowest node of the binary tree. +*/ + +/* Note - Project is incomplete - I had difficulty in returning what I believe to be +the correct depth via the recursive shortestBranch function added in genBST11.h, but am +submitting to show work done for partial credit.*/ + +using namespace std; + +#include +#include "genBST11.h" +#include + +int main() { + vector inputs = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}; + BST tree; + + for (auto i = inputs.begin(); i != inputs.end(); i++) { + tree.insert(*i); + } + + cout << "Nodes:\n"; + tree.inorder(); + + cout << "\nThe shortest branch has " << tree.shortestBranch(tree.getRoot(), 1) << " nodes.\n"; +} \ No newline at end of file diff --git a/Project11/Project11.sln b/Project11/Project11.sln new file mode 100644 index 0000000..00251bb --- /dev/null +++ b/Project11/Project11.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33801.468 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Project11", "Project11.vcxproj", "{8E37ACB6-C108-45EC-B16E-37CFB50532E3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8E37ACB6-C108-45EC-B16E-37CFB50532E3}.Debug|x64.ActiveCfg = Debug|x64 + {8E37ACB6-C108-45EC-B16E-37CFB50532E3}.Debug|x64.Build.0 = Debug|x64 + {8E37ACB6-C108-45EC-B16E-37CFB50532E3}.Debug|x86.ActiveCfg = Debug|Win32 + {8E37ACB6-C108-45EC-B16E-37CFB50532E3}.Debug|x86.Build.0 = Debug|Win32 + {8E37ACB6-C108-45EC-B16E-37CFB50532E3}.Release|x64.ActiveCfg = Release|x64 + {8E37ACB6-C108-45EC-B16E-37CFB50532E3}.Release|x64.Build.0 = Release|x64 + {8E37ACB6-C108-45EC-B16E-37CFB50532E3}.Release|x86.ActiveCfg = Release|Win32 + {8E37ACB6-C108-45EC-B16E-37CFB50532E3}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B1D76519-A8BF-4D8F-85A1-9D405A6285A6} + EndGlobalSection +EndGlobal diff --git a/Project11/Project11.vcxproj b/Project11/Project11.vcxproj new file mode 100644 index 0000000..220e615 --- /dev/null +++ b/Project11/Project11.vcxproj @@ -0,0 +1,138 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {8e37acb6-c108-45ec-b16e-37cfb50532e3} + Project11 + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/Project11/Project11.vcxproj.filters b/Project11/Project11.vcxproj.filters new file mode 100644 index 0000000..d205e2e --- /dev/null +++ b/Project11/Project11.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/Project11/genBST11.h b/Project11/genBST11.h new file mode 100644 index 0000000..d3f26e3 --- /dev/null +++ b/Project11/genBST11.h @@ -0,0 +1,471 @@ +//************************ genBST.h ************************** +// generic binary search tree + +#include +#include + +#ifndef BINARY_SEARCH_TREE +#define BINARY_SEARCH_TREE + +template +class Stack : public stack { +public: + T pop() { + T tmp = stack::pop(); + return tmp; + } +}; + +template +class Queue : public queue { +public: + T dequeue() { + T tmp = queue::pop(); + return tmp; + } + void enqueue(const T& el) { + push(el); + } +}; +template class BST; + +template +class BSTNode { +public: + BSTNode() { + left = right = 0; + } + BSTNode(const T& e, BSTNode *l = 0, BSTNode *r = 0) { + el = e; left = l; right = r; + } + T el; + BSTNode *left, *right; +}; + +template +class BST { +public: + int shallowestDepth; + BST() { + root = 0; + shallowestDepth = -1; + } + ~BST() { + clear(); + } + void clear() { + clear(root); + root = 0; + } + bool isEmpty() const { + return root == 0; + } + void preorder() { + preorder(root); + } + void inorder() { + inorder(root); + } + void postorder() { + postorder(root); + } + void insert(const T&); + void recursiveInsert(const T& el) { + recursiveInsert(root,el); + } + T* search(const T& el) const { + return search(root,el); + } + T* recursiveSearch(const T& el) const { + return recursiveSearch(root,el); + } + void deleteByCopying(BSTNode*&); + void findAndDeleteByCopying(const T&); + void deleteByMerging(BSTNode*&); + void findAndDeleteByMerging(const T&); + void iterativePreorder(); + void iterativeInorder(); + void iterativePostorder(); + void breadthFirst(); + void MorrisPreorder(); + void MorrisInorder(); + void MorrisPostorder(); + void balance(T*,int,int); + BSTNode* getRoot() { + return root; + }; + int shortestBranch(BSTNode* p, int depth); +protected: + BSTNode* root; + void clear(BSTNode*); + void recursiveInsert(BSTNode*&, const T&); + T* search(BSTNode*, const T&) const; + T* recursiveSearch(BSTNode*, const T&) const; + void preorder(BSTNode*); + void inorder(BSTNode*); + void postorder(BSTNode*); + virtual void visit(BSTNode* p) { + cout << p->el << ' '; + } +}; + +template +void BST::clear(BSTNode *p) { + if (p != 0) { + clear(p->left); + clear(p->right); + delete p; + } +} + +template +void BST::insert(const T& el) { + BSTNode *p = root, *prev = 0; + while (p != 0) { // find a place for inserting new node; + prev = p; + if (el < p->el) + p = p->left; + else p = p->right; + } + if (root == 0) // tree is empty; + root = new BSTNode(el); + else if (el < prev->el) + prev->left = new BSTNode(el); + else prev->right = new BSTNode(el); +} + +template +void BST::recursiveInsert(BSTNode*& p, const T& el) { + if (p == 0) + p = new BSTNode(el); + else if (el < p->el) + recursiveInsert(p->left, el); + else recursiveInsert(p->right,el); +} + +template +T* BST::search(BSTNode* p, const T& el) const { + while (p != 0) + if (el == p->el) + return &p->el; + else if (el < p->el) + p = p->left; + else p = p->right; + return 0; +} + +template +T* BST::recursiveSearch(BSTNode* p, const T& el) const { + if (p != 0) + if (el == p->el) + return &p->el; + else if (el < p->el) + return recursiveSearch(p->left,el); + else return recursiveSearch(p->right,el); + else return 0; +} + +template +void BST::inorder(BSTNode *p) { + if (p != 0) { + inorder(p->left); + visit(p); + inorder(p->right); + } +} + +template +void BST::preorder(BSTNode *p) { + if (p != 0) { + visit(p); + preorder(p->left); + preorder(p->right); + } +} + +template +void BST::postorder(BSTNode* p) { + if (p != 0) { + postorder(p->left); + postorder(p->right); + visit(p); + } +} + +template +void BST::deleteByCopying(BSTNode*& node) { + BSTNode *previous, *tmp = node; + if (node->right == 0) // node has no right child; + node = node->left; + else if (node->left == 0) // node has no left child; + node = node->right; + else { + tmp = node->left; // node has both children; + previous = node; // 1. + while (tmp->right != 0) { // 2. + previous = tmp; + tmp = tmp->right; + } + node->el = tmp->el; // 3. + if (previous == node) + previous->left = tmp->left; + else previous->right = tmp->left; // 4. + } + delete tmp; // 5. +} + +// findAndDeleteByCopying() searches the tree to locate the node containing +// el. If the node is located, the function DeleteByCopying() is called. + +template +void BST::findAndDeleteByCopying(const T& el) { + BSTNode *p = root, *prev = 0; + while (p != 0 && !(p->el == el)) { + prev = p; + if (el < p->el) + p = p->left; + else p = p->right; + } + if (p != 0 && p->el == el) + if (p == root) + deleteByCopying(root); + else if (prev->left == p) + deleteByCopying(prev->left); + else deleteByCopying(prev->right); + else if (root != 0) + cout << "el " << el << " is not in the tree\n"; + else cout << "the tree is empty\n"; +} + +template +void BST::deleteByMerging(BSTNode*& node) { + BSTNode *tmp = node; + if (node != 0) { + if (!node->right) // node has no right child: its left + node = node->left; // child (if any) is attached to its parent; + else if (node->left == 0) // node has no left child: its right + node = node->right; // child is attached to its parent; + else { // be ready for merging subtrees; + tmp = node->left; // 1. move left + while (tmp->right != 0)// 2. and then right as far as possible; + tmp = tmp->right; + tmp->right = // 3. establish the link between the + node->right; // the rightmost node of the left + // subtree and the right subtree; + tmp = node; // 4. + node = node->left; // 5. + } + delete tmp; // 6. + } +} + +template +void BST::findAndDeleteByMerging(const T& el) { + BSTNode *node = root, *prev = 0; + while (node != 0) { + if (node->el == el) + break; + prev = node; + if (el < node->el) + node = node->left; + else node = node->right; + } + if (node != 0 && node->el == el) + if (node == root) + deleteByMerging(root); + else if (prev->left == node) + deleteByMerging(prev->left); + else deleteByMerging(prev->right); + else if (root != 0) + cout << "el " << el << " is not in the tree\n"; + else cout << "the tree is empty\n"; +} + +template +void BST::iterativePreorder() { + Stack*> travStack; + BSTNode *p = root; + if (p != 0) { + travStack.push(p); + while (!travStack.empty()) { + p = travStack.pop(); + visit(p); + if (p->right != 0) + travStack.push(p->right); + if (p->left != 0) // left child pushed after right + travStack.push(p->left); // to be on the top of the stack; + } + } +} + +template +void BST::iterativeInorder() { + Stack*> travStack; + BSTNode *p = root; + while (p != 0) { + while (p != 0) { // stack the right child (if any) + if (p->right) // and the node itself when going + travStack.push(p->right); // to the left; + travStack.push(p); + p = p->left; + } + p = travStack.pop(); // pop a node with no left child + while (!travStack.empty() && p->right == 0) { // visit it and all nodes + visit(p); // with no right child; + p = travStack.pop(); + } + visit(p); // visit also the first node with + if (!travStack.empty()) // a right child (if any); + p = travStack.pop(); + else p = 0; + } +} + +template +void BST::iterativePostorder() { + Stack*> travStack; + BSTNode* p = root, *q = root; + while (p != 0) { + for ( ; p->left != 0; p = p->left) + travStack.push(p); + while (p->right == 0 || p->right == q) { + visit(p); + q = p; + if (travStack.empty()) + return; + p = travStack.pop(); + } + travStack.push(p); + p = p->right; + } +} + +template +void BST::breadthFirst() { + Queue*> queue; + BSTNode *p = root; + if (p != 0) { + queue.enqueue(p); + while (!queue.empty()) { + p = queue.dequeue(); + visit(p); + if (p->left != 0) + queue.enqueue(p->left); + if (p->right != 0) + queue.enqueue(p->right); + } + } +} + +template +void BST::MorrisInorder() { + BSTNode *p = root, *tmp; + while (p != 0) + if (p->left == 0) { + visit(p); + p = p->right; + } + else { + tmp = p->left; + while (tmp->right != 0 &&// go to the rightmost node of + tmp->right != p) // the left subtree or + tmp = tmp->right; // to the temporary parent of p; + if (tmp->right == 0) { // if 'true' rightmost node was + tmp->right = p; // reached, make it a temporary + p = p->left; // parent of the current root, + } + else { // else a temporary parent has been + visit(p); // found; visit node p and then cut + tmp->right = 0; // the right pointer of the current + p = p->right; // parent, whereby it ceases to be + } // a parent; + } +} + +template +void BST::MorrisPreorder() { + BSTNode *p = root, *tmp; + while (p != 0) { + if (p->left == 0) { + visit(p); + p = p->right; + } + else { + tmp = p->left; + while (tmp->right != 0 &&// go to the rightmost node of + tmp->right != p) // the left subtree or + tmp = tmp->right; // to the temporary parent of p; + if (tmp->right == 0) { // if 'true' rightmost node was + visit(p); // reached, visit the root and + tmp->right = p; // make the rightmost node a temporary + p = p->left; // parent of the current root, + } + else { // else a temporary parent has been + tmp->right = 0; // found; cut the right pointer of + p = p->right; // the current parent, whereby it ceases + } // to be a parent; + } + } +} + +template +void BST::MorrisPostorder() { + BSTNode *p = new BSTNode(), *tmp, *q, *r, *s; + p->left = root; + while (p != 0) + if (p->left == 0) + p = p->right; + else { + tmp = p->left; + while (tmp->right != 0 &&// go to the rightmost node of + tmp->right != p) // the left subtree or + tmp = tmp->right; // to the temporary parent of p; + if (tmp->right == 0) { // if 'true' rightmost node was + tmp->right = p; // reached, make it a temporary + p = p->left; // parent of the current root, + } + else { // else a temporary parent has been found; + // process nodes between p->left (included) and p (excluded) + // extended to the right in modified tree in reverse order; + // the first loop descends this chain of nodes and reverses + // right pointers; the second loop goes back, visits nodes, + // and reverses right pointers again to restore the pointers + // to their original setting; + for (q = p->left, r = q->right, s = r->right; + r != p; q = r, r = s, s = s->right) + r->right = q; + for (s = q->right; q != p->left; + q->right = r, r = q, q = s, s = s->right) + visit(q); + visit(p->left); // visit node p->left and then cut + tmp->right = 0; // the right pointer of the current + p = p->right; // parent, whereby it ceases to be + } // a parent; + } +} + +template +void BST::balance (T data[], int first, int last) { + if (first <= last) { + int middle = (first + last)/2; + insert(data[middle]); + balance(data,first,middle-1); + balance(data,middle+1,last); + } +} + +template +int BST::shortestBranch(BSTNode* p, int depth) { + int lenL = INT_MAX; + int lenR = INT_MAX; + + if (p == 0) return depth; + if (p != 0) { + lenL = shortestBranch(p->left, depth+1); + lenR = shortestBranch(p->right, depth+1); + } + + return min(lenL, lenR) + 1; +} + +#endif