The University of Western Ontario Department of Computer Science Computer Science 1027b Final Exam April 27, 2012 3 hours Print your name:______________________________________________ Student number: ______________________________________________ Instructions: Fill in your name and student number above immediately. Answer all the questions in the exam in the spaces provided. You have 3 hours to complete the exam. The exam has 11 questions and is out of a possible 146 marks. The marks for each individual question are given. Allow approximately 1 minute per mark on average. There are two pages for rough work at the back of the exam paper. Read the questions carefully. Note that the StackADT, QueueADT, ListADT, UnorderedListADT, OrderedListADT, BinaryTreeADT and BinarySearchTreeADT interfaces are provided in the accompanying handout, as well as the code for LinearNode.java and BinaryTreeNode.java. DO NOT TURN THIS PAGE UNTIL DIRECTED TO DO SO. 1 2 3 4 5 6 /10 /6 /10 /15 /10 /15 7 8 9 10 11 12 (bonus) TOTAL /20 /20 /15 /15 /10 /10 /146 1 1. (10 marks) For each of the following, give the time complexity using big-O notation. Assume an input size of n in each case. a) for (int i = 0; i < n; i++) Answer: _______________ System.out.println(i); b) for (int i = 0; i < n; i++) Answer:_______________ for (int j = i ; j > 0 ; j--) System.out.println(i,j); c) for (int i = 1; i < n/2; i=i*2) { int j = n; while (j > 0) { System.out.println(j); j = j / 2; } } Answer: _______________ d) for (int i = 1; i <= 10; i++) for (int j = 1; j <= 10; j++) for (int k = 1; k <= 10; k++) System.out.println(i,j,k); Answer: _______________ e) for (int i = 1; i < n; i++) Answer: _______________ for (int j = n; j > 0; j=j/2) System.out.println(i,j); 2 2. (6 marks) For each of the following questions, write the code that corresponds to the required Big-O notation. a) Write two nested for loops such that your code fragment has a time complexity of O(n 3 ) b) Write three nested loops such that your code fragment has a time complexity of O(n 2 ) c) Write a for loop such that your code fragment as a time complexity of O(log 2 (n)) 3 3. (10 marks) Answer the following true/false questions. Assume that each container (stack, queue, etc.) contains n elements. Also assume worst-case time complexity, unless stated otherwise. a) The time complexity of pushing an object on a LinkedStack is O(1) except when expanding capacity, which makes it O (n) . TRUE FALSE b) The time complexity of popping an object in a stack of type LinkedStack is identical to that of popping an object in a stack of type ArrayStack. TRUE FALSE c) The time complexity of dequeuing an object from a queue of type ArrayQueue is identical to that of dequeueing an object from a queue of type CircularArrayQueue. TRUE FALSE d) The time complexity of enqueueing an object in a queue of type LinkedQueue is O(1) . TRUE FALSE e) The time complexity to remove a particular object from an ordered list of type ArrayOrderedList with a binary search method is identical to that of removing a particular object from a binary search tree of type LinkedBinarySearchTree. TRUE FALSE f) Suppose a binary search tree containing integers is built with the following sequence (to be read from left to right): 0, 100, 50, 60, 55, 57, 56. Does this tree represent a degenerate case? TRUE FALSE g) The time complexity of finding an object in a tree of type LinkedBinarySearchTree is O (n) . TRUE FALSE 4 h) The time complexity of finding an object in a sorted array with a binary search method is O (n) . TRUE FALSE i) The time complexity of creating a LinkedBinarySearchTree with n nodes is O(n log 2 (n)) (assume average case). TRUE FALSE j) Implementing a LinkedQueue with doubly linked nodes improves the time complexity of both enqueue and dequeue methods. TRUE FALSE 5 4. (15 marks) Write a method which merges the contents of a queue and stack containing integer values into a single sorted stack of integers, returning it to the caller method, with its largest element at the top of the stack (Assume that both the input stack and the input queue each contain a sorted sequence of integers such that the smallest element in the stack is at the top, and the smallest element in the queue is at the front). public static ArrayStack<Integer> StackQueueMerge(ArrayStack<Integer> Stack, ArrayQueue<Integer> Queue) 6 5. (10 marks) Write the method removeFirst() that is found in the LinkedList implementation of ListADT.java. public T removeFirst () throws EmptyCollectionException 7 6. (15 marks) Write a recursive method countInternal which counts the number of internal nodes of a binary tree. Recall that an internal node is a node that is not a leaf. public int countInternal(BinaryTreeNode<T> node) 8 7. (20 marks) a) (15 marks) The method InsertElements is used by a main method to insert integer values from a sorted array into a binary search tree. Complete the method such that the order in which the values are inserted creates a tree of minimum height. The method InsertElements must be recursive (Hint: The element at the midpoint of the array is an excellent choice for the root element in the binary search tree. In addition, use the addElement method from the LinkedBinaryTree class to perform the insertions). public class BalancedTree { private static void InsertElements(LinkedBinarySearchTree<Integer> tree, int a[], int low, int high) { } public static void main (String [] args) { int [] a = {5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75}; LinkedBinarySearchTree<Integer> tree = new LinkedBinarySearchTree<Integer>(); InsertElements(tree, a, 0, a.length-1); } } 9 b) (5 marks) Consider the following method which inserts integers into a binary search tree. Display the tree created by this method, as called by its main. public class Mystery { private static void InsertElementMystery(LinkedBinarySearchTree<Integer> tree, int a[]) { for (int i = 0; i < a.length/2; i++) { tree.addElement(a[i]); tree.addElement(a[a.length - i - 1]); } } public static void main (String [] args) { int [] a = {5, 10, 15, 20, 25, 30}; LinkedBinarySearchTree<Integer> tree = new LinkedBinarySearchTree<Integer>(); InsertElementMystery(tree,a); } } 10 8. (20 marks) Consider the following binary tree: a) (5 marks) Give the order in which the nodes of this tree would be visited by a preorder traversal. b) (5 marks) Give the order in which the nodes of this tree would be visited by an inorder traversal. c) (5 marks) Give the order in which the nodes of this tree would be visited by a postorder traversal. 11 d) (5 marks) The method shown below performs Euler’s traversal of a binary tree, and has been added to LinkedBinaryTree.java. Give the order in which the nodes of the tree shown on this page would be added to templist by Euler’s traversal. protected void Eulerorder(BinaryTreeNode<T> node, ArrayUnorderedList<T> templist) { if (node != null) { templist.addToRear(node.getElement()); Eulerorder(node.getLeft(),templist); templist.addToRear(node.getElement()); Eulerorder(node.getRight(),templist); templist.addToRear(node.getElement()); } } 12 9. (15 marks) Using a stack of binary tree nodes for temporary storage, complete the following method so that it iteratively traverses a binary tree in preorder; “visiting” a node corresponds to adding it to the end of templist. (Hint: A levelorder traversal uses a similar algorithm, but uses a queue for temporary storage of nodes.) public void Iterativepreorder(BinaryTreeNode<T> node, ArrayUnorderedList<T> templist) { LinkedStack<BinaryTreeNode<T>> stack = new LinkedStack<BinaryTreeNode<T>>(); 13 10. (15 marks) The following method is an iterative inorder binary tree traversal that uses a stack to store nodes until they are visited. Complete it by filling in the two missing lines of code. (Again, visiting a node corresponds to adding it to the end of templist.) public void Iterativeinorder(BinaryTreeNode<T> node, ArrayUnorderedList<T> templist) { LinkedStack<BinaryTreeNode<T>> stack = new LinkedStack<BinaryTreeNode<T>>(); boolean done; if (node != null) { stack.push(node) ; while (!stack.isEmpty()) { while (node.getLeft() != null) { __________________________________________________________ __________________________________________________________ } done = false ; while (!stack.isEmpty() && !done)) { node = stack.pop(); templist.addToRear(node.getElement()); if (node.getRight() != null){ node = node.getRight(); stack.push(node); done = true; } } } } } 14 11. (10 marks) Consider the following definition for the height of a binary tree: The height of an empty binary tree is -1. The height of a non-empty binary tree is 1 + the maximum of the heights of the two sub-trees descending from its root node. Complete the following recursive method so that it uses this definition, and returns the height of the binary tree rooted at node. public int height(BinaryTreeNode<T> node) 15 12. (Bonus Question - 10 marks) What does the following method compute? public int someThing(BinaryTreeNode<T> here) { if (here == null) return 1 ; return someThing(here.left) + someThing(here.right); } 16 Extra Page if Needed 17 Extra Page if Needed 18