Computer Science 136
Professor Bruce
Midterm Examination 2
April 30, 1997
Question
Points Score
1 10 ____
2 10 ____
3 16 ____
4 16 ____
5 10 ____
6 10 ____
TOTAL 72 ____
Your name (Please print)
____________________________________
I have neither given nor received aid on this examination.
____________________________________
(sign here)
1. ARRAY-BASED IMPLEMENTATIONS
In class we described an array-based implementation of queues that was made
more efficient by treating the array as if it were circular. Portions of the Java code are excerpted
below:
public class QueueArray implements Queue
{
protected Object data[]; // a array of the data
protected int head; // next dequeue-able value
protected int count; // no. elts in queue
public QueueArray(int size)
// post: create queue capable of holding size values.
{
data = new Object[size];
head = 0;
count = 0;
}
public void enqueue(Object value)
// pre: !isFull()
// post: the value is added to the tail of the structure
public Object dequeue()
// pre: the queue is not empty
// post: element at head of queue is removed and returned
public boolean isFull()
// post: returns true iff no space for new elements.
The add and remove methods add new elements to the right end of the queue and remove them from the left end. A deque (double-ended queue) is a variant of a queue in which elements can be added or deleted from either end.
Please define an array-based implementation of a deque as a subclass of QueueArray. To save time you need not include the body of remove_right, only the declaration (like those shown above). You must include the body of any other methods (e.g., add_left) and constructors included in the subclass. Please include both pre and post-conditions for all routines. Your grade will depend partially on how well you take advantage of the fact that this is being defined as a subclass. Please write your answer on the next page. Hint: "%" is the symbol for "mod" in Java.
1 continued:
2. The following tree is a min-heap, as defined in class (i.e., each node is smaller than any of its descendants).
a. Please show the contents of the array representing this heap:
b. Suppose we wished to add the element with priority value 13 to the heap. Please show the sequence of steps which would be taken in adding 13 to the heap and restoring it to be a heap. You may do this by drawing a sequence of pictures of trees (not arrays).
c. What is the worst-case complexity (using big "O" notation) of adding an element to a heap of n elements? Please justify your answer.
3a. Please write the time complexity of the following sorts. The options are:
O(1), O(log n), O(n), O(n log n), O(n2), O(n3), O(2n).
i. Insertion sort
average case:
worst case:
ii. Selection sort:
average case:
worst case:
iii. Quick sort
average case:
worst case:
iv. Merge sort
average case:
worst case:
v. Heap sort
average case:
worst case:
b. Which of these is the fastest on average for random data?
c. Describe an important case in which an insertion sort might be more appropriate (and efficient) than a quicksort. You may assume the array to be sorted is large.
d. Why is it more efficient (in both space and time) in the worst case to use a heap sort rather than building a binary search tree and then doing an in-order traversal?
4. Short answers
a. When we discussed iterators for trees, we found that using an algorithm with a stack produced one kind of traversal, whereas the same algorithm with a queue produced a different kind of traversal.
What kind of tree traversal did we get with a stack?
What kind of tree traversal did we get with a queue?
b. The predefined Java class Object has a method equals, with declaration:
public boolean
equals(Object other)
The interface Comparable, defined in the text, contains only the method:
public boolean lessThan
(Comparable item);
We defined the class ComparableInt with header:
public class
ComparableInt implements Comparable {
That class includes a method lessThan with types as in Comparable and also the following implementation of the method equals:
public boolean equals(Object other)
{
ComparableInt that = (ComparableInt)other;
return value() == that.value();
}
Note that the first thing done in the implementation is to cast other to ComparableInt. Why didn't we just define equals in ComparableInt to take a parameter of type Comparable or ComparableInt?
c. In an array implementation of trees (e.g., used with heaps), what is the upper bound on the amount of space necessary to represent a general binary tree with n nodes. Use big-"O" notation.
d. Why is the following section of code inefficient? Rewrite it so it is more efficient. Assume OtherClass has a constructor with no parameters and SomeClass has a parameterless method m which returns an object of type OtherClass.
public void someMethod(SomeClass
newOb)
{
OtherClass ob = new
OtherClass ();
ob := newOb.m();
...
}
e. Why is a heap implementation of a priority queue more efficient than using an ordered linked list or an ordered vector of elements?
f. What is the complexity of a search in a binary search tree in the worst case.
g. What is the complexity of a search in a splay tree in the worst case?
h. What is the advantage of the use of splay trees over regular binary search trees?
5. Alternate implementations of binary trees place more responsibility for operations on the objects of type BinaryTreeNode rather than on the tree. In this problem you are to implement one of these.
A BinaryTree method for performing an inorder traversal could simply ask the root to perform an inorder traversal, as follows:
public void inorder()
{
if (root != null) root.inorder();
}
Please write the code (including the header) for a method to perform an inorder traversal of the subtree headed by the node executing the method. This is to be a method for the class BinaryTreeNode which has instance variables:
protected Object val;
protected BinaryTreeNode parent;
protected BinaryTreeNode left;
protected BinaryTreeNode right;
When you actually "visit" the node, simply send it the message "doIt()", which you may presume is defined somewhere else in BinaryTreeNode.
6. One can rather easily design an O(n log n) algorithm for finding the kth largest element of an array of size n which sorts the array and then picks out the kth element of the sorted array. A more efficient procedure (in fact, it is O(n) on average) can be written which finds the kth smallest element in an unsorted array without first sorting the list. The algorithm uses a method Partition which is the one given in class with the QuickSort algorithm:
/**
post: Returns pivotIndex where table[left..pivotIndex-1] <=
table[pivotIndex] <= table[pivotIndex+1..right]
**/
protected int partition (int left, int right,
Comparable[] table)
You need not write partition. You may assume that it is given. You are to write a function which has the following specification:
/** PRE: 0 ¾ low ¾ n-1 ¾ high < elts.length.
POST: The value returned from FindNth is the nth
smallest element of elts.
**/
public Comparable findNth(Comparable[] elts,
int low, int high, int n)
The result of a call findNth(myElts,0,49,25) should return the 25th smallest element of myElts (i.e., the one that would be in slot 24 if the myElts were held in order). findNth(myElts,0,49,1) should return the smallest element in myElts. Your task is to write the body of the function procedure findNth.
Hint: If you use the partition
procedure to subdivide the array you will find that you can do something
reminiscent of a binary search even though the array is not sorted and the partition procedure does
not always divide the array in half.
Note: You will receive at most half credit for this problem if you sort the entire array.
You may write your answer on the next page.
Answer to 6: