ECE Fall 2009 1st Midterm Examination (120 Minutes, closed book) Name: ______________________ Student ID: ______________________ Question Score 1 (15) 2 (20) 3 (20) 4 (15) 5 (20) 6 (10) NOTE: Any questions on writing code must be answered in Java using Data Structures topics covered in lectures 1- 10 1. [15 points] a) For the following three cases, indicate the complexity of the given operation using big-O notation for an array or linked list of n items (array locations or nodes). Then, in your own words, provide a one line description regarding how you determined this complexity. i. Print the middle item in an array of known size. Complexity O(1) Explanation Constant time ii. Print the first item in a Linked List of known size. Complexity O(1) Explanation Constant time iii.Print the middle item in a Linked List of known size. Complexity O(n) Explanation Linear time . . . b) Analyze the methods given below. What are their big-O running times, assuming that every basic operation takes 1 unit of time? Then, in your own words, provide a one line description regarding how you determined this complexity. i. public static int func1 (int n, int m) { for (int i=0; i<n; i++) { for (int j=0; j<m; j++) { System.out.println(I + j); } } } Complexity O(n*m) Explanation O(m), together they are O(n*m) There are two loops one has O(n) and the other . ii. public static void func2(int n) { for (int i=1;i<10;i++){ for(int j=i-1;j<=9;j++) { for(int l=j;l<=9;l++) { System.out.println(""+i+j+l+j+i); } } } } Complexity O(1) Explanation Although there are three nested loops, each approximately iterates a constant number of times, no matter what the value of n is, the runtime is constant, hence the complexity is O(1) . 2.[20 points] This question asks you to create a queue class which includes the following two methods (enqueue and dequeue) and a constructor. The queue must consist of one or more Stacks which contain the following methods. Void push(Object) Object pop() Object peek() Boolean isEmpty() Int size() You can create a Stack object using a line such as Stack mystack = new Stack(); . The implementation of the Stack is unimportant (you do not have to implement it). Your answer for the three queue methods and the queue constructor should only contain Stack objects; you do not need to create any linked lists or arrays. You do not need to check if a Stack is full before you add a value to it. The queue should store values of Object type. Public class queue public StackQueue () { stack1 = new ArrayStack(); stack2 = new ArrayStack(); rear = 0; front = 0; } // Enqueue(Object) public void enqueue(Object item) { stack1.push(item); rear++; } // Dequeue public Object dequeue() { //System.out.println("The size of stack1 is " +stack1.size()); int size = stack1.size(); for(int i=0;i<size; i++){ //Pop the entire content of the first stack onto the second stack stack2.push(stack1.pop()); } //Now the first element is on the top of the second stack, //we now pop it off and return it. Object temp = stack2.pop(); size = stack2.size(); for(int i=0;i<size; i++){ //After the top most element is popped off, we push back all the //elements onto the first stack stack1.push(stack2.pop()); } rear--; return temp; } 3.[20 points] Consider the following question related to a doubly linked list DList which has a head and tail reference, as shown below. Write a method movemiddle that takes DLIst mylist as input and performs the following actions: I.Locates the middle node in the list II.Moves the middle node to the head of the list You can assume for this problem that the list contains an odd number of nodes. The class definitions for DNode and DList for the question are provided below. public class DNode { public DNode next, prev; public Object value; public DNode(DNode p, DNode n, Object v){ prev = p; next = n; value = v; } } DList class and its method declarations: public class DList{ public DNode head, tail; } public void movemiddle (DList mylist) { DNode fromHead = d.head; DNode fromTail = d.tail; DNode midnode = null; /* * Since we can assume that the number of nodes is odd, the following * logic is sufficient */ while (fromHead!=fromTail){ // n/2 times fromHead=fromHead.next; fromTail=fromTail.prev; } midnode = fromHead; midnode.previous.next = midnode.next; midnode.next.prev = midnode.prev; fromHead = d.head; midnode.prev = null; fromHead.prev = midnode; midnode.next = fromHead; d.head = midnode; return midnode; } 4. [15 points] Consider this question which uses a singly linked list SList. Write a method reverseorder that will reverse the order of input SList myslist. In other words, after reversal the node which was originally at the tail of the linked list should be at the head, the node that was originally at the head should be at the tail, and so forth. The SNode and SList classes for the question are provided below. Hint: Consider the use of a Stack or Queue and their associated methods, which you can assume are available. The question can also be completed without a Stack or Queue. public class SNode { public SNode next; public Object element; } public class SList { public SNode head; } public static void reverseorder(SList mylist) { SNode currentNode, nextNode, loopNode; if(mylist.head==null) return; currentNode=mylist.head; nextNode= mylist.head.next; loopNode=null; while(nextNode != null) { currentNode.next = loopNode; loopNode= currentNode; currentNode=nextNode; nextNode =nextNode.next; } mylist.head = currentNode; mylist.head.next = loopNode; } 5.[20 points] In lecture, we discussed the implementation of a CircularArrayQueue which grows from the bottom of an array (e.g. index 0) upward. In this question you will write the constructor, enqueue(Object) and dequeue() methods for a CircularQueueArray which starts at the top (e.g. array.length -1) of the array and grows downward. Consider the definition of the CircularQueueArray below in creating your methods. Your methods must consider what happens when the bottom of the array is reached. Class definition for CircularArrayQueue: public class CircularArrayQueue implements Queue { public final int DEFAULT_CAPACITY = 100; public int front, rear, count; public Object array[]; public CircularArrayQueue(); public void enqueue(Object); public Object dequeue(); } // Constructor public CircularArrayQueue() { front = rear = count = 0; array = (T[]) (new Object[DEFAULT_CAPACITY]); } public CircularArrayQueue (int initialCapacity) { front = initialCapacity-1; rear = initialCapacity-1; count = 0; array = ( (T[])(new Object[initialCapacity]) ); System.out.println("the value of array.length is " +array.length); } // Enqueue method /** * Adds the specified element to the rear of this queue, expanding * the capacity of the queue array if necessary. * * @param element the element to add to the rear of the queue */ public void enqueue (T element) { System.out.println("Rear is " +rear); if (size() == array.length) { rear = array.length-1; } array[rear] = element; if (rear == 0) rear = array.length-1; else rear = (rear-1) % array.length; count++; } // Dequeue method public T dequeue() throws EmptyCollectionException { if (isEmpty()) throw new EmptyCollectionException ("queue"); T result = array[front]; front = (front-1) % array.length; count--; return result; } 6. [10 points] You are given a populated singly linked list myslist of at least n nodes. Write a method ReturnListElement that returns the element of the nth node from the start of the list without deleting the node. Refer to question 4 for the definitions of SNode and SList. public static Object ReturnListElement (SList myslist, int n) { SNode mynode = null; SNode HeadNode = myslist.getHead(); int i=0; if(HeadNode.next == null){ return HeadNode; } while((HeadNode.next != null) && ( i < n )){ mynode = HeadNode; HeadNode = HeadNode.next; i++; } return mynode; }