PROGRAM 4
// PROGRAM: PROGRAM4.CPP AUTHOR: ANTHONY F. ORTIZ // (NOTE: TURNED IN CLOSED HASH TABLE PROGRAM.) #include #include #include #include // OUTFILE. ofstream OUTFILE; // DELCARATION OF TREE NODE CLASS. template class TREE_NODE { protected: // KEY INFORMATION. ETYPE ELEMENT; // RIGHT AND LEFT POINTERS. TREE_NODE * LEFT; TREE_NODE * RIGHT; // TREE_NODE CONSTRUCTOR. TREE_NODE (ETYPE E = 0, TREE_NODE * L = 0, TREE_NODE * R = 0) : ELEMENT (E), LEFT (L), RIGHT (R) {} // HEIGHT OF A NODE IN A TREE. friend int HEIGHT (TREE_NODE * T); // A CLASS CALLED BINARY_SEARCH_TREE WILL USE THE TREE NODE // CLASS. friend class BINARY_SEARCH_TREE ; }; // DELCARATION OF BINARY SEARCH TREE CLASS. template class BINARY_SEARCH_TREE { // THESE PROCEDURES WILL BE CALLED BY THE PUBLIC ONES OF THE SAME // NAME. protected: // MAKE AN EMPTY TREE. void MAKE_EMPTY (TREE_NODE * & T); // INSERT AN ELEMENT INTO A TREE. void INSERT (const ETYPE & X, TREE_NODE * & T); // REMOVE AN ELEMENT FROM A TREE. void REMOVE (const ETYPE & X, TREE_NODE * & T); // PRINT THE TREE USING A INORDER TRAVERSAL. // THIS WILL PRINT IT IN SORTED ORDER. void PRINT_TREE (TREE_NODE * T) const; // COPY A TREE. TREE_NODE * COPY (const TREE_NODE * T); // FIND AN ELEMENT IN THE TREE. TREE_NODE * FIND (const ETYPE & X, TREE_NODE * T) const; // FIND THE MINIMUM ELEMENT IN THE TREE. TREE_NODE * FIND_MIN (TREE_NODE * T) const; // FIND THE MAXIMUM ELEMENT IN THE TREE. TREE_NODE * FIND_MAX (TREE_NODE * T) const; // ROOT OF THE TREE. TREE_NODE * ROOT; // THE LAST FIND IN A FIND ROUTINE. TREE_NODE * LAST_FIND; // THESE PROCEDURES WILL CALL THE PROTECTED ONES. public: // CONSTRUCTORS. BINARY_SEARCH_TREE () : ROOT (0), LAST_FIND (0) {} // ERROR MESSAGE WHEN PASS BY VALUE. BINARY_SEARCH_TREE (BINARY_SEARCH_TREE & VALUE) {OUTFILE << "TREE PASSED BY VALUE."; operator = (VALUE);} // DESTRUCTOR. virtual ~BINARY_SEARCH_TREE () {MAKE_EMPTY (ROOT); ROOT = LAST_FIND = 0;} // OPERATORS. // COPY A TREE. const BINARY_SEARCH_TREE & operator = (const BINARY_SEARCH_TREE & VALUE); // RETURN A TREE ELEMENT. ETYPE operator () () const {return LAST_FIND != 0 ? LAST_FIND -> ELEMENT : 0;} // MEMBER FUNCTIONS. // CALL MAKE_EMPTY AND ASSIGN 0 TO ROOT AND LAST FIND. void MAKE_EMPTY () {MAKE_EMPTY (ROOT); ROOT = LAST_FIND = 0;} // CALL PRINT_TREE. void PRINT_TREE () const {PRINT_TREE (ROOT);} // ASSIGN LAST_FIND TO THE FUNCTION FIND. virtual int FIND (const ETYPE & X) {return int (LAST_FIND = FIND (X, ROOT));} // ASSIGN LAST_FIND TO THE FUNCTION FIND_MIN. virtual int FIND_MIN () {return int (LAST_FIND = FIND_MIN (ROOT));} // ASSIGN LAST_FIND TO THE FUNCTION FIND_MAX. virtual int FIND_MAX () {return int (LAST_FIND = FIND_MAX (ROOT));} // CALL INSERT. virtual void INSERT (const ETYPE & X) {INSERT (X, ROOT);} // CALL REMOVE. virtual void REMOVE (const ETYPE & X) {REMOVE (X, ROOT);} }; // THIS IS THE IMPLEMENTATION OF A BINARY SEARCH TREE CLASS. // COPY A TREE USING '=' OPERATOR. template const BINARY_SEARCH_TREE & BINARY_SEARCH_TREE :: operator = (const BINARY_SEARCH_TREE & VALUE) { if (this != & VALUE) { MAKE_EMPTY (ROOT); ROOT = COPY (VALUE.ROOT); LAST_FIND = ROOT; } return * this; } // COPY THE TREE. template TREE_NODE * BINARY_SEARCH_TREE :: COPY (const TREE_NODE * T) { if (T != 0) return new TREE_NODE (T -> ELEMENT, COPY (T -> LEFT), COPY (T -> RIGHT)); else return 0; } // MAKE THE TREE EMPTY. template void BINARY_SEARCH_TREE :: MAKE_EMPTY (TREE_NODE * & T) { if (T != 0) { MAKE_EMPTY (T -> LEFT); MAKE_EMPTY (T -> RIGHT); delete T; T = 0; } } // FIND AN ELEMENT IN THE TREE. template TREE_NODE * BINARY_SEARCH_TREE :: FIND (const ETYPE & X, TREE_NODE * T) const { if (T == 0) return 0; else if (X < T -> ELEMENT) return FIND (X, T -> LEFT); else if (X > T -> ELEMENT) return FIND (X, T -> RIGHT); else return T; } // FIND THE MINIMUM ELEMENT IN THE TREE. template TREE_NODE * BINARY_SEARCH_TREE :: FIND_MIN (TREE_NODE * T) const { if (T == 0) return 0; else if (T -> LEFT == 0) return T; else return FIND_MIN (T -> LEFT); } // FIND THE MAXIMUM ELEMENT OF A TREE. template TREE_NODE * BINARY_SEARCH_TREE :: FIND_MAX (TREE_NODE * T) const { if (T == 0) return 0; else if (T -> RIGHT == 0) return T; else return FIND_MAX (T -> RIGHT); } // INSERT AN ELEMENT INTO THE TREE. template void BINARY_SEARCH_TREE :: INSERT (const ETYPE & X, TREE_NODE * & T) { if (T == 0) { T = new TREE_NODE (X); if (T == 0) OUTFILE << "OUT OF SPACE."; } else if (X < T -> ELEMENT) INSERT (X, T -> LEFT); else if (X > T -> ELEMENT) INSERT (X, T -> RIGHT); // ELSE X IS IN THE TREE ALREADY AND DO NOTHING. } // REMOVE AN ELEMENT FROM THE TREE. template void BINARY_SEARCH_TREE :: REMOVE (const ETYPE & X, TREE_NODE * & T) { TREE_NODE * TMP_CELL; if (T == 0) OUTFILE << "ELEMENT NOT FOUND."; else if (X < T -> ELEMENT) // GO LEFT. REMOVE (X, T -> LEFT); else if (X > T -> ELEMENT) // GO RIGHT. REMOVE (X, T -> RIGHT); else // FOUND ELEMENT TO BE REMOVED. if (T -> LEFT != 0 && T -> RIGHT != 0) // TWO CHILDREN. { // REPLACE WITH SMALLEST IN RIGHT SUBTREE. TMP_CELL = FIND_MIN (T -> RIGHT); T -> ELEMENT = TMP_CELL -> ELEMENT; REMOVE (T -> ELEMENT, T -> RIGHT); } else // ONE OR ZERO CHILD. { TMP_CELL = T; if (T -> LEFT == 0) // ONLY A RIGHT CHILD. T = T -> RIGHT; else if (T -> RIGHT == 0) // ONLY A LEFT CHILD. T = T -> LEFT; delete TMP_CELL; } } // PRINT THE TREE USING AN INORDER TRAVERSAL. // THIS WILL PRINT IT IN SORTED ORDER. template void BINARY_SEARCH_TREE :: PRINT_TREE (TREE_NODE * T) const { static int COUNT; if (T != 0) { PRINT_TREE (T -> LEFT); OUTFILE << HEIGHT (T) << " " << T -> ELEMENT << " "; COUNT = COUNT + 1; if (COUNT % 8 == 0) { OUTFILE << "\n"; COUNT = 0; } PRINT_TREE (T -> RIGHT); } } // CALCULATE THE HEIGHT OF A NODE. template int HEIGHT (TREE_NODE * T) { if (T == 0) return -1; else return 1 + MAX (HEIGHT (T -> LEFT), HEIGHT (T -> RIGHT)); } // THIS IS THE DECLARATION FOR A AVL NODE CLASS. template class AVL_NODE : public TREE_NODE { private: // HEIGHT OF THE AVL TREE NODE. int HEIGHT; // CALCULATE THE HEIGHT OF A AVL NODE TREE. friend int NODE_HT (AVL_NODE * P) {return P ? P -> HEIGHT : -1;} friend int NODE_HT (TREE_NODE * P) {return NODE_HT ((AVL_NODE *) (P));} friend void CALCULATE_HEIGHT (AVL_NODE * P) {P -> HEIGHT = 1 + MAX (NODE_HT (P -> LEFT), NODE_HT (P -> RIGHT ));} // SINGLE ROTATE LEFT. friend void S_ROTATE_LEFT (AVL_NODE * & K2); // DOUBLE ROTATE LEFT. friend void D_ROTATE_LEFT (AVL_NODE * & K3); // SINGLE ROTATE RIGHT. friend void S_ROTATE_RIGHT (AVL_NODE * & K1); // DOUBLE ROTATE RIGHT. friend void D_ROTATE_RIGHT (AVL_NODE * & K3); protected: // AVL_TREE WILL USE THIS CLASS. friend class AVL_TREE ; public: // AVL NODE CONSTRUCTOR. AVL_NODE (ETYPE E = 0, AVL_NODE * L = 0, AVL_NODE * R = 0, int H = 0) : TREE_NODE (E, L, R), HEIGHT (H) {} }; // THIS IS THE DECLARATION FOR A AVL SEARCH TREE CLASS. template class AVL_TREE : public BINARY_SEARCH_TREE { // THESE PROCEDURES ARE CALLED BY THE PUBLIC ONES OF THE SAME NAME. protected: // COPY AN AVL TREE. AVL_NODE * COPY (const AVL_NODE * T); // INSERT AN ELEMENT INTO AN AVL TREE. void INSERT (const ETYPE & X, AVL_NODE * & T); // DELETE AN ELEMENT FROM AN AVL TREE. void REMOVE (const ETYPE & X, AVL_NODE * & T); // THESE PROCEDURES WILL CALL THE PROTECTED ONES. public: // CONSTRUCTOR. AVL_TREE () : BINARY_SEARCH_TREE () {} // COPY AVL TREE USING '='. const AVL_TREE & operator = (const AVL_TREE & VALUE); // CALL INSERT. virtual void INSERT (const ETYPE & X) {INSERT (X, (AVL_NODE * &) ROOT);} // CALL REMOVE. virtual void REMOVE (const ETYPE & X) {REMOVE (X, (AVL_NODE * &) ROOT);} }; // THIS IS THE IMPLEMENTATION OF THE AVL SEARCH TREE CLASS. // COPY THE AVL TREE. template AVL_NODE * AVL_TREE :: COPY (const AVL_NODE * T) { if (T != 0) return new AVL_NODE (T -> ELEMENT, COPY ((AVL_NODE * )(T -> LEFT)), COPY ((AVL_NODE *) (T -> RIGHT)), T -> HEIGHT); else return 0; } // INSERT AN ELEMENT INTO THE AVL TREE. CORRECT BALANCE IF NECESSARY. template void AVL_TREE :: INSERT (const ETYPE & X, AVL_NODE * & T) { if (T == 0) // CREATE A ONE NODE TREE. { T = new AVL_NODE (X); if (T == 0) OUTFILE << "OUT OF SPACE."; return; } if (X < T -> ELEMENT) { INSERT (X, (AVL_NODE * &) T -> LEFT); if (NODE_HT (T -> LEFT) - NODE_HT (T -> RIGHT) == 2) if (X < ((AVL_NODE *) T -> LEFT) -> ELEMENT) S_ROTATE_LEFT (T); else D_ROTATE_LEFT (T); else CALCULATE_HEIGHT (T); } else if (X > T -> ELEMENT) { INSERT (X, (AVL_NODE * & ) T -> RIGHT); if (NODE_HT (T -> RIGHT) - NODE_HT (T -> LEFT) == 2) if (X > ((AVL_NODE *) T -> RIGHT) -> ELEMENT) S_ROTATE_RIGHT (T); else D_ROTATE_RIGHT (T); else CALCULATE_HEIGHT (T); } // ELSE X IS IN THE TREE ALREADY, SO WE'LL DO NOTHING. } // REMOVE AN ELEMENT FROM THE AVL TREE. CORRECT BALANCE IF NECESSARY. template void AVL_TREE :: REMOVE (const ETYPE & X, AVL_NODE * & T) { AVL_NODE * TMP_CELL; if (T == 0) OUTFILE << "ELEMENT NOT FOUND."; else if (X < T -> ELEMENT) // GO LEFT. { { REMOVE (X, (AVL_NODE * &)T -> LEFT); } } else if (X > T -> ELEMENT) // GO RIGHT. { { REMOVE (X, (AVL_NODE * &) T -> RIGHT); } } else // FOUND ELEMENT TO BE REMOVED. if (T -> LEFT != 0 && T -> RIGHT != 0) // TWO CHILDREN. { // REPLACE WITH SMALLEST IN RIGHT SUBTREE. TMP_CELL = (AVL_NODE *) FIND_MIN (T -> RIGHT); T -> ELEMENT = TMP_CELL -> ELEMENT; REMOVE (T -> ELEMENT, (AVL_NODE * &) T -> RIGHT); } else // ONE OR ZERO CHILD. { TMP_CELL = T; if (T -> LEFT == 0) // ONLY A RIGHT CHILD. T = (AVL_NODE * &) T -> RIGHT; else if (T -> RIGHT == 0) // ONLY A LEFT CHILD. T = (AVL_NODE * &) T -> LEFT; delete TMP_CELL; } } // THIS FUNCTION CAN BE CALLED ONLY IF K2 HAS A LEFT CHILD. // PERFORM A ROTATE BETWEEN A NODE (K2) AND ITS LEFT CHILD. // UPDATE HEIGHTS. template void S_ROTATE_LEFT (AVL_NODE * & K2) { AVL_NODE * K1 = (AVL_NODE * ) K2 -> LEFT; K2 -> LEFT = K1 -> RIGHT; K1 -> RIGHT = K2; K2 -> HEIGHT = MAX (NODE_HT (K2 -> LEFT), NODE_HT (K2 -> RIGHT)) + 1; K1 -> HEIGHT = MAX (NODE_HT (K1 -> LEFT), K2 -> HEIGHT) + 1; K2 = K1; } // THIS PROCEDURE CAN ONLY BE CALLED IF K3 HAS A LEFT CHILD AND K3'S LEFT // CHILD HAS A RIGHT CHILD. // DO THE LEFT-RIGHT DOUBLE ROTATION. template void D_ROTATE_LEFT (AVL_NODE * & K3) { S_ROTATE_RIGHT ((AVL_NODE * &) K3 -> LEFT); S_ROTATE_LEFT (K3); } // THIS FUNCTION CAN BE CALLED ONLY IF K1 HAS A RIGHT CHILD. // PERFORM A ROTATE BETWEEN A NODE (K1) AND ITS RIGHT CHILD. // UPDATE HEIGHTS. template void S_ROTATE_RIGHT (AVL_NODE * & K1) { AVL_NODE * K2 = (AVL_NODE * ) K1 -> RIGHT; K1 -> RIGHT = K2 -> LEFT; K2 -> LEFT = K1; K1 -> HEIGHT = MAX (NODE_HT (K1 -> RIGHT), NODE_HT (K1 -> LEFT)) + 1; K2 -> HEIGHT = MAX (NODE_HT (K2 -> RIGHT), K1 -> HEIGHT) + 1; K1 = K2; } // THIS PROCEDURE CAN ONLY BE CALLED IF K3 HAS A RIGHT CHILD AND K3'S RIGHT // CHILD HAS A LEFT CHILD. // DO THE RIGHT-LEFT DOUBLE ROTATION. template void D_ROTATE_RIGHT (AVL_NODE * & K3) { S_ROTATE_LEFT ((AVL_NODE * &) K3 -> RIGHT); S_ROTATE_RIGHT (K3); } // RETURN THE MAXIMUM NUMBER OF TWO INTEGERS. USED FOR THE HEIGHT. int MAX (int A, int B) { if (A > B) { return A; } else { return B; } } // THIS PROGRAM WILL INSERT 40 RANDOM INTEGERS FROM 1000 TO 10000 INTO // A AVL TREE AND PRINT THEM IN ASCENDING ORDER. THEN, IT // WILL DELETE 20 ELEMENTS FROM THE TREE, PRINTING THE NEW TREE EVERY // FORTH REMOVAL. int main () { // OPEN OUTFILE. OUTFILE.open ("AVL.OUT", ios :: out); // CLEAR SCREEN. clrscr (); // MAKE EACH EXECUTION DIFFERENT. randomize (); // DECLARE VARIABLE FOR AN AVL TREE OF INTEGERS. // IT WILL HOLD THE 40 RANDOM INTEGERS. AVL_TREE INTEGER_TREE; // HOLDS THE CURRENT RANDOM NUMBER. int RANDOM_NUMBER; // HOLDS THE CURRENT RANDOM NUMBER. NEEDED FOR REMOVAL. int TEMP; // HOLDS THE 40 RANDOM INTEGERS. // THIS WILL BE USED FOR DELETION. int RANDOM_ARRAY [40]; // FLAG = 1, THE INTEGER IS ALREADY IN THE TREE. // FLAG = 0, THE INTEGER IS NOT IN THE TREE. int FLAG; // INSERT 40 RANDOM INTEGERS FROM 1000 TO 10000 INTO THE TREE. for (int I = 0; I <= 39; I++) { // GET RANDOM NUMBER AND MAKE SURE IT IS NOT ALREADY IN // THE TREE. do { FLAG = 0; RANDOM_NUMBER = (rand () % 9000) + 1000; for (int J = 0; J <= I; J++) { if (RANDOM_ARRAY [J] == RANDOM_NUMBER); { FLAG = 1; break; } } } while (FLAG != 1); // INSERT IT INTO THE TREE. INTEGER_TREE.INSERT (RANDOM_NUMBER); // ALSO, INSERT IT INTO AN ARRAY. RANDOM_ARRAY [I] = RANDOM_NUMBER; } // PRINT A HEADING AND THEN THE TREE. OUTFILE << "AFTER 40 INSERTIONS (HEIGHT AND INT):\n"; INTEGER_TREE.PRINT_TREE (); // REMOVE 20 ELEMENTS FROM THE TREE. for (int J = 0; J <= 19; J++) { // LOOP IF THE RANDOM NUMBER IS NOT IN THE ARRAY. // THIS MIGHT HAPPEN IF IT HAS BEEN REMOVED FROM // TREE AND ARRAY. do { // RANDOM NUMBER FROM 0 TO 39. // INDEX OF THE ARRAY. RANDOM_NUMBER = (rand () % 40); } while (RANDOM_ARRAY [RANDOM_NUMBER] == 0); // HOLD THE RANDOM NUMBER. TEMP = RANDOM_ARRAY [RANDOM_NUMBER]; // PUT 0 IN THE ARRAY OF THE APPROPRIATE INDEX. RANDOM_ARRAY [RANDOM_NUMBER] = 0; // PUT THE RANDOM NUMBER IN THE TEMP VARIABLE INTO // THE RANDOM NUMBER VARIABLE. RANDOM_NUMBER = TEMP; // REMOVE THE RANDOM NUMBER. INTEGER_TREE.REMOVE (RANDOM_NUMBER); // WRITE A HEADING AND SHOW THE NEW TREE. if ((J + 1) % 4 == 0) { OUTFILE << "\nAFTER 4 DELETIONS (HEIGHT AND INT):\n"; INTEGER_TREE.PRINT_TREE (); } } // CLOSE OUTFILE. OUTFILE.close (); return 0; } // OUTFILE: AVL.OUT AFTER 40 INSERTIONS (HEIGHT AND INT): 0 1309 1 1316 2 1723 0 2170 1 2479 3 2531 0 2891 1 3092 0 3104 5 3315 1 3570 0 3645 2 3713 0 3790 4 4359 0 4501 2 4984 1 5007 0 5200 3 5257 0 5266 1 5308 0 5344 6 5430 0 5606 1 5975 3 6317 0 6427 2 6523 0 7141 1 7227 4 7759 1 7816 0 8000 3 8224 0 8687 1 9104 0 9337 2 9460 0 9788 AFTER 4 DELETIONS (HEIGHT AND INT): 0 1309 1 1316 2 1723 0 2170 1 2479 3 2531 0 2891 1 3092 0 3104 5 3315 1 3570 0 3645 2 3713 0 3790 4 4359 0 4501 2 4984 1 5007 0 5200 3 5257 1 5308 0 5344 6 5430 0 5606 1 5975 2 6317 1 6523 0 7227 4 7759 1 7816 0 8000 3 8224 0 8687 1 9337 2 9460 0 9788 AFTER 4 DELETIONS (HEIGHT AND INT): 0 1309 1 1316 2 1723 0 2170 1 2479 3 2531 0 2891 1 3092 0 3104 5 3315 1 3570 0 3645 2 3713 4 4359 0 4501 2 4984 1 5007 0 5200 3 5257 1 5308 0 5344 6 5430 0 5606 1 5975 2 6317 0 6523 3 7759 0 7816 2 8224 0 8687 1 9460 0 9788 AFTER 4 DELETIONS (HEIGHT AND INT): 0 1316 2 1723 0 2170 1 2479 3 2531 0 2891 1 3092 5 3315 0 3645 1 3713 4 4359 2 4984 1 5007 0 5200 3 5257 1 5308 0 5344 6 5430 0 5606 1 5975 2 6317 0 6523 3 7759 0 7816 2 8224 0 8687 1 9460 0 9788 AFTER 4 DELETIONS (HEIGHT AND INT): 0 1316 2 1723 0 2170 1 2479 3 2891 0 3092 4 3315 0 3713 3 4359 1 4984 0 5007 2 5257 0 5344 5 5430 0 5606 1 5975 2 6317 0 6523 3 7759 0 7816 2 8224 0 8687 1 9460 0 9788 AFTER 4 DELETIONS (HEIGHT AND INT): 1 1723 0 2479 2 2891 0 3092 3 3315 0 3713 2 4359 0 5007 1 5257 0 5344 4 5430 0 5606 1 5975 2 6317 0 6523 3 7759 0 7816 2 8224 1 9460 0 9788
BACK TO CS3240 PAGE.