- (10 points) Show the binary search tree that results when the
keys are presented in the following order:
300 150 40 80 450 600 550 200 800 20
- (10 points) Show the binary search tree that results if susan is deleted from the
tree below:
------nancy----------------
/ \
-fred- ---susan-------
/ \ / \
bonnie george peter zachary
/ \ \ /
charles nick sarah yifan
/ /
rebecca xavier
/
ralph
- (10 points) Show the result of doing a single left rotation about the node 500. Do not worry if the rotation increases the height of the tree. All I
care about is whether you know how to perform a rotation.
-300-
/ \
175 500
/ / \
100 400 600
/ / \
50 350 450
- (12 points) If we delete 60 from the following AVL tree
--100---
/ \
40 200
\ / \
60 150 400
/ \
125 175
we end up with the following binary search tree that is not a valid AVL
tree and hence needs to be re-balanced:
--100---
/ \
40 200
/ \
150 400
/ \
125 175
- Identify the bottom-most node
that violates the AVL condition and explain why
that node violates the AVL condition.
- In order to rebalance the tree do we have to use the zig-zig case
or the zig-zag case? Justify your answer.
- Use the proper rotation(s) to rebalance the above tree so that it
becomes a legitimate AVL tree.
- (10 points) Behold the following recursive function that computes and returns
the sum of an array of n numbers:
int sum(int numbers[], int start, int end) {
1) int middle = (start+end)/2;
2) return sum(numbers, start, middle) + sum(numbers, middle + 1, end);
}
Answer the following questions about this function:
- Why is this function incorrect? You must answer in 3 sentences or
less.
- Write the C++ code fragment that you must add to the above function to make
it compute the sum correctly and indicate the line
that it should be placed before or after (e.g., you might write
after line x where x is the line number). You may not modify
any code from the above function.
- (15 points) The greatest common divisor (gcd) of two non-zero numbers is the largest
positive integer that divides the numbers with a remainder of 0. For
example, the gcd of 48 and 20 is 4, the gcd of 48 and 12 is 12, and the
gcd of 12 and 12 is 12.
Euclid's algorithm is a recursive algorithm for finding the gcd of
two integers a and b that can be written as
the following C++ function:
int gcd(int a, int b) {
1) if (a == b) return a;
2) else if (a < b) return gcd(a, b-a);
3) else return gcd(a-b, b);
}
Suppose I have the following main function:
int main() {
1) int x = 48;
2) int y = 20;
3) cout << gcd(x, y) << endl;
}
In the stack diagram shown below, complete the stack frames
that exist when
the series of recursive calls finally arrives at the base case for
gcd.
- I
have started the stack for you by showing the frame for main.
- Each
stack frame should show 1) the name of the executing function,
2) the line number that is executing when it makes its function
call, and 3) the
values of the local variables/parameters.
- The final stack frame will
be the stack frame for the base case. It will not call a function so
for this final stack frame show the values of the variables and
the return value. You should not show the return values for any
other frame.
- The stack is going downwards, so successive frames should
appear under each other, with the frame for the base case being the
bottommost stack frame you fill in.
|----------------------------------------|
| main: |
| line: 3 |
| x: 48 |
| y: 20 |
|----------------------------------------|
| |
| |
| |
| |
| |
|----------------------------------------|
| |
| |
| |
| |
| |
|----------------------------------------|
| |
| |
| |
| |
| |
|----------------------------------------|
| |
| |
| |
| |
| |
|----------------------------------------|
| |
| |
| |
| |
| |
|----------------------------------------|
| |
| |
| |
| |
|----------------------------------------|
- (12 points) Behold the following 4 fragments of code:
(a)
int i, j;
int sum = 0;
for (i = 0; i < n*n; i++)
sum += i;
for (j = 0; j < n/2; j++)
sum *= j;
|
(b)
for (year = 0; year < 2000; year++) {
for (day = 0; day < 365; day++) {
if (n == year % day) {
printf("year = %d and day = %d\n");
}
}
}
|
(c)
int mystery(vector<int> &row, vector<int> &col) {
int i;
int result = 0;
for (i = 1; i < row.size(); i *= 2) {
result += row[i] * col[i];
}
return result;
}
|
(d)
In the following code, assume that the function f is O(n2)
int i, j;
int sum_f = 0, sum_loops = 0;
for (i = 0; i < n; i++) {
sum += f(i);
}
for (i = 0; i < n; i++) {
for (j = i; j < n; j++) {
sum += i * j;
}
}
if (sum_f > sum_loops)
cout << sum_f << endl;
else
cout << sum_loops << endl;
|
For each fragment of code, please circle its Big-O running time:
a O(1) O(log n) O(n) O(n log n) O(n2) O(n3) O(2n)
b O(1) O(log n) O(n) O(n log n) O(n2) O(n3) O(2n)
c O(1) O(log n) O(n) O(n log n) O(n2) O(n3) O(2n)
d O(1) O(log n) O(n) O(n log n) O(n2) O(n3) O(2n)
- (12 points)
a. array
b. vector
c. stack
d. deque
e. hash table
f. list
g. binary search tree
h. AVL tree
For each of the following questions choose the best answer from the
above list. Assume that the size of an array is fixed once
it is created, and that its size cannot be changed thereafter.
Sometimes it may seem as though two or more choices would
be equally good. In those cases think about the operations that the
data structures support and choose the data structure whose operations
are best suited for the problem.
You may have to use the same answer for more than one
question:
- ____________ The data structure you should use if you want to
implement a map that records the results of a 10K
race and the keys are the last names of the runners. The keys must
be kept in alphabetical order and the runners names will be entered
in the order that the runners finish the race (hence if "Joe"
finishes before "Barry" then "Joe" will be inserted first and then
"Barry").
- ____________ The data structure you should use if you want to
implement a map that records the results of a 10K
race and the keys are the race times of the runner. The keys must
be kept in sorted order and the race times will be entered
in the order that the runners finish the race (hence a runner with the time
15:21 will be inserted before a runner with the time 15:36).
- ____________ The data structure you should use if you want to
reverse a file by reading its lines, adding each line to the front of
the data structure, and then traversing the data structure from
front to back and printing the lines.
- ____________ The data structure you should use to store a collection of
emails where the emails are ordered by the time that they arrived and
they are inserted at the time that they arrived. You want to be able to
print the emails in sorted order by time of arrival, insert/delete emails,
and find emails.
- ____________ The data structure that is used to implement hashing with
linear probing when the size of the data is known in advance (the answer
is not a hash table--I want to know the data structure used to implement the hash table).
- ____________ The best data structure to use to implement the buckets
in separate chaining. Each bucket holds the key/value pairs that hash
to that bucket and new key/value pairs are typically added to the end
of the bucket.