Question Description
Hi Buddy,
i was wondering if you could do this assignment ?
For this project, we will be implementing functions of an AVL tree. The tree will act as a BST with integer keys (which are Comparable types) and must maintain the AVL nature as you insert and delete nodes. This archive includes a working AVL tree implementation, but does not do several things:
- Do inserts into the tree with integers
- You’ll see the vector inserts used in the test code, that’s calling your code
- Maintain the heights of nodes after an insert
- Check heights of subtrees and do rotations as appropriate to keep the tree balanced
- Search the tree to see if it contains a given node
- Return the size (node count) in the tree
- Remove a node when given a key
- Return whether the tree is empty or not
- Print out the tree in pre-, in-, and post- order
- Implement the makeEmpty function for the destructor
Your assignment is to add these features to the provided code. There are several notes in AvlTree.h about where you need to fill in the stubbed functions or replace/update the ones that are there, notably in insert, remove, contains, height, pre-, in-, post- print functions. Any function that has “TODO” in the comments is one that you’ll need to look at. Feel free to add any additional private member functions to AvlTree.h as you see fit.
The starter code compiles and runs on the EECS SSH servers just fine. You can use that as a starting point for you own work. You will need to compile it using the provided Makefile. I have committed the project to your Git repository under the “PA1” branch.
This makefile has one extra target for a big fuzzing test. You’ll need to do the full fuzzing test once you have both insert and remove implemented by executing ‘make bigtest’. The fuzzing test will do many random inserts and ⅓ as many deletes. This kind of test is called fuzzing because it’s trying many random input values to a given algorithm to see if anything breaks. In this case, we’ll make a tree of up to 3000 nodes and just seeing if it breaks.
Expected Output
Your code must compile on the EECS servers, though you can do your development on other systems and do final tests on the EECS machines if you like.
Your program will be tested first by doing this series of commands:
- make
- make test
- make bigtest
- make clean
Then we’ll inspect the source code for quality. Structure, indentation, naming, commenting, cleanliness, consistency.
Grading Criteria
Your assignment will be judged by the following criteria:
- [80] Code operational success. Your code compiles, executes, and passes the tests.
- [10] Your code is well documented and generally easy to read.
- [10] Your program intelligently uses classes when appropriate and generally conforms to good OOP design (i.e. everything isn't slapped into main).
the files:
Avltree.h
| #ifndef AVL_TREE_H | |
| #define AVL_TREE_H | |
| #include "dsexceptions.h" | |
| #include <iostream> // For NULL | |
| #include <vector> | |
| #include <algorithm> // For max() function | |
| using namespace std; | |
| // AvlTree class | |
| // | |
| // CONSTRUCTION: with ITEM_NOT_FOUND object used to signal failed finds | |
| // | |
| // ******************PUBLIC OPERATIONS********************* | |
| // int size( ) –> Quantity of elements in tree | |
| // int height( ) –> Height of the tree (null == -1) | |
| // void insert( x ) –> Insert x | |
| // void insert( vector<T> ) –> Insert whole vector of values | |
| // void remove( x ) –> Remove x (unimplemented) | |
| // bool contains( x ) –> Return true if x is present | |
| // Comparable findMin( ) –> Return smallest item | |
| // Comparable findMax( ) –> Return largest item | |
| // boolean isEmpty( ) –> Return true if empty; else false | |
| // void makeEmpty( ) –> Remove all items | |
| // void printTree( ) –> Print tree in sorted (in) order | |
| // void printPreOrder( ) –> Print tree in pre order | |
| // void printPostOrder( ) –> Print tree in post order | |
| // void printInOrder( ) –> Print tree in *in* order | |
| // ******************ERRORS******************************** | |
| // Throws UnderflowException as warranted | |
| template <typename Comparable> | |
| class AvlTree | |
| { | |
| public: | |
| AvlTree( ) : root( NULL ) | |
| { } | |
| AvlTree( const AvlTree & rhs ) : root( NULL ) | |
| { | |
| *this = rhs; | |
| } | |
| ~AvlTree( ) | |
| { | |
| cout << " [!] Destructor called." << endl; | |
| makeEmpty( ); | |
| } | |
| /** | |
| * Find the smallest item in the tree. | |
| * Throw UnderflowException if empty. | |
| */ | |
| const Comparable & findMin( ) const | |
| { | |
| if( isEmpty( ) ) | |
| throw UnderflowException( ); | |
| return findMin( root )->element; | |
| } | |
| /** | |
| * Find the largest item in the tree. | |
| * Throw UnderflowException if empty. | |
| */ | |
| const Comparable & findMax( ) const | |
| { | |
| if( isEmpty( ) ) | |
| throw UnderflowException( ); | |
| return findMax( root )->element; | |
| } | |
| /** | |
| * Returns true if x is found in the tree. | |
| */ | |
| bool contains( const Comparable & x ) const | |
| { | |
| return contains( x, root ); | |
| } | |
| /** | |
| * Test if the tree is logically empty. | |
| * Return true if empty, false otherwise. | |
| * TODO: Implement | |
| */ | |
| bool isEmpty( ) const | |
| { | |
| return false; // so not correct | |
| } | |
| /** | |
| * Return number of elements in tree. | |
| */ | |
| int size( ) | |
| { | |
| return size( root ); | |
| } | |
| /** | |
| * Return height of tree. | |
| * Null nodes are height -1 | |
| */ | |
| int height( ) | |
| { | |
| return height( root ); | |
| } | |
| /** | |
| * Print the tree contents in sorted order. | |
| */ | |
| void printTree( ) const | |
| { | |
| if( isEmpty( ) ) | |
| cout << "Empty tree" << endl; | |
| else | |
| printInOrder( root ); | |
| } | |
| /** | |
| * Print the tree contents in sorted order. | |
| */ | |
| void printInOrder( ) const | |
| { | |
| if( isEmpty( ) ) | |
| cout << "Empty tree" << endl; | |
| else | |
| printInOrder( root ); | |
| } | |
| /** | |
| * Print the tree contents in pre order. | |
| */ | |
| void printPreOrder( ) const | |
| { | |
| if( isEmpty( ) ) | |
| cout << "Empty tree" << endl; | |
| else | |
| printPreOrder( root ); | |
| } | |
| /** | |
| * Print the tree contents in post order. | |
| */ | |
| void printPostOrder( ) const | |
| { | |
| if( isEmpty( ) ) | |
| cout << "Empty tree" << endl; | |
| else | |
| printPostOrder( root ); | |
| } | |
| /** | |
| * Make the tree logically empty. | |
| */ | |
| void makeEmpty( ) | |
| { | |
| makeEmpty( root ); | |
| } | |
| /** | |
| * Insert x into the tree; duplicates are ignored. | |
| */ | |
| void insert( const Comparable & x ) | |
| { | |
| insert( x, root ); | |
| } | |
| /** | |
| * Insert vector of x's into the tree; duplicates are ignored. | |
| */ | |
| void insert( vector<Comparable> vals) | |
| { | |
| for( auto x : vals ) { | |
| insert( x, root ); | |
| } | |
| } | |
| /** | |
| * Remove x from the tree. Nothing is done if x is not found. | |
| * TODO: Implement | |
| */ | |
| void remove( const Comparable & x ) | |
| { | |
| //cout << "[!] Sorry, remove unimplemented; " << x << " still present" << endl; | |
| } | |
| /** | |
| * Deep copy. – or copy assignment operator | |
| * Will be in part II | |
| */ | |
| const AvlTree & operator=( const AvlTree & rhs ) | |
| { | |
| cout << " [!] Copy *assignment* operator called." << endl; | |
| return *this; | |
| } | |
| /*****************************************************************************/ | |
| private: | |
| struct AvlNode | |
| { | |
| Comparable element; | |
| AvlNode *left; | |
| AvlNode *right; | |
| int height; | |
| AvlNode( const Comparable & theElement, AvlNode *lt, | |
| AvlNode *rt, int h = 0 ) | |
| : element( theElement ), left( lt ), right( rt ), height( h ) { } | |
| }; | |
| AvlNode *root; | |
| /** | |
| * Internal method to count nodes in tree | |
| * TODO: Implement | |
| */ | |
| int size( AvlNode * & t ) | |
| { | |
| return(-1); | |
| } | |
| /** | |
| * Internal method to insert into a subtree. | |
| * x is the item to insert. | |
| * t is the node that roots the subtree. | |
| * Set the new root of the subtree. | |
| * TODO: Implement | |
| */ | |
| void insert( const Comparable & x, AvlNode * & t ) | |
| { | |
| // Definitely to do | |
| } | |
| /** | |
| * Internal method to find the smallest item in a subtree t. | |
| * Return node containing the smallest item. | |
| * You'll need this for deletes | |
| * TODO: Implement | |
| */ | |
| AvlNode * findMin( AvlNode *t ) const | |
| { | |
| return t; // placeholder | |
| } | |
| /** | |
| * Internal method to find the largest item in a subtree t. | |
| * Return node containing the largest item. | |
| * TODO: Implement | |
| */ | |
| AvlNode * findMax( AvlNode *t ) const | |
| { | |
| return t; // placeholder | |
| } | |
| /** | |
| * Internal method to test if an item is in a subtree. | |
| * x is item to search for. | |
| * t is the node that roots the tree. | |
| * TODO: Implement | |
| */ | |
| bool contains( const Comparable & x, AvlNode *t ) const | |
| { | |
| return false; // Lolz | |
| } | |
| /******************************************************/ | |
| /** | |
| * Internal method to make subtree empty. | |
| * TODO: implement for destructor | |
| * | |
| */ | |
| void makeEmpty( AvlNode * & t ) | |
| { | |
| cout << " [!] makeEmpty not implemented " << endl; | |
| } | |
| /** | |
| * Internal method to print a subtree rooted at t in sorted order. | |
| * TODO: Implement | |
| */ | |
| void printInOrder( AvlNode *t ) const | |
| { | |
| cout << " [!] Printing In Order"; | |
| } | |
| /** | |
| * Internal method to print a subtree rooted at t in pre order. | |
| * TODO: Implement | |
| */ | |
| void printPreOrder( AvlNode *t ) const | |
| { | |
| cout << " [!] Printing Pre order"; | |
| } | |
| /** | |
| * Internal method to print a subtree rooted at t in post order. | |
| * TODO: Implement | |
| */ | |
| void printPostOrder( AvlNode *t ) const | |
| { | |
| cout << " [!] Printing post order"; | |
| } | |
| /** | |
| * Internal method to clone subtree. | |
| */ | |
| AvlNode * clone( AvlNode *t ) const | |
| { | |
| if( t == NULL ) | |
| return NULL; | |
| else | |
| return new AvlNode( t->element, clone( t->left ), clone( t->right ), t->height ); | |
| } | |
| // Avl manipulations | |
| /** | |
| * Return the height of node t or -1 if NULL. | |
| * TODO: Implement | |
| */ | |
| int height( AvlNode *t ) const | |
| { | |
| return(-2); // DEFINITELY not true | |
| } | |
| int max( int lhs, int rhs ) const | |
| { | |
| return lhs > rhs ? lhs : rhs; | |
| } | |
| /** | |
| * Rotate binary tree node with left child. | |
| * For AVL trees, this is a single rotation for case 1. | |
| * Update heights, then set new root. | |
| * TODO: Implement | |
| */ | |
| void rotateWithLeftChild( AvlNode * & k2 ) | |
| { | |
| } | |
| /** | |
| * Rotate binary tree node with right child. | |
| * For AVL trees, this is a single rotation for case 4. | |
| * Update heights, then set new root. | |
| * TODO: Implement | |
| */ | |
| void rotateWithRightChild( AvlNode * & k1 ) | |
| { | |
| } | |
| /** | |
| * Double rotate binary tree node: first left child. | |
| * with its right child; then node k3 with new left child. | |
| * For AVL trees, this is a double rotation for case 2. | |
| * Update heights, then set new root. | |
| * TODO: Implement | |
| */ | |
| void doubleWithLeftChild( AvlNode * & k3 ) | |
| { | |
| } | |
| /** | |
| * Double rotate binary tree node: first right child. | |
| * with its left child; then node k1 with new right child. | |
| * For AVL trees, this is a double rotation for case 3. | |
| * Update heights, then set new root. | |
| * TODO: Implement | |
| */ | |
| void doubleWithRightChild( AvlNode * & k1 ) | |
| { | |
| } | |
| }; | |
| #endif |
AvlTreeTesting.h
| #include "AvlTree.h" | |
| #include <iostream> | |
| #include <string.h> | |
| /*****************************************************************************/ | |
| // Do lots of random inserts and deletes. This is a fuzzing test | |
| void test_BigTreeFuzzing() { | |
| /* BIGGER test of your AVL tree! */ | |
| cout << " [t] Big Tree Fuzzing test."; | |
| vector<int> incVals; | |
| AvlTree<int> bigTree; | |
| srand (time(NULL)); | |
| for( int i = 0; i < 3000; i++ ) { | |
| int newVal = rand() % 900000; // Generate new integer to insert into tree | |
| bool skip = false; | |
| for( int j = 0; j < incVals.size(); j++ ){ // Very dumb search! | |
| if( incVals[j] == newVal ){ | |
| skip = true; | |
| j = incVals.size(); | |
| } | |
| } | |
| if( !skip ){ | |
| bigTree.insert(newVal); | |
| incVals.push_back(newVal); | |
| } | |
| if( i % 3 == 0 ){ // Delete a random element every 3 inserts | |
| int remIndex = rand() % incVals.size(); | |
| bigTree.remove( incVals[remIndex] ); | |
| incVals.erase(incVals.begin() + remIndex); | |
| } | |
| } | |
| cout << " – fuzzing test complete. " << endl; | |
| } | |
| void test_empty() { | |
| AvlTree<int> myTree; | |
| cout << " [t] Testing isEmpty() interface"; | |
| if( myTree.isEmpty() ) { | |
| cout << " – Pass" << endl; | |
| } else { | |
| cout << " – Fail" << endl; | |
| } | |
| } | |
| void test_size() { | |
| AvlTree<int> myTree; | |
| cout << " [t] Testing size() interface…" << endl;; | |
| cout << " [t] size() when empty: " << myTree.size() << " – "; | |
| (myTree.size() == 0) ? cout << "Pass" : cout << "Fail"; | |
| cout << endl; | |
| vector<int> vals = { 10, 5, 23, 3, 7, 30, 1 }; // Give us some data! | |
| myTree.insert( vals ); | |
| cout << " [t] size() with " << vals.size() << " values: " << myTree.size() << " – "; | |
| (vals.size() == myTree.size()) ? cout << "Pass" : cout << "Fail"; | |
| cout << endl; | |
| myTree.remove( 10 ); // Remove the root, what about now? | |
| cout << " [t] size() with " << vals.size() – 1<< " values: " << myTree.size() << " – "; | |
| (vals.size() – 1 == myTree.size()) ? cout << "Pass" : cout << "Fail"; | |
| cout << endl; | |
| } | |
| void test_height() { | |
| AvlTree<int> myTree; | |
| vector<int> vals = { 10, 5, 23, 3, 7, 30, 1 }; // Give us some data! | |
| cout << " [t] Testing tree heights" << endl; | |
| cout << " [t] Height of empty: " << myTree.height() << " – "; | |
| (myTree.height() == –1) ? cout << "Pass" : cout << "Fail"; cout << endl; | |
| myTree.insert(vals); | |
| cout << " [t] Height of filled (3): " << myTree.height() << " – "; | |
| (myTree.height() == 3) ? cout << "Pass" : cout << "Fail"; cout << endl; | |
| } | |
| void test_prints() { | |
| AvlTree<int> myTree; | |
| vector<int> vals = { 10, 5, 23, 3, 7, 30, 1 }; // Give us some data! | |
| myTree.insert(vals); | |
| cout << " [t] Testing tree print orders: " << endl; | |
| cout << " [t] In Order: t"; | |
| myTree.printInOrder(); | |
| cout << endl; | |
| cout << " [t] Pre Order:t"; | |
| myTree.printPreOrder(); | |
| cout << endl; | |
| cout << " [t] Post Order:t"; | |
| myTree.printPostOrder(); | |
| cout << endl; | |
| } | |
| void test_insert() | |
| { | |
| AvlTree<int> myTree; | |
| cout << " [t] Testing tree basic inserts: " << endl; | |
| myTree.insert(20); | |
| myTree.insert(10); | |
| myTree.insert(5); // Forces right rotate | |
| cout << " [t] Should be: t10 5 20" << endl; | |
| cout << " [t] Pre Order: t"; | |
| myTree.printPreOrder(); | |
| cout << endl; | |
| myTree.insert(30); | |
| myTree.insert(40); // Forces left rotate | |
| cout << " [t] Should be: t10 5 30 20 40" << endl; | |
| cout << " [t] Pre Order: t"; | |
| myTree.printPreOrder(); | |
| cout << endl; | |
| myTree.insert(15); // Forces Right-Left double rotate | |
| cout << " [t] Should be: t20 10 5 15 30 40" << endl; | |
| cout << " [t] Pre Order: t"; | |
| myTree.printPreOrder(); | |
| cout << endl; | |
| myTree.insert(13); | |
| myTree.insert(14); // Forces Left-Right double rotate | |
| cout << " [t] Should be: t20 10 5 14 13 15 30 40" << endl; | |
| cout << " [t] Pre Order: t"; | |
| myTree.printPreOrder(); | |
| cout << endl; | |
| } | |
| void test_contains() { | |
| AvlTree<int> myTree; | |
| vector<int> vals = { 10, 5, 23, 3, 7, 30, 1 }; // Give us some data! | |
| myTree.insert( vals ); | |
| cout << " [t] Testing contains:" << endl; | |
| cout << " [t] Searching for: 7 (is in tree)"; | |
| (myTree.contains(7)) ? cout << " – pass" : cout << " – fail"; cout << endl; | |
| cout << " [t] Searching for: 15 (not in tree)"; | |
| (!myTree.contains(15)) ? cout << " – pass" : cout << " – fail"; cout << endl; | |
| } | |
| /** | |
| * Testing the remove() function | |
| */ | |
| void test_remove() { | |
| AvlTree<int> myTree; | |
| vector<int> vals = { 10, 5, 23, 3, 7, 30, 1 }; // Give us some data! | |
| myTree.insert( vals ); | |
| cout << " [t] Testing remove():" << endl; | |
| cout << " [t] Searching for: 7 (is in tree)"; | |
| (myTree.contains(7)) ? cout << " – pass" : cout << " – fail"; cout << endl; | |
| cout << " [x] Removing 7 from tree. " << endl; | |
| myTree.remove(7); | |
| cout << " [t] Searching for: 7 (is not in tree)"; | |
| (!myTree.contains(7)) ? cout << " – pass" : cout << " – fail"; cout << endl; | |
| } | |
| /* | |
| * Testing features of your AVL Tree implementation | |
| */ | |
| int avlTreeTests( bool fuzzing ) | |
| { | |
| cout << " [x] Starting AVL tree test. " << endl; | |
| test_empty(); // empty() interface working? | |
| test_size(); // size() interface working properly? | |
| test_height(); // height() working properly? | |
| test_prints(); // Print: preorder, postorder, inorder, levelorder | |
| test_insert(); // Insert test | |
| test_contains(); // Testing contains interface | |
| test_remove(); // Test of removing nodes via remove() | |
| if( fuzzing ) test_BigTreeFuzzing(); //Big tree fuzzing test | |
| return(0); | |
| } |
Makefile
| # Variables | |
| GPP = g++ | |
| CFLAGS = -g -std=c++11 | |
| RM = rm -f | |
| BINNAME = avltree | |
| # Shell gives make a full user environment | |
| # Adding this to PATH will find the newer g++ compiler on the EECS servers. | |
| SHELL := /bin/bash | |
| PATH := /opt/rh/devtoolset-3/root/usr/bin/:$(PATH) | |
| # Default is what happenes when you call make with no options | |
| # In this case, it requires that 'all' is completed | |
| default: all | |
| # All is the normal default for most Makefiles | |
| # In this case, it requires that build is completed | |
| all: build | |
| # build depends upon *.cpp, then runs the command: | |
| # g++ -g -std=c++0x -o bigFiveList | |
| build: main.cpp | |
| $(GPP) $(CFLAGS) -o $(BINNAME) main.cpp | |
| run: build | |
| ./$(BINNAME) | |
| test: build | |
| ./$(BINNAME) –test | |
| bigtest: build | |
| ./$(BINNAME) –test –withFuzzing | |
| # If you call "make clean" it will remove the built program | |
| # rm -f HelloWorld | |
| clean veryclean: | |
| $(RM) $(BINNAME) |
dsexception.h
| #ifndef DS_EXCEPTIONS_H | |
| #define DS_EXCEPTIONS_H | |
| class UnderflowException { }; | |
| class IllegalArgumentException { }; | |
| class ArrayIndexOutOfBoundsException { }; | |
| class IteratorOutOfBoundsException { }; | |
| class IteratorMismatchException { }; | |
| class IteratorUninitializedException { }; | |
| #endif |
main.cpp
| #include <iostream> | |
| #include <cstdlib> | |
| #include <string.h> | |
| #include "AvlTree.h" | |
| #include "AvlTreeTesting.h" | |
| using namespace std; | |
| /* | |
| * Main function for test or use | |
| */ | |
| int main( int argc, char* argv[] ) | |
| { | |
| int retState = 0; | |
| // Note: If you call this program like this: ./avltree –test | |
| // it will call the test function | |
| bool is_test_mode = false; | |
| bool is_fuzzing_test_mode = false; | |
| for( int i = 0; i < argc; i++ ) { | |
| if( !strcmp(argv[i], "–test" ) ) { | |
| cout << " [x] Enabling test mode. " << endl; | |
| is_test_mode = true; | |
| } else if( !strcmp(argv[i], "–withFuzzing" ) ) { | |
| cout << " [x] Enabling fuzzing tests. " << endl; | |
| is_fuzzing_test_mode = true; | |
| } | |
| } | |
| if( is_test_mode || is_fuzzing_test_mode ) { | |
| retState = avlTreeTests( is_fuzzing_test_mode ); // From AvlTreeTesting.h | |
| } | |
| else | |
| { | |
| cout << " [x] Running in normal mode. " << endl; | |
| cout << " [!] Nothing to do in normal mode so here's a helicopter: " << endl; | |
| cout << " ___.___n (_]===*n o 0" << endl; | |
| cout << endl << " You should probably run 'make test' to test your program. " << endl; | |
| cout << " This program also has a fuzzing test with 'make bigtest' to test your program. " << endl; | |
| } | |
| cout << " [x] Program complete. " << endl; | |
| return(retState); | |
| } |
Our website has a team of professional writers who can help you write any of your homework. They will write your papers from scratch. We also have a team of editors just to make sure all papers are of HIGH QUALITY & PLAGIARISM FREE. To make an Order you only need to click Ask A Question and we will direct you to our Order Page at WriteDemy. Then fill Our Order Form with all your assignment instructions. Select your deadline and pay for your paper. You will get it few hours before your set deadline.
Fill in all the assignment paper details that are required in the order form with the standard information being the page count, deadline, academic level and type of paper. It is advisable to have this information at hand so that you can quickly fill in the necessary information needed in the form for the essay writer to be immediately assigned to your writing project. Make payment for the custom essay order to enable us to assign a suitable writer to your order. Payments are made through Paypal on a secured billing page. Finally, sit back and relax.
About Writedemy
We are a professional paper writing website. If you have searched a question and bumped into our website just know you are in the right place to get help in your coursework. We offer HIGH QUALITY & PLAGIARISM FREE Papers.
How It Works
To make an Order you only need to click on “Place Order” and we will direct you to our Order Page. Fill Our Order Form with all your assignment instructions. Select your deadline and pay for your paper. You will get it few hours before your set deadline.
Are there Discounts?
All new clients are eligible for 20% off in their first Order. Our payment method is safe and secure.