Algorithms and Data Structures Written Exam Proposed SOLUTION 2005-01-07 from 09:00 to 13:00 Allowed tools: A standard calculator. Grading criteria: You can get at most 30 points. For an E, 15 points are required. For an D, 18 points are required. For an C, 21 points are required. For an B, 24 points are required. For an A, 27 points are required. Responsible: Verónica Gaspes, telephone 16 7380. Read carefully! Write clearly! Good Luck! 1
1. (5 pts.) The following program fragment is taken from the code distributed with the laboration on sequence alignment. Given the two argument strings, it fills a matrix with the costs for the optimal alignments of all prefixes of both strings. Assuming that the operations length, min, d and charat are constant time, give a Big-Oh analysis of the execution time of the fragment. public SequenceAlignment1(String a, String b) n = a.length(); m = b.length(); M = new int[n+1][m+1]; for(int i = 1; i<=n; i++) M[i][0] = i; for(int j = 1; j<=m; j++) M[0][j] = j; for(int i = 1; i<=n; i++) for(int j = 1; j<=m; j++) M[i][j] = min(m[i-1][j-1]+d(a.charat(i-1),b.charat(j-1)), M[i-1][j]+1, M[i][j-1]+1); The first for-loop does N iterations, where N is the length of string a. The second one does M iterations, where M is the length of string b. The last one does M N iterations, and this is the dominant term. We say then that the algorithm is O(M N), or if we consider strings of the same length, say L, the algorithm is O(L 2 ) 2. (a) (5 pts.) Design an algorithm for searching for a given element X in an ordered array A. You should use the technique known as Divide and Conquer. Describe your algorithm briefly. Say the array A has length N > 1. We can consider the element in the middle of the array and the two strictly smaller slices of the array before and after the middle element (the divide phase). The sought element X will either be equal to the element in the middle (in which case it is found!) or it will be smaller (and then it can be sought in 2
the lower part of the array) or it will be bigger (and then it can be sought in the higher part of the array). In this case there is nothing left to do when the solution is found (the conquer phase is trivial) In case the array has length 1 the element X is compared with the only element of the array In case the array has length 0 the element X is not present in the array. (b) (5 pts.) Implement your algorithm in Java as a method static int find(comparable x, Comparable[] a) that returns the position of x in a (or -1 in case x is not in a). Here is a possible program: static int find( Comparable [ ] a, Comparable x ) return binarysearch( a, x, 0, a.length -1 ); static int binarysearch( Comparable [ ] a, Comparable x, int low, int high ) if(low > high) //slice length == 0 return -1; //not found if (low == high) //slice length == 1 return (a[low].compareto(x)==0)?low:-1; //check the only element int mid = (low + high) / 2; if(a[ mid ].compareto(x) < 0) return binarysearch( a, x, mid + 1, high ); //search in the higher else if(a[ mid ].compareto(x) > 0) return binarysearch( a, x, low, mid - 1 ); //search in the lowe else return mid; //found! 3. (5 pts.) Queues can be implemented in many different ways. In the lectures we presented an implementation where the elements of the queue are stored in an array. In this exercise you will complete an implementation where the elements are stored in nodes that are linked together. New nodes are created as the queue grows and removed as the queue shrinks. In this way, at any time only the memory needed to store the elements in the queue is used. For this exercise you are provided with the class that implements nodes and part of the implementation of queues using these nodes. 3
Your task is to program all methods where the text // YOUR TASK! has been included as method body in the class Queue. class ListNode public Object element; public ListNode next; // Constructors public ListNode( Object theelement ) this( theelement, null ); public ListNode( Object theelement, ListNode n ) element = theelement; next = n; // ListQueue class // // CONSTRUCTION: with no initializer // // ******************PUBLIC OPERATIONS******************* // void enqueue(x) --> Insert x // Object getfront()-->return least recently inserted item // Object dequeue() -->Return and remove least recent item // boolean isempty()--> Return true if empty; else false // void makeempty() --> Remove all items * List-based implementation of the queue. * @author Mark Allen Weiss public class ListQueue private ListNode front; private ListNode back; 4
* Construct the queue. public ListQueue( ) front = back = null; * Test if the queue is logically empty. * @return true if empty, false otherwise. public boolean isempty( ) return front == null; * Insert a new item into the queue. * @param x the item to insert. public void enqueue( Object x ) // YOUR TASK! * Return and remove the least recently inserted item * from the queue. * @return the least recently inserted item in the * queue. public Object dequeue( ) // YOUR TASK! 5
* Get the least recently inserted item in the queue. * Does not alter the queue. * @return the least recently inserted item in the * queue. public Object getfront( ) // YOUR TASK! * Make the queue logically empty. public void makeempty( ) // YOUR TASK! Here is the code provided with the course book: public void enqueue( Object x ) if( isempty( ) ) // Make queue of one element back = front = new ListNode( x ); else // Regular case back = back.next = new ListNode( x ); // has to be used on non-empty queues! public Object dequeue( ) Object returnvalue = front.element; front = front.next; return returnvalue; // has to be used on non-empty queues! public Object getfront( ) 6
return front.element; public void makeempty( ) front = null; back = null; 4. In the course we discussed a naive implementation of Binary Search Trees. This implementation uses a binary node to represent the root of the binary search tree and implements the methods for insertion, deletion and search recursively. You find part of the implementation after the text for this exercise. (a) (2 pts.) Study the constructor and the method insert in the class BinarySearchTree. Draw the tree resulting from the following sequence of statements: BinarySearchTree bst = new BinarySearchTree(); bst.insert(new Integer(1)); bst.insert(new Integer(2)); bst.insert(new Integer(3)); bst.insert(new Integer(4)); bst.insert(new Integer(5)); bst.insert(new Integer(6)); 1 2 Here is the tree: 3 4 5 6 7
(b) (2 pts.) What is the execution time of the operation find(comparable a, BinaryNode t) for a tree of the form you obtained above? (see the implementation of find in the class BinarySearchTree!) The execution time is in the order of the number of elements. (c) (1 pts.) Given a binary search tree consider outputing its elements by traversing the tree in inorder. What can you say about the order of the elements in the output? The elements will be output so that they are ordered from lower values to higher values. (d) (2 pts.) Imagine you have to write a program that has to deal with a large data set where you have to do frequent searches. You choose to store the elements in a binary search tree. When the program starts it loads the elements form a file into the binary search tree by doing repeated insertions. When the program terminates it stores the elements back into the file. What strategy will you choose to traverse the tree to output its elements to the file? Why? By traversing the tree in preorder, when building the tree again by repeated insertions the shape of the tree will be preserved. If it was balanced it will remain balanced! (e) (3 pts.) Implement the operation Comparable findmin() in the class BinarySearchTree that returns the least element in a binary search tree. Here it is as in the course book: * Find the smallest item in the tree. * @return smallest item or null if empty. public Comparable findmin( ) return elementat( findmin( root ) ); * Internal method to find the smallest item in a subtree. * @param t the node that roots the tree. * @return node containing the smallest item. protected BinaryNode findmin( BinaryNode t ) if( t!= null ) while( t.left!= null ) 8
t = t.left; return t; 9
class BinaryNode // Friendly data; // accessible by other package routines Comparable element; // The data in the node BinaryNode left; // Left child BinaryNode right; // Right child // Constructors BinaryNode( Comparable theelement ) element = theelement; left = right = null; // BinarySearchTree class // CONSTRUCTION: with no initializer // ******************PUBLIC OPERATIONS****************** // void insert( x ) --> Insert x // void remove( x ) --> Remove x // void removemin( ) --> Remove minimum item // Comparable find( x ) --> Return item that matches x // Comparable findmin( ) --> Return smallest item // Comparable findmax( ) --> Return largest item // boolean isempty( ) --> Return true if empty; // else false // void makeempty( ) --> Remove all items public class BinarySearchTree The tree root. protected BinaryNode root; * Construct the tree. public BinarySearchTree( ) 10
root = null; * Insert into the tree. * @param x the item to insert. public void insert( Comparable x ) root = insert( x, root ); * Internal method to insert into a subtree. * @param x the item to insert. * @param t the node that roots the tree. * @return the new root. protected BinaryNode insert( Comparable x, BinaryNode t) if( t == null ) t = new BinaryNode( x ); else if( x.compareto( t.element ) < 0 ) t.left = insert( x, t.left ); else if( x.compareto( t.element ) > 0 ) t.right = insert( x, t.right ); return t; * Find an item in the tree. * @param x the item to search for. * @return the matching item or null if not found. public Comparable find( Comparable x ) return elementat( find( x, root ) ); private Comparable elementat( BinaryNode t ) return t == null? null : t.element; 11
* Internal method to find an item in a subtree. * @param x is item to search for. * @param t the node that roots the tree. * @return node containing the matched item. private BinaryNode find( Comparable x, BinaryNode t) while( t!= null ) if( x.compareto( t.element ) < 0 ) t = t.left; else if( x.compareto( t.element ) > 0 ) t = t.right; else return t; // Match return null; // Not found // OTHER METHODS NOT SHOWN HERE! 12