// CPS 100, fall 1995, test 2 answers /**** Problem 1: array: binary search, max is first or last minheap: min at top, for max search whole heap bst: worst case is long, string linked list array (sorted) minheap binary search tree Find(x) O(log n) O(n) O(n) FindMax(x) O(1) O(n) O(n) Problem 2: Part A: 23 / \ / +----\ 8 40 / \ / 5 12 32 \ / 15 27 Part B: preorder: 22, 12, 7, 3, 18, 61, 50, 58,88 postorder: 3, 7, 18, 12, 58, 50, 88, 61, 22 Part C average case of CopyTree: T(n) = 2 T(n/2) + O(1) ==> O(n) [visit each node once) Part D: swap calls of Copy(t->left) and Copy(t->right) Part E average case of CopyCount T(n) = 2 T(n/2) + O(n) ==> O(n log n) the O(n) in the recurrence is for NumNodes *******/ // first version using CCAux Tree * CopyCount(Tree * t) // postcondition: returns "counted" copy of t { Tree * temp; int count; CCAux(t,temp,count); return temp; } void CCAux(Tree * t, Tree * & copy, int & count) // postcondition: copy is a "copy count" copy of the tree t // e.g., all info fields replaced by node count // count is the number of nodes in tree t (rooted at t) { count = 0; copy = 0; if (t != 0) { Tree * leftcopy; Tree * rightcopy; int leftcount,rightcount; // do subtrees CCAux(t->left,leftcopy,leftcount); CCAux(t->right,rightcopy,rightcount); count = 1 + leftcount + rightcount; // subtrees + 1 for self copy = new Tree(count,leftcopy,rightcopy); // and make tree } } // second version, O(n) without using CCAux, still done bottom up Tree * CopyCount(Tree * t) // postcondition: returns "counted" copy of t { Tree * temp = 0; if (t != 0) { if (t->left == 0 && t->right == 0) // leaf? { temp = new Tree(1,0,0); // one node } else { // make new tree, but adjust node count afterward temp = new Tree(0,CopyCount(t->left),CopyCount(t->right)); temp->info = 1 + temp->left + (temp->left ? temp->left->info : 0) + (temp->right ? temp->right->info : 0); } } return temp; } // Problem 3, first version void DoubleUp(Tree * t) // postcondition: modifies to so that it is "doubled up" { if (t != 0) { DoubleUp(t->left); // take care of subtrees DoubleUp(t->right); if (t->left) { t->left = new Tree(t->left->info,t->left,0); } if (t->right) { t->right = new Tree(t->right->info,0,t->right); } } } // second version void DoubleUp(Tree * t) // postcondition: modifies to so that it is "doubled up" { if (t != 0) { if (t->left != 0) { t->left = new Tree(t->left->info,t->left,0); DoubleUp(t->left->left); } if (t->right != 0) { t->right = new Tree(t->right->info,0,t->right); DoubleUp(t->right->right); } } } // problem 5 void SortStudents(Vector & list, int numElts) // precondition: numElts = # of students in list // ID numbers are unique and in range 1...numElts // postcondition: list is sorted into increasing order by // student ID number // performance: O(n) { int k; Student temp; Student current = list[0]; for(k=0; k < numElts; k++) { temp = list[current.classID - 1]; // student #1 in index 0, etc. list[current.classID - 1] = current; current = temp; } } // using aux vector void SortStudents(Vector & list, int numElts) // precondition: numElts = # of students in list // ID numbers are unique and in range 1...numElts // postcondition: list is sorted into increasing order by // student ID number // performance: O(n) { int k; Vector temp(numElts); for(k=0; k < numElts; k++) { temp[list[k].classID - 1] = list[k]; } list = temp; } /*** problem 5 part B O(n log n) sort the array using an O(n log n) sort [e.g., merge] then make n passes, for each element a[j] of the vector, use binary search O(log n) to search for k-a[j] to see if sum can be formed. Total: O(n log n) + n O(n log n) = O(n log n) O(n) Hash all the numbers: O(n) to hash all of them. Then for each element a[j] of the vector, search using hashing for k-a[j]. The search is O(1), so Total: O(n) + n O(1) = O(n) (average case hashing is constant time or O(1 + loadfactor) ******/ // extra credit int NumLessThan(const Vector & heap, int size, int key) // precondition: size is the number of elements in the heap, // heap is a minheap // postcondition: returns the number of elements in the heap // less than key { return Aux(heap,1,size,key); } int Aux(const Vector & heap, int index, int size, int key) // precondition: size is the number of elements in the heap, // heap is a minheap, // postcondition: returns # elements in subheap starting at index // that are less than key { if (index <= size) // heap is non-empty? { if (heap[index] < key) // key bigger than root, check subheaps { return 1 + Aux(heap,2*index,size,heap) + Aux(heap,2*index+1,size,heap); } } return 0; }