Name: Section: TA: Expected Score (Just Guess) :: CSE 143, Summer 1995 Final Exam (100 Points) Date: 8/18/95
Name: Section: TA: Expected Score (Just Guess) :: CSE 143, Summer 1995 Final Exam (100 Points) Date: 8/18/95
Name:
Section:
TA:
Expected Score (just guess):
1 (8)
2 (10)
3 (10)
4 (4)
5 (8)
6 (8)
7 (10)
8 (6)
9 (10)
10 (10)
11 (4)
12 (4)
13 (8)
TOTAL (100)
1
In the problems in this test, assume the following declarations:
class Node {
public:
Node(int in_data, Node* in_next);
int data;
Node* next;
};
class List {
public:
List();
private:
Node* head;
};
List::List()
{
head = NULL;
}
2
1. [8 points] Pointers and Dynamic Memory
In each of the following pictures, assume
Node* x, y;
and show the effect of executing the following statement (by changing the appropriate data/point-
ers). Also, circle any garbage and cross out any Node returned to free memory and draw in new
nodes as appropriate.
(a) y = new Node(10, y);
x 3 1 5 2 4
10
y
x 3 13 5 2 4
x 3 1 5 2 4
x 3 1 5 2 4
3
2. [10 points] Add a get_size() member function to the List class. Also add a get_size() mem-
ber function to the Node class. The former should call the latter to return the size of the
list. The latter should be a recursive function. Show both the specification and the imple-
mentation of both functions.
SOLUTION:
class Node {
public:
int get_size() const;
};
class List {
public:
int get_size() const;
};
4
3. [10 points] Implement the function to reverse the elements of a List object.
The prototype of this member function of the List class looks like this:
void List::reverse();
You may define other functions to help you write this one.
SOLUTION 1 (iterative):
void List::reverse()
{
if ((head == NULL) || (head->next == NULL)) {
return;
}
SOLUTION 2 (recursive):
void Node::reverse(Node* p, Node*& tail)
{
if (next == NULL) { // base case, when you reach the last node
next = p; // p points to the previous node
tail = this; // tail is the pointer to the last node
return;
} else { // recursive case
next->reverse(this, tail);
next = p; // a chain reaction to reverse all pointers
}
}
void List::reverse()
{
if (head) {
head->reverse(NULL, head);
}
}
5
4. [4 points] Imagine that you’re working on a large project with a number of nice but not
too smart other people. You know that your colleagues assume that any code that com-
piles is perfectly okay.
class myString {
public:
myString();
~myString();
private:
int length;
char* theString;
};
There are at least 4 unsafe features in the class definition and for each unsafe feature, suggest a
better way to write C++ code. You may simply modify the code above to show what changes you
suggest. You may not add or remove an entire member funciton or data member.
SOLUTION is in red. It will be easier to pick up the solution using a color terminal and look at
the postscript version of the solution.
6
5. [8 points] C++ classes
(a) [4] In C++, 4 member functions have default behavior, i.e., they do not need to be explicitly
declared by you. What are those 4 member functions? Be as specific as possible.
• default constructor
• copy constructor
• destructor
• assignment operator
(b) [4] Under what circumstances would you like to define each of the four member functions
mentioned above?
• default constructor - e.g. to initialize an object with proper values when the object is defined.
• copy constructor - e.g. when shallow copying is not acceptable.
• destructor - e.g. when it is necessary to destroy dynamically allocated objects.
• assignment operator - e.g. when shallow copying is not acceptable.
7
6. [8 points] Consider linked list implementations.
(a) What is the major advantage of using the head node implementation?
• Don’t have to deal with the special case that the head pointer may need to be changed.
• This makes insertion and deletion of nodes in a list easier to write.
(c) What is the major advantage of using a linked list over an array implementation of a list?
(d) What is the advantage of using dynamic arrays (growing and shrinking arrays) over pointer
implementation of a linked list?
8
7. [10 points] Time Complexity
(a) Why do we use big-oh notation to describe the time complexity of algorithms rather than
directly reporting running times?
• Running times are machine dependent.
• An estimate of the worst case scenario.
• Simple to use because we drop constants and only keep the dominant term.
Give the worst-case run-time of the following functions
(b) O(n2)
int runMe(int n)
{
int result = 0;
for (int i = 0; i < (n/100); i+=2) {
for (int j = 0; j < 10; j++) {
for (int k = -10; k < 5*n; k++) {
result += k;
}
}
}
}
(c) O(n)
// assume pow(2,n) computes 2n in constant time.
int runMeToo(int n)
{
int i, result = 0;
for (i = 1; i < pow(2, n); i*=2)
result += i;
}
(d) O(log a)
int fun(int a)
{
if (a <= 1) {
return 1;
} else {
return 1 + fun(a/5);
}
}
(e) O(2a)
int fun(int a)
{
if (a <= 5) {
return 1;
} else {
return fun(a - 1) + fun(a - 3);
}
}
9
8. [6 points] Identify the major problem in each of the following functions:
(a)
• inaccessible object (*y) because y’s object is no longer accessible when this function returns.
(b)
• returning the address of an object (y) which will be deallocated when this function returns.
(c)
10
9. [10 points] To create a binary search tree, we can repeatedly apply the binary search tree inser-
tion algorithm until all values have been inserted.
(a) [4] For the following integer sequences, show the binary search tree that results from insert-
ing in the specified order: 3, 2, 1, 9, 7, 8, 5, 4, 6.
2 9
1 7
5 8
4 6
(b) [2] Give the order in which nodes of this tree are visited by preorder traversal.
• 321975468
(c) [2] Give the order in which nodes of this tree are visited by inorder traversal.
• 123456789
(d) [2] Give the order in which nodes of this tree are visited by postorder traversal.
• 124658793
11
10. [10 points] A ternary tree is a tree with at most three children per node and with each
child designated as left, right, or middle child.
(a) [4] Write the type declarations necessary to implement a ternary tree as a linked structure
with each tree node represented as a Ternary_Node class. Each node needs to contain an int
value. (Solution in red)
class Ternary_Node {
public:
void preorder_print(ostream& ost) const;
private:
int data;
Ternary_Node* left;
Ternary_Node* middle;
Ternary_Node* right;
};
(b) [6] Write a preorder traversal algorithm for this ternary tree. The preorder traversal function
should be a member function of the Ternary_Node class. It should print the int values of the
nodes while traversing the tree.
12
11. [4 points] Consider the following code:
class Birthday {
public:
Birthday(int day, int month, int year);
private:
int day, month, year;
};
class Grand_Parent {
public:
Grand_Parent(const Birthday& birthday);
private:
Birthday my_birthday;
};
Parent::Parent()
{
data = 0;
}
(a) [2] What are two compilation problems in the code above?
• A problem in Grand_Parent, my_birthday, because Birthday does not have a default construc-
tor.
• Another problem in Parent’s default constructor, because Grand_Parent does not have a default
constructor.
(b) [2] How can the compilation problems be removed? (You may just change the code above.
You don’t have to rewrite anything that is not necessary.)
• Provide a default constructor in each case.
• Rewrite the Parent’s constructor to use an initailizer.
• Rewrite the Grand_Parent’s data member to use a pointer and allocate a Birthday object in the
constructor.
• Many many other solutions.
13
12. [4 points] Consider the following code:
class Grand_Parent {
// ...
};
For each of the following, say if there is a compilation error. If not, say if there is a potential run
time error.
(a)
• okay.
(b)
• compilation error.
(c)
• okay.
(d)
14
13. [8 points] Consider the code below:
class Person {
public:
Person(long in_ssn): ssn(in_ssn) {}
virtual void write(ostream& ost) { ost << “Person: “ << ssn << endl; }
protected:
long get_ssn() const { return ssn; }
private:
long ssn;
};
What should be the output from the following code? (Solution in red)
15