#include #include #include // for exit #include "CPstring.h" #include "tree.h" #include "StackAr.h" // author: Owen Astrachan // // lists all words in an input file, with word counts // uses class WordList to encapsulate behavior // // 5-15-95 // // modified 6/10/96 to use a binary search tree to // store each word // // modified 11/3/96 to make it a separate class static void DeleteTree(TreeNode * root) // postcondition: tree pointed to by root is deleted { if (root != 0) { DeleteTree(root->left); DeleteTree(root->right); delete root; } } static void UpdateTreeLevels(TreeNode * & root, Display & display, int level, int id) // postcondition: Nodes are moved in tree for samba { // Routine recursively updates each subtree if (root != 0) { // update current node display.DisconnectNodeFromParent(root); root->level = level; root->id = id; display.MoveNode(root); display.ConnectNodeToParent(root); // update subtrees UpdateTreeLevels(root->left, display, level+1, 2*id); UpdateTreeLevels(root->right, display, level+1, 2*id+1); } } static void DoInorder(TreeNode * root, Stack & stack) // postcondition: tree is Inordered in a preorder traversal { if (root != 0) { // Push subtrees in order DoInorder(root->right, stack); stack.Push(root); DoInorder(root->left, stack); } } static int ComputeHeight(TreeNode * root) // postcondition: Computes "height of tree" { int count; // count for whole tree if (root) { // Add 1 to max of height of left subtree and right subtree int left_count = ComputeHeight(root->left); int right_count = ComputeHeight(root->right); if (left_count>=right_count) { count = left_count + 1; } else { count = right_count + 1; } } else { count = 0; } return count; } static int ComputeDiameter(TreeNode * root) // postcondition: Computes # of nodes in diameter of tree { int retdiameter; // diameter for whole tree if (root) { // diameter is max of diameter of left subtree, diameter of // the right subtree and the sum of the deepest level of both // subtrees + 1 for the current node int diameter_left = ComputeDiameter(root->left); int diameter_right = ComputeDiameter(root->right); int left_count = ComputeHeight(root->left); int right_count = ComputeHeight(root->right); int diameter = left_count + right_count + 1; if (diameter_left >=diameter_right) { retdiameter = diameter_left; } else { retdiameter = diameter_right; } //Compare subtree diameter with "diameter" including current node if (diameter > retdiameter) { retdiameter = diameter; } } else { retdiameter = 0; } return retdiameter; } static void DisplayStack(Stack & stack, Display & display) // postcondition:: Displays stack // stack is empty after call { // You get to implement this function cerr << "DisplayStack not implemented " << endl; string junk; cerr << "Hit Enter to continue: " ; getline(cin,junk); } TreeList::TreeList() : myCount(0), myTree(0), myMaxLevel(0), myDisplay(cout) { // all work done in initializer list } TreeList::TreeList(ostream & outstream) : myCount(0), myTree(0), myMaxLevel(0), myDisplay(outstream) { // all work done in initializer list } TreeList::~TreeList() // postcondition: all new'd storage deleted { DeleteTree(myTree); } void TreeList::DeleteAllNodes() // postcondition: All nodes deleted from tree. { while (myTree!=0) { DeleteNode(myTree); } } void TreeList::DeleteNode(TreeNode * loc) // post condition: loc deleted from tree { TreeNode * current = myTree; // current node of tree TreeNode * parent = 0; // nodes parent //Find Node's Parent while (current!=0 && current != loc) { parent = current; // update parent if (current->info > loc->info) // update current { current = current->left; } else { current = current->right; } } if (current!=0) { // replace the node with in order successor TreeNode * replace; // Node to replace current with if (current->right!=0) { TreeNode * replace_parent = current; replace = current->right; while (replace->left) { replace_parent = replace; replace = replace->left; } if (replace_parent != current) { replace_parent->left = replace->right; replace->right = current->right; } replace->left = current->left; } else { replace = current->left; // right node of current is null } if (parent!=0) { // hook new node if (parent->left==current) { parent->left = replace; } else { parent->right = replace; } } else { // replace the root node myTree = replace; } // Do display stuff for samba myDisplay.DisconnectNodeFromParent(current); myDisplay.DeleteNode(current); UpdateTreeLevels(replace, myDisplay, current->level, current->id); // see if we can "contract" the tree int newCount = ComputeHeight(myTree) - 1; if (newCount != myMaxLevel) { myMaxLevel = newCount; myDisplay.UpdateLevelCount(myMaxLevel); UpdateTreeLevels(myTree, myDisplay, 0, 0); } delete current; myCount--; } } TreeNode * TreeList::Search(const string & key) // postcondition: returns pointer to struct with key // returns 0 if key does not occur // performance: O(log n), n = # items in myTree { TreeNode * current = myTree; while (current != 0) { // Make Node light up myDisplay.FlashNode(current); if (current->info == key) { return current; } else if (key < current->info) { current = current->left; } else { current = current->right; } } return 0; } void TreeList::DoInsert(TreeNode * & root, const string & word, int level, int id) //Post Condition Node is inserted into the tree { // Routine recursively inserts node into proper subtree if (root == 0) { // Grow the tree if necessary if (level > myMaxLevel) { myMaxLevel = level; myDisplay.UpdateLevelCount(myMaxLevel); UpdateTreeLevels(myTree, myDisplay, 0, 0); } root = new TreeNode; root->info = word; root->left = root->right = 0; root->level = level; root->id = id; //Display the node myDisplay.InitializeTreeNode(root); myDisplay.FlashNode(root); } else if (word < root->info) { DoInsert(root->left,word, level+1, 2*id); } else { DoInsert(root->right,word, level+1, 2*id+1); } } void TreeList::Insert(const string & word) // postcondition: updates occurrence of word // adds word and increments count of total # of words // to list if not already present { TreeNode * loc = Search(word); if (loc == 0) { myCount++; DoInsert(myTree,word, 0, 0); } } bool TreeList::Delete(const string & key) // postcondition: returns pointer to struct with key // returns 0 if key does not occur // performance: O(log n), n = # items in myTree { TreeNode * loc = Search(key); if (loc!=0) { DeleteNode(loc); return true; } return false; } void TreeList::InorderTraversal() // postcondition: Prints list with an inorder traversal { Stack stack; // stack of tree nodes DoInorder(myTree, stack); DisplayStack(stack, myDisplay); } int TreeList::GetCount() // postcondition: returns # unique words in list { return myCount; } int TreeList::ComputeTreeHeight() // postcondition: Computes height of tree { return ComputeHeight(myTree); } int TreeList::ComputeTreeDiameter() // postcondition: Computes # of nodes in diameter of tree { return ComputeDiameter(myTree); }