- (12 points) Your boss has asked you to choose between two algorithms. The
two algorithms have the following running times:
Algorithm 1: T(n) = n + 5n2 + 80
Algorithm 2: T(n) = 10000log n + 10000
- What is the Big-O running time of Algorithm 1?
- What is the Big-O running time of Algorithm 2?
- If the size of the input will be typically on the order
of n < 50. Which of the two algorithms should you choose and why?
- If the size of the input will be typically on the order
of n > 10000, which of the two algorithms should you choose and why?
- (14 points) For each of the following questions circle the best answer from the
above list.
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 what I said about them in class. Then
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.
a. vector
b. list
c. deque
d. map
e. set
f. multimap
g. multiset
h. hash table
- a b c d e f g h You want to get the distribution of exam scores by counting the number of exams in the range 0-9, 10-19, 20-29, ..., 90-100. You are guaranteed that the exam scores range from 0-100.
- a b c d e f g h You have a test bank of questions and you want to ensure that the test-taker is never presented the same question twice. You decide you want to store the questions that the test-taker has seen. You do not need to keep the questions in sorted order. The two operations you need to perform are insert to insert a question that has been presented to the test-taker and find to determine if a question is in the data structure. You may assume that each question is identified by a unique label.
- a b c d e f g h You are implementing a router for the internet which receives packets from various locations and transmits them to other locations. As packets arrive they should be placed at the end of the "line" and packets should be removed from and transmitted from the front of the "line".
- a b c d e f g h You are implementing a diary program that stores dates and locations that the diarist visited on that date. The values are kept as (date, location) pairs. It is important to keep the dates in chronological order and a person may visit multiple locations on the same dates (hence there could be multiple pairs that start with the same date).
- a b c d e f g h You want to reverse the lines in a file by storing the lines in the same order they are stored in the file (i.e., add each line to the back of the data structure) and then traversing the data structure from back to front once you finish reading all the lines from the file.
- a b c d e f g h You want to implement a to-do list where the user can both add and delete items in arbitrary places in the list. The to-do list is not kept in any type of order.
- a b c d e f g h You are keeping track of the number of times that each IP (internet) address has accessed your web-site. Each time an IP address accesses your web-site, you access that address in your data structure and increment its count by 1. You decide that it is important to keep the IP addresses in sorted order so that you can perform range queries on them. Each IP address is unique.
- (10 points) Suppose I have the following declarations and code:
string a, b;
string *x, *y;
Also suppose that the above variables are assigned the following memory addresses:
a: 0x1000
b: 0x1100
x: 0x1200
y: 0x1204
After each of the following code sequence executes, what are the values of a, b, x,
and y? Assume that code segments 1 and 2 execute independently (i.e., code
segment 2 does not execute after code segment 1.
Code Segment 1
x = &b;
*x = "Smiley";
y = x;
*y = "Brad";
b = *x;
Code Segment 2
x = new string("Michelle"); // address of new string = 0x2000
a = *x;
y = new string("Charles"); // address of new string = 0x2100
x = y;
b = *x;
Code Segment 1 Code Segment 2
a: _______________________ a: _______________________
b: _______________________ b: _______________________
x: _______________________ x: _______________________
y: _______________________ y: _______________________
*x: _______________________
*y: _______________________
- (6 points) Suppose you are given the following code:
class Picture {
public:
ifstream *sourceFile;
int rows;
int cols;
};
Picture *p;
string *name1, *name2;
name1 = new string("Hank Aaron");
name2 = name1;
delete name1;
p = new Picture();
p->sourceFile = new ifstream();
p->rows = 30;
p->cols = 40;
*name2 = "Hammerin Hank Aaron";
p->sourceFile->open("mountain.jpg");
Answer the following questions about the above code:
- __________________________________ This term is used to describe what
name2 becomes after name1 is deleted.
- What is likely to happen when p->sourceFile->open is executed
and why is it likely to happen? Use no more than 3 sentences for your
answer.
- (8 points Suppose I want to insert n telephone numbers into the following
data structures and then perform n finds, one for each of
the telephone numbers. For each of the following three data structures
give the total Big-O running time for the find and insert
operations (i.e., I do not want the running time for a single insert operation
but for all n insert operations). Make the following assumptions:
- For the list and vector, assume that new telephone numbers
are always added to the beginning of the data structure.
- For the hash table give me the average case
running time.
Data Structure | Insert | Find |
Map | | |
Hash Table | | |
List | | |
Vector | | |
- (10 points) The following
code is reading the first and last names of individuals and is keeping
track of all of the first names that are associated with a last name.
For example, if the input is:
Brad VanderZanden
Smiley VanderZanden
Minnie Mouse
Mickey Mouse
Ebby VanderZanden
then the set {Brad, Ebby, Smiley} will be associated with "VanderZanden"
and the set {Mickey, Minnie} will be associated with "Mouse".
typedef set <string> fnset;
map <string, fnset> lnames;
string fn, ln;
fnset firstnames;
while (cin >> fn >> ln) {
firstnames = lnames[ln];
firstnames.insert(fn);
lnames[ln] = firstnames;
}
- Explain why the following code is
inefficient (it computes the correct result but is inefficient).
Use no more than 3 sentences to describe the problem.
- How could you rewrite the code to fix the inefficiency. Only
modify that portion of the code that needs to be changed.
- (12 points) Assume you have the following declaration:
class ListNode {
public:
string name;
ListNode *next;
ListNode *prev;
ListNode(string n) : name(n) {}
};
Further suppose that a series of inserts have created the following list:
The code below is supposed to move the node containing "Ben" so that it
is between "Nancy" and "Sarah". However, the code eventually seg faults
and there are some other issues with the code as well.
1) ListNode *nextNode = currentNode->next;
2) currentNode->prev = currentNode->prev->prev;
3) currentNode->next = currentNode->prev;
4) nextNode->prev = currentNode->prev;
5) currentNode->prev->prev = currentNode;
6) currentNode->next->next = nextNode;
- Draw the diagram that results when the code above is executed
up until the statement that seg faults
(include nextNode in the diagram). Do not include the seg faulted
statement or the effects of executing any statement after the seg
faulted statement.
- Which statement seg faults? ________________________
- What does the seg faulting statement appear to be trying
to accomplish? Please say something like "it was trying to make
Sarah's next field point to Ben's node".
- One reason the above code is buggy is because it tries to
avoid using temporary variables by traversing multiple pointers
in a single expression (e.g., current->next->next). These types
of multiple traversals often result in buggy code. Re-write the
above code so that 1) it successfully places the node containing "Ben"
between the nodes containing "Nancy" and "Sarah", and 2) it
is easier to read by introducing an additional temporary variable
and eliminating multiple pointer traversals (i.e., in any
pointer expression, there should be only one ->).
- (10 points) Assume you have the following code:
class Person {
public:
string name;
Person *bestFriend;
Person(string n) { name = n; }
};
string names[] = { "mickey", "bugs", "daffy", "winnie" };
list<Person *> friends;
Person *newPerson;
Person *lastPerson;
int i;
lastPerson = NULL;
for (i = 0; i < 4; i++) {
newPerson = new Person(names[i]);
newPerson->bestFriend = lastPerson;
friends.push_back(newPerson);
lastPerson = newPerson;
}
Draw a diagram that shows the list, the Person objects that
get created, and the objects to which each pointer points when the
code has finished execution. Make sure that:
- You draw the sentinel nodes for the list
- You show the objects to which
newPerson and lastPerson point.
- You show the objects to which the bestFriend pointers point.
- You show the objects to which each list node points