diff --git a/labs/lab05/code.zip b/labs/lab05/code.zip index 7974814d5..3e7e0a601 100644 Binary files a/labs/lab05/code.zip and b/labs/lab05/code.zip differ diff --git a/labs/lab05/code/postlab/AVLNode.cpp b/labs/lab05/code/postlab/AVLNode.cpp new file mode 100644 index 000000000..43f96bb29 --- /dev/null +++ b/labs/lab05/code/postlab/AVLNode.cpp @@ -0,0 +1,34 @@ +#include "AVLNode.h" +#include + +using namespace std; + +AVLNode::AVLNode() +{ + value = ""; + left = NULL; + right = NULL; + height = 0; +} + +AVLNode::~AVLNode() +{ + delete left; + delete right; + + // to avoid crash on double deletes + left = NULL; + right = NULL; +} + +AVLNode& AVLNode::operator=(const AVLNode& other) +{ + if (this != &other) + { + this->value = other.value; + this->left = other.left; + this->right = other.right; + this->height = other.height; + } + return *this; +} \ No newline at end of file diff --git a/labs/lab05/code/postlab/AVLNode.h b/labs/lab05/code/postlab/AVLNode.h new file mode 100644 index 000000000..82e8369bb --- /dev/null +++ b/labs/lab05/code/postlab/AVLNode.h @@ -0,0 +1,19 @@ +#ifndef AVL_NODE +#define AVL_NODE + +#include + +class AVLNode { + AVLNode(); + ~AVLNode(); + AVLNode& operator=(const AVLNode& other); + + std::string value; + AVLNode* left; + AVLNode* right; + int height; + + friend class AVLTree; +}; + +#endif //AVL_NODE \ No newline at end of file diff --git a/labs/lab05/code/postlab/AVLTree.cpp b/labs/lab05/code/postlab/AVLTree.cpp index 94aaaa79f..6977c54ec 100644 --- a/labs/lab05/code/postlab/AVLTree.cpp +++ b/labs/lab05/code/postlab/AVLTree.cpp @@ -1,66 +1,94 @@ +// Feel free to edit this file and add functions as necessary #include "AVLTree.h" +#include "AVLNode.h" #include +#include +#include //for setw in postorder using namespace std; -// Implement the following -AVLNode::AVLNode() {} -AVLTree::AVLTree() {} -AVLTree::~AVLTree() {} -void AVLTree::insert(const string& x) {} -string pathTo(const string& x) const {} -bool find(const string& x) const {} -int numNodes() const {} -void balance(AVLNode*& n) {} -AVLNode* rotateLeft(AVLNode*& n) {} -AVLNode* rotateRight(AVLNode*& n) {} +// Implement at least the remaining unimplemented methods in AVLTree.h (see below method skeletons) +AVLTree::AVLTree() { } -// The following are implemented for you -// remove finds x's position in the tree and removes it, rebalancing as -// necessary. -void AVLTree::remove(const string& x) { root = remove(root, x); } +AVLTree::~AVLTree() { } -// private helper for remove to allow recursion over different nodes. returns -// an AVLNode* that is assigned to the original node. -AVLNode* AVLTree::remove(AVLNode*& n, const string& x) { - if (n == NULL) { - return NULL; +void AVLTree::insert(const string& x) { } +string AVLTree::pathTo(const string& x) const { return ""; } +bool AVLTree::find(const string& x) const { return false; } +int AVLTree::numNodes() const { return -1; } +// balance should balance only the single node it is given +void AVLTree::balance(AVLNode*& n) { } +AVLNode* AVLTree::rotateLeft(AVLNode*& n) { return NULL; } +AVLNode* AVLTree::rotateRight(AVLNode*& n) { return NULL; } + +/** The following are implemented for you: remove, max, min, and height; +remove finds x's position in the tree and removes it, rebalancing as necessary. **/ +void AVLTree::remove(const string& x) { remove(root, x); } + +/** private helper for remove to allow recursion over different nodes; +returns an AVLNode* that is assigned to the original node. **/ +bool AVLTree::remove(AVLNode*& current, const string& x) { + bool returnVal = false; + // base-case for x not present in tree + if (current == NULL) + { + returnVal = false; + } + // recursively approach base case to left + else if (x < current->value) + { + returnVal = remove(current->left, x); + } + // recursively approach base case to right + else if (x > current->value) + { + returnVal = remove(current->right, x); } - // first look for x - if (x == n->value) { - // found + // base-case for x present in tree + else + { // no children - if (n->left == NULL && n->right == NULL) { - delete n; - return NULL; + if(current->left == NULL && current->right == NULL) + { + delete current; + current = NULL; + returnVal = (current == NULL); // should be true } - // single child - if (n->left == NULL) { - return n->right; + // two children + else if (current-> left != NULL && current->right != NULL) + { + AVLNode *rLMost = current->right; + // find leftmost node in right subtree iteratively + // this value is the lowest of the values higher than our current value + // i.e. the middle-most value of this (sub)tree + while(rLMost->left != NULL) + { + rLMost = rLMost->left; + } + // replace current with rLMost (value only) + current->value = rLMost->value; + // this should immediately reach either base-case present + // with (above) no children or (below) one child, the right + // just log more recurse; runtime preserved. + returnVal = remove(current->right, rLMost->value); } - if (n->right == NULL) { - return n->left; + // one child + else + { + // if right is not null, then child is right; otherwise child is left + AVLNode* child = (current->right != NULL) ? current->right : current->left; + // replace current with child but keep height + int heightTemp = current->height; + current = child; + current->height = heightTemp; + delete child; + child = NULL; + returnVal = (child == NULL); //should be true } - // two children -- tree may become unbalanced after deleting n - string sr = min(n->right); - n->value = sr; - n->right = remove(n->right, sr); - } else if (x < n->value) { - n->left = remove(n->left, x); - } else { - n->right = remove(n->right, x); } - n->height = 1 + max(height(n->left), height(n->right)); - balance(n); - return n; -} - -// max returns the greater of two integers. -int max(int a, int b) { - if (a > b) { - return a; - } - return b; + balance(current); + return returnVal; + // recall that if this returns true, balance(root) will be called, fixing any inbalance } // min finds the string with the smallest value in a subtree. @@ -72,11 +100,37 @@ string AVLTree::min(AVLNode* node) const { return min(node->left); } -// height returns the value of the height field in a node. If the node is -// null, it returns -1. +/** height returns the value of the height field in a node. +If the node is null, it returns 0. **/ int AVLTree::height(AVLNode* node) const { if (node == NULL) { - return -1; + return 0; } return node->height; +} + +void AVLTree::print() +{ + postorder(root, 0); +} + +void AVLTree::postorder(AVLNode*& current, int indent) +{ + if(current != NULL) { + if(current->left != NULL) postorder(current->left, indent+4); + if(current->right != NULL) postorder(current->right, indent+4); + if (indent) { + std::cout << std::setw(indent) << ' '; + } + std::cout << current->value << std::endl; + } +} + +// non-member(s) +// max returns the greater of two integers. +int max(int a, int b) { + if (a > b) { + return a; + } + return b; } \ No newline at end of file diff --git a/labs/lab05/code/postlab/AVLTree.h b/labs/lab05/code/postlab/AVLTree.h index 28a05b816..ec6a6f74e 100644 --- a/labs/lab05/code/postlab/AVLTree.h +++ b/labs/lab05/code/postlab/AVLTree.h @@ -1,21 +1,13 @@ +// Feel free to edit this file and add functions as necessary + #ifndef AVL_H #define AVL_H +#include "AVLNode.h" #include using namespace std; -class AVLNode { - AVLNode(); - - string value; - AVLNode* left; - AVLNode* right; - int height; - - friend class AVLTree; -}; - class AVLTree { public: AVLTree(); @@ -36,12 +28,14 @@ class AVLTree { // numNodes returns the total number of nodes in the tree. int numNodes() const; + void print(); + private: // Declare a root node AVLNode* root; - // balance makes sure that the subtree with root n maintains the AVL tree - // property, namely that the balance factor of n is either -1, 0, or 1. + // balance should balance only the single node it is given + // that the balance factor of n is either -1, 0, or 1. void balance(AVLNode*& n); // rotateLeft performs a single rotation on node n with its left child. AVLNode* rotateLeft(AVLNode*& n); @@ -49,17 +43,22 @@ class AVLTree { AVLNode* rotateRight(AVLNode*& n); // private helper for remove to allow recursion over different nodes. returns - // an AVLNode* that is assigned to the original node. - AVLNode* remove(AVLNode*& n, const string& x); + // an true if the node is removed; false otherwise + bool remove(AVLNode*& n, const string& x); // min finds the string with the smallest value in a subtree. string min(AVLNode* node) const; // height returns the value of the height field in a node. If the node is - // null, it returns -1. + // null, it returns 0. int height(AVLNode* node) const; + // prints a subtree + // call on root for postorder of full tree + void postorder(AVLNode* ¤t, int indent); + // Any other methods you need... }; +// non-member(s) // max returns the greater of two integers. int max(int a, int b); diff --git a/labs/lab05/code/postlab/BinaryNode.cpp b/labs/lab05/code/postlab/BinaryNode.cpp new file mode 100644 index 000000000..50825dfd4 --- /dev/null +++ b/labs/lab05/code/postlab/BinaryNode.cpp @@ -0,0 +1,32 @@ +#include "BinaryNode.h" +#include + +using namespace std; + +BinaryNode::BinaryNode() +{ + value = ""; + left = NULL; + right = NULL; +} + +BinaryNode::~BinaryNode() +{ + delete left; + delete right; + + // to avoid crash on double deletes + left = NULL; + right = NULL; +} + +BinaryNode& BinaryNode::operator=(const BinaryNode& other) +{ + if (this != &other) + { + this->value = other.value; + this->left = other.left; + this->right = other.right; + } + return *this; +} \ No newline at end of file diff --git a/labs/lab05/code/postlab/BinaryNode.h b/labs/lab05/code/postlab/BinaryNode.h new file mode 100644 index 000000000..c80afc594 --- /dev/null +++ b/labs/lab05/code/postlab/BinaryNode.h @@ -0,0 +1,18 @@ +#ifndef BINARY_NODE +#define BINARY_NODE + +#include + +class BinaryNode { + BinaryNode(); + ~BinaryNode(); + BinaryNode& operator=(const BinaryNode& other); + + std::string value; + BinaryNode* left; + BinaryNode* right; + + friend class BinarySearchTree; +}; + +#endif //BINARY_NODE \ No newline at end of file diff --git a/labs/lab05/code/postlab/BinarySearchTree.cpp b/labs/lab05/code/postlab/BinarySearchTree.cpp new file mode 100644 index 000000000..39a20da3e --- /dev/null +++ b/labs/lab05/code/postlab/BinarySearchTree.cpp @@ -0,0 +1,43 @@ +// Feel free to edit this file and add functions as necessary +#include "BinaryNode.h" +#include "BinarySearchTree.h" +#include +#include +#include //for setw in postorder + +using namespace std; + +BinarySearchTree::BinarySearchTree() {} +BinarySearchTree::~BinarySearchTree() {} + +// insert finds a position for x in the tree and places it there. +void BinarySearchTree::insert(const string& x) {} +// remove finds x's position in the tree and removes it. +void BinarySearchTree::remove(const string& x) {} + +// pathTo finds x in the tree and returns a string representing the path it +// took to get there. +string BinarySearchTree::pathTo(const string& x) const { return ""; } +// find determines whether or not x exists in the tree. +bool BinarySearchTree::find(const string& x) const { return false; } +// numNodes returns the total number of nodes in the tree. +int BinarySearchTree::numNodes() const { return -1; } + +void BinarySearchTree::print() +{ + postorder(root, 0); +} + +// prints a subtree +// call on root for postorder of full tree +void BinarySearchTree::postorder(BinaryNode* ¤t, int indent) +{ + if(current != NULL) { + if(current->left) postorder(current->left, indent+4); + if(current->right) postorder(current->right, indent+4); + if (indent) { + std::cout << std::setw(indent) << ' '; + } + std::cout << current->value << std::endl; + } +} \ No newline at end of file diff --git a/labs/lab05/code/postlab/BinarySearchTree.h b/labs/lab05/code/postlab/BinarySearchTree.h index a443fd352..4920ec786 100644 --- a/labs/lab05/code/postlab/BinarySearchTree.h +++ b/labs/lab05/code/postlab/BinarySearchTree.h @@ -1,15 +1,11 @@ +// Feel free to edit this file and add functions as necessary + #ifndef BST_H #define BST_H -class BinaryNode { - BinaryNode(); - - string value; - BinaryNode* left; - BinaryNode* right; +#include "BinaryNode.h" - friend class BinarySearchTree; -}; +using namespace std; class BinarySearchTree { public: @@ -28,12 +24,19 @@ class BinarySearchTree { bool find(const string& x) const; // numNodes returns the total number of nodes in the tree. int numNodes() const; + + void print(); private: // Declare a root node BinaryNode* root; + // prints a subtree + // call on root for postorder of full tree + void postorder(BinaryNode* ¤t, int indent); + // Any other methods you need... }; + #endif \ No newline at end of file diff --git a/labs/lab05/index.md b/labs/lab05/index.md index b938f57ee..0f109edb9 100644 --- a/labs/lab05/index.md +++ b/labs/lab05/index.md @@ -41,8 +41,8 @@ Procedure 1. For this lab, you will implement a Binary search tree, an AVL tree, and submit a brief lab report electronically via the submission system. 2. Your report must be in PDF format! See the [How to convert a file to PDF](../../docs/convert_to_pdf.html) page for details. -3. Files to download: [BinarySearchTree.h](code/postlab/BinarySearchTree.h.html) ([src](code/postlab/BinarySearchTree.h)), [AVLTree.h](code/postlab/AVLTree.h.html) ([src](code/postlab/AVLTree.h)), [AVLTree.cpp](code/postlab/AVLTree.cpp.html) ([src](code/postlab/AVLTree.cpp)), [TreePathTest.cpp](code/postlab/TreePathTest.cpp.html) ([src](code/postlab/TreePathTest.cpp)), [testfile1.txt](code/postlab/testfile1.txt), [testfile2.txt](code/postlab/testfile2.txt), [testfile3.txt](code/postlab/testfile3.txt). These files are contained in the postlab/ directory of the [code.zip](code.zip) file. -4. Files to submit: AVLTree.h, BinarySearchTree.h, TreePathTest.cpp, Makefile, any other files needed to make your code compile (files such as AVLTree.cpp, BinarySearchTree.cpp, etc...), analysis.pdf (see the post-lab section for formatting details) +3. Files to download: [BinaryNode.h](code/postlab/BinaryNode.h.html) ([src](code/postlab/BinaryNode.h)), [BinaryNode.cpp](code/postlab/BinaryNode.cpp.html) ([src](code/postlab/BinaryNode.cpp)), [BinarySearchTree.h](code/postlab/BinarySearchTree.h.html) ([src](code/postlab/BinarySearchTree.h)), [BinarySearchTree.cpp](code/postlab/BinarySearchTree.cpp.html) ([src](code/postlab/BinarySearchTree.cpp)), [AVLNode.h](code/postlab/AVLNode.h.html) ([src](code/postlab/AVLNode.h)), [AVLNode.cpp](code/postlab/AVLNode.cpp.html) ([src](code/postlab/AVLNode.cpp)), [AVLTree.h](code/postlab/AVLNode.h.html), ([src](code/postlab/AVLTree.h)), [AVLTree.cpp](code/postlab/AVLTree.cpp.html) ([src](code/postlab/AVLTree.cpp)), [TreePathTest.cpp](code/postlab/TreePathTest.cpp.html) ([src](code/postlab/TreePathTest.cpp)), [testfile1.txt](code/postlab/testfile1.txt), [testfile2.txt](code/postlab/testfile2.txt), [testfile3.txt](code/postlab/testfile3.txt). These files are contained in the postlab/ directory of the [code.zip](code.zip) file. +4. Files to submit: AVLTree.h, BinarySearchTree.h, TreePathTest.cpp, Makefile, any other files needed to make your code compile (files such as AVLTree.cpp, BinarySearchTree.cpp, Node.h's and .cpp's, etc...), analysis.pdf (see the post-lab section for formatting details) ------------------------------------------------------------