CPS 100 Test 2 Solutions Problem 1. Part A. B \ W / \ M Y / \ G P / E Part B. Preorder: AFZCWKEYMH Inorder: FWCKZAYEHM Part C. void ReversePostorder(Node * T) // postcondition: prints values in T in reverse postorder { if (T != NULL) { cout << T->info << endl; ReversePostorder(T->right); ReversePostorder(T->left); } } Part D. void LevelOrder(Node * T) // postcondition: prints values in T in level order { Node * tmp; Queue Q; Q.Enqueue(T); while (!Q.IsEmpty()) { tmp = Q.GetFront(); Q.Dequeue(); if (tmp->left != NULL) Q.Enqueue(tmp->left); if (tmp->right != NULL) Q.Enqueue(tmp->right); cout << tmp->info << endl; } } Part E. O(N) Problem 2. Part A. void FillOut(Node * T) // postcondition: Every node N that previously had only one child now has // a subtree of three nodes, each with the same value as N { if (T != NULL) { if (T->left == NULL && T->right != NULL) // no left child { T->left = new Node(T->right->info); } if (T->left != NULL && T->right == NULL) // no right child { T->right = new Node(T->left->info); } FillOut(T->left); FillOut(T->right); } } Part B. void Shrink(Node * T) // postcondition: Every right child that had a right child but no left // child has been removed. { Node * tmp; if (T != NULL) { if (T->right != NULL && T->right->right != NULL && T->right->left == NULL) { // remove T->right tmp = T->right; T->right = tmp->right; delete tmp; Shrink(T); // to process two nodes in a row } else { Shrink(T->right); Shrink(T->left); } } } Problem 3. Part A. GenNode * Find (GenNode * T, string name) // precondition: values in T are unique // postcondition: returns a pointer to the GenNode with value 'name', // returns NULL if 'name' is not in T { if (T == NULL) return NULL; else if (T->name == name) { return T; } else { GenNode * tmp = Find(T->sibling, name); if (tmp != NULL) return tmp; return Find(T->child, name); } } Part B. bool IsDescendant(GenNode * T, string name1, string name2) // precondition: T contains unique values, name1 is not equal to name2 // postcondition: returns true if name2 is a descendant of name1, // otherwise returns false. { GenNode * tmp; tmp = Find(T, name1); if (tmp != NULL) { if (Find(tmp->child, name2) != NULL) return true; } return false; } Alternative Solution: bool IsDescendant(GenNode * T, string name1, string name2) { return (Find(Find(T,name1)->child,name2) != NULL) } Problem 4. Number of Leaves: O(N) Minimum: O(log N) Is X in Tree?: O(log N) Problem 5. Part A. 9 7 5 4 3 2 Part B. Insertion sort is close to O(N) if the elements are in sorted order. With each pass of Shellsort, the elements get closer to being in sorted order, so calling Selection sort (which is always O(N^2)) instead of Insertion sort would increase the running time of Shellsort. Part C. 1. Sort both arrays using mergesort. O(N log N) worst case. 2. For each element in the first array, perform a binary search in the second array to see if it is there. (N elements, each O(log N) search results in O(N log N) worst case. For each element in the second array, perform a binary search in the first array to see if it is there. O(N log N). 2 (alternate). Scan both arrays at the same time in order to make sure the elements are the same. O(N) 3. If all elements are found, the arrays are equivalent. Total time is O(N log N). Part D. 1. Sort both arrays using bucket sort, which takes time O(N + M). 2. Scan both arrays at the same time in order to make sure they contain the same elements. Scanning an array takes O(N) time. Total time is O(N + M). Problem 6. MS(3,1) / MS(4,1) / | \ MS(5,1) MS(3,1) MS(4 , 2) / | \ MS(5,2) MS(3,2) MS(4,3) / | | \ MS(4,2) MS(2,2) MS(3,3) MS(3,1) Extra Credit int NodesWith3(Node23 * T) // postcondition: returns the number of nodes that have three children { if (T==NULL) return 0; if (T->leaf == true) return 0; int count = 0; if (T->right != NULL) // 3 children { count = 1; } return count + NodesWith3(T->left) + NodesWith3(T->middle) + NodesWith3(T->right); }