LevelPrint
A.First Edition
This is first edition of first question in assignment 3 of comp352 and it is a simple test.
How to print a binary tree level by level?
C.Further improvement
The problem is that for such a simple question I have used 7 classes, not including their base abstract classes.
And I haven't mentioned that several classes are template class and I already used some I/O class like ofstream
for I/O. Such deluxry!
//the file name is Levelprint.cpp
#include <iostream> #include <fstream> #include "book.h" #include "Compare.h" #include "BST.h" #include "BinNode.h" //#include "queue.h" #include "AQueue.h" using namespace std; class LevelBST: public BST<int, Int, intIntCompare, IntIntCompare> { private: ifstream in; AQueue<BinNode<Int>*> Que; public: void readFile(const char* fileName); void preOrder(BinNode<Int>* ptr, void (*visit)(BinNode<Int>*node)); void LevelPrint(); }; int main() { LevelBST L; L.readFile("c:\\mytree.txt"); L.LevelPrint(); return 0; } void LevelBST::LevelPrint() { BinNode<Int>* son; Que.enqueue(root); while (Que.dequeue(son)) { cout<<son->val().key()<<endl; if (son->left()!=NULL) { Que.enqueue(son->left()); } if (son->right()!=NULL) { Que.enqueue(son->right()); } } } void LevelBST::preOrder(BinNode<Int>* ptr, void (*visit)(BinNode<Int>*node)) { if (ptr!=NULL) { visit(ptr); preOrder(ptr->left(), visit); preOrder(ptr->right(), visit); } } void LevelBST::readFile(const char* fileName) { in.open(fileName); Int *myInt; int i; while (!in.eof()) { in>>i; myInt= new Int(i); insert(*myInt); } }
//file name AQueue.h
// This is the file to include in your code if you want access to the // complete AQueue template class // First, get the declaration for the base stack class #include "queue.h" // Array-based queue implementation template <class Elem> class AQueue: public Queue<Elem> { private: int size; // Maximum size of queue int front; // Index of front element int rear; // Index of rear element Elem *listArray; // Array holding queue elements public: AQueue(int sz =DefaultListSize) { // Constructor // Make list array one position larger for empty slot size = sz+1; rear = 0; front = 1; listArray = new Elem[size]; } ~AQueue() { delete [] listArray; } // Destructor void clear() { front = rear; } bool enqueue(const Elem& it) { if (((rear+2) % size) == front) return false; // Full rear = (rear+1) % size; // Circular increment listArray[rear] = it; return true; } bool dequeue(Elem& it) { if (length() == 0) return false; // Empty it = listArray[front]; front = (front+1) % size; // Circular increment return true; } bool frontValue(Elem& it) const { if (length() == 0) return false; // Empty it = listArray[front]; return true; } virtual int length() const { return ((rear+size) - front + 1) % size; } };
//file name Binnode.h
#ifndef BINNODE_H #define BINNODE_H // Binary tree node abstract class template <class Elem> class BinNode { public: // Return the node's element virtual Elem& val() = 0; // Set the node's element virtual void setVal(const Elem&) = 0; // Return the node's left child virtual BinNode* left() const = 0; // Set the node's left child virtual void setLeft(BinNode*) = 0; // Return the node's right child virtual BinNode* right() const = 0; // Set the node's right child virtual void setRight(BinNode*) = 0; // Return true iff the node is a leaf virtual bool isLeaf() = 0; }; // Binary tree node class template <class Elem> class BinNodePtr : public BinNode<Elem> { private: Elem it; // The node's value BinNodePtr* lc; // Pointer to left child BinNodePtr* rc; // Pointer to right child public: // Two constructors -- with and without initial values BinNodePtr() { lc = rc = NULL; } BinNodePtr(Elem e, BinNodePtr* l =NULL, BinNodePtr* r =NULL) { it = e; lc = l; rc = r; } ~BinNodePtr() {} // Destructor Elem& val() { return it; } void setVal(const Elem& e) { it = e; } inline BinNode<Elem>* left() const { return lc; } void setLeft(BinNode<Elem>* b) { lc = (BinNodePtr*)b; } inline BinNode<Elem>* right() const { return rc; } void setRight(BinNode<Elem>* b) { rc = (BinNodePtr*)b; } bool isLeaf() { return (lc == NULL) && (rc == NULL); } }; #endif
//filename BST.h
// This file includes all of the pieces of the BST implementation #include "dictionary.h" #include "binnode.h" // Binary Search Tree implementation for the Dictionary ADT template <class Key, class Elem, class KEComp, class EEComp> class BST : public Dictionary<Key, Elem, KEComp, EEComp> { protected: BinNode<Elem>* root; // Root of the BST int nodecount; // Number of nodes in the BST // Private "helper" functions void clearhelp(BinNode<Elem>*); BinNode<Elem>* inserthelp(BinNode<Elem>*, const Elem&); BinNode<Elem>* deletemin(BinNode<Elem>*, BinNode<Elem>*&); BinNode<Elem>* removehelp(BinNode<Elem>*, const Key&, BinNode<Elem>*&); bool findhelp(BinNode<Elem>*, const Key&, Elem&) const; void printhelp(BinNode<Elem>*, int) const; public: BST() { root = NULL; nodecount = 0; } // Constructor ~BST() { clearhelp(root); } // Destructor void clear() { clearhelp(root); root = NULL; nodecount = 0; } bool insert(const Elem& e) { root = inserthelp(root, e); nodecount++; return true; } bool remove(const Key& K, Elem& e) { BinNode<Elem>* t = NULL; root = removehelp(root, K, t); if (t == NULL) return false; // Nothing found e = t->val(); nodecount--; delete t; return true; } bool removeAny(Elem& e) { // Delete min value if (root == NULL) return false; // Empty tree BinNode<Elem>* t; root = deletemin(root, t); e = t->val(); delete t; nodecount--; return true; } bool find(const Key& K, Elem& e) const { return findhelp(root, K, e); } int size() { return nodecount; } void print() const { if (root == NULL) cout << "The BST is empty.\n"; else printhelp(root, 0); } }; template <class Key, class Elem, class KEComp, class EEComp> void BST<Key, Elem, KEComp, EEComp>:: clearhelp(BinNode<Elem>* subroot) { if (subroot == NULL) return; clearhelp(subroot->left()); clearhelp(subroot->right()); delete subroot; } template <class Key, class Elem, class KEComp, class EEComp> BinNode<Elem>* BST<Key, Elem, KEComp, EEComp>:: inserthelp(BinNode<Elem>* subroot, const Elem& val) { if (subroot == NULL) // Empty tree: create node return (new BinNodePtr<Elem>(val, NULL, NULL)); if (EEComp::lt(val, subroot->val())) // Insert on left subroot->setLeft(inserthelp(subroot->left(), val)); else subroot->setRight(inserthelp(subroot->right(), val)); return subroot; // Return subtree with node inserted } template <class Key, class Elem, class KEComp, class EEComp> BinNode<Elem>* BST<Key, Elem, KEComp, EEComp>:: deletemin(BinNode<Elem>* subroot, BinNode<Elem>*& min) { if (subroot->left() == NULL) { // Found min min = subroot; return subroot->right(); } else { // Continue left subroot->setLeft(deletemin(subroot->left(), min)); return subroot; } } template <class Key, class Elem, class KEComp, class EEComp> BinNode<Elem>* BST<Key, Elem, KEComp, EEComp>:: removehelp(BinNode<Elem>* subroot, const Key& K, BinNode<Elem>*& t) { if (subroot == NULL) return NULL; // Val is not in tree else if (KEComp::lt(K, subroot->val())) // Check left subroot->setLeft(removehelp(subroot->left(), K, t)); else if (KEComp::gt(K, subroot->val())) // Check right subroot->setRight(removehelp(subroot->right(), K, t)); else { // Found it: remove it BinNode<Elem>* temp; t = subroot; if (subroot->left() == NULL) // Only a right child subroot = subroot->right(); // so point to right else if (subroot->right() == NULL) // Only a left child subroot = subroot->left(); // so point to left else { // Both children are non-empty subroot->setRight(deletemin(subroot->right(), temp)); Elem te = subroot->val(); subroot->setVal(temp->val()); temp->setVal(te); t = temp; } } return subroot; } template <class Key, class Elem, class KEComp, class EEComp> bool BST<Key, Elem, KEComp, EEComp>:: findhelp( BinNode<Elem>* subroot, const Key& K, Elem& e) const { if (subroot == NULL) return false; // Empty tree else if (KEComp::lt(K, subroot->val())) // Check left return findhelp(subroot->left(), K, e); else if (KEComp::gt(K, subroot->val())) // Check right return findhelp(subroot->right(), K, e); else { e = subroot->val(); return true; } // Found it } template <class Key, class Elem, class KEComp, class EEComp> void BST<Key, Elem, KEComp, EEComp>:: printhelp(BinNode<Elem>* subroot, int level) const { if (subroot == NULL) return; // Empty tree printhelp(subroot->left(), level+1); // Do left subtree for (int i=0; i<level; i++) // Indent to level cout << " "; cout << subroot->val() << "\n"; // Print node value printhelp(subroot->right(), level+1); // Do right subtree }
//file name book.h
#include <time.h> // Used by timing functions #include <iostream> using namespace std; // Utility functions and macros // Return true iff x is even inline bool EVEN(int x) { return (x % 2) == 0; } // Return true iff x is odd inline bool ODD(int x) { return (x & 1) != 0; } const int DefaultListSize = 10; // Lists, etc. default size // Assert: If boolean expression is false, print a message // and terminate the program void Assert(bool val, char* string) { if (!val) { // Assertion failed -- close the program cout << "Assertion Failed: " << string << endl; exit(-1); } } // Random number generator functions inline void Randomize() // Seed the generator { srand(1); } // Return a random value in range 0 to n-1 inline int Random(int n) { return rand() % (n); } // Swap two elements in a generic array template<class Elem> inline void swap(Elem A[], int i, int j) { Elem temp = A[i]; A[i] = A[j]; A[j] = temp; } // Swap two objects passed by reference template<class Elem> inline void swap(Elem &e1, Elem &e2) { Elem temp = e1; e1 = e2; e2 = temp; } // Timing variables and functions clock_t tstart = 0; // Time at beginning of timed section // Initialize the program timer void Settime() { tstart = clock(); } // Return the elapsed time since the last call to Settime double Gettime() { return (double)((double)clock() - (double)tstart)/ (double)CLOCKS_PER_SEC; } // Your basic int type as an object. class Int { private: int val; public: Int(int input=0) { val = input; } // The following is for those times when we actually // need to get a value, rather than compare objects. int key() const { return val; } // Overload = to support Int foo = 5 syntax operator= (int input) { val = input; } }; // Let us print out Ints easily ostream& operator<<(ostream& s, const Int& i) { return s << i.key(); } ostream& operator<<(ostream& s, const Int* i) { return s << i->key(); }
//file name compare.h
// Some definitions for Comparator classes class intintCompare { public: static bool lt(int x, int y) { return x < y; } static bool eq(int x, int y) { return x == y; } static bool gt(int x, int y) { return x > y; } }; class IntIntCompare { public: static bool lt(Int x, Int y) { return x.key() < y.key(); } static bool eq(Int x, Int y) { return x.key() == y.key(); } static bool gt(Int x, Int y) { return x.key() > y.key(); } }; class intIntCompare { public: static bool lt(int x, Int y) { return x < y.key(); } static bool eq(int x, Int y) { return x == y.key(); } static bool gt(int x, Int y) { return x > y.key(); } }; class intIntsCompare { public: static bool lt(int x, Int* y) { return x < y->key(); } static bool eq(int x, Int* y) { return x == y->key(); } static bool gt(int x, Int* y) { return x > y->key(); } }; class IntsIntsCompare { public: static bool lt(Int* x, Int* y) { return x->key() < y->key(); } static bool eq(Int* x, Int* y) { return x->key() == y->key(); } static bool gt(Int* x, Int* y) { return x->key() > y->key(); } }; class CCCompare { public: static bool lt(char* x, char* y) { return strcmp(x, y) < 0; } static bool eq(char* x, char* y) { return strcmp(x, y) == 0; } static bool gt(char* x, char* y) { return strcmp(x, y) > 0; } };
//here is the tree input
54 34 2 99 23 33 1 12 19 28 45 55
//the output of level printing is like following:
54 34 99 2 45 55 1 23 12 33 19 28 Press any key to continue