This lab is designed to give you experience with thinking about how to solve a problem in the most efficient way possible. For this lab you will not have to turn in programs. Instead you will turn in an ascii text file that contains your solutions.
10
/ \
/ \
5 15
/ \
/ \
3 20
\
25
/
22
your routine should print:
0 10 1 5 1 15 2 3 2 20 3 25 4 22For full credit your routine must run in linear time (i.e., proportional to the number of nodes in the tree). Assume you have the class definition:
class treenode {
public:
int value;
treenode *left_child;
treenode *right_child;
};
void print_levels(treenode *root)
printLevels seed child_probability max_depthseed is a seed for the random number generator that will be used to generate children and values for the children. child_probability gives the probability that a left child or right child will exist. It must be a real number between 0 and 1. max_depth is the maximum depth of the tree. Without max_depth the tree generator routine may get into an infinite recursion because it will keep trying to generate children.
The test program first prints out the generated tree and then calls your print levels function. The test program prints one node per line and indents each level by two spaces. For example, the above tree would be printed as:
10
5
3
----
----
----
15
----
20
----
25
22
----
----
----
Your first reaction might be that you can do multiplication in O(1) time using a machine-level instruction so why bother. Technically this is wrong. Machine-level instructions cannot accomplish their task in O(1) time. They only appear to do so by limiting integers to 32 or 64 bits. Further, they may well use a hard-wired version of the algorithm that you will be developing. Another reason to care is that some scripting languages implement arbitrarily large-sized integer multiplication and hence cannot complete integer multiplication in one step using 32 or 64 bit multiplication instructions.
The obvious algorithm for doing multiplication using only addition is:
int multiply(int factor1, int factor2) {
int multiplier = (factor1 < factor2) ? factor1 : factor2;
int multiplicand = (factor1 > factor2) ? factor1 : factor2:
int product = 0;
for (int i = 0; i < multiplier; i++)
product += multiplicand;
return product;
}
This algorithm runs in O(min(factor1, factor2)). It is a linear time
algorithm (actually it is considered an exponential time algorithm
because
numbers can be represented with log n bits and hence "n" is considered
to be the number of bits--thus a linear time
algorithm must require no more than a constant factor of log n
steps). You can obtain an O(min(log factor1, log factor2)) algorithm
if you use addition and bit shifts (as just discussed, this algorithm
is actually considered linear). Write such an algorithm using
C-code.
Hints
a = 14; b = 3; a & b = (1110 & 0011) = 0010 = 2Bit-wise and can prove helpful for inspecting the bits of an integer. In the above example 3 was used to extract the first two bits of 14.
node *find(node *current_node, int key) {
if (current_node == 0)
return 0;
else if (current_node->key == key)
return current_node;
else if (current_node->key < key)
return find(current_node->left_child, key);
else
return find(current_node->right_child, key);
}
If we instead make the left and right children point to sentinel
nodes then the first two lines of the find function could be
eliminated, since we could ensure that even if the key is not in the
tree, the search will terminate when a sentinel node is reached. The
problem is that if each child points to its own sentinel node we would
have to initialize all the sentinal nodes before performing the search
and that would be expensive. How can we solve this problem and make
it feasible to use sentinel nodes?
matrix n seedwhere seed is a seed for the random number generator that creates entries in the matrix.
Hints
Submit an ascii text file named lab5-solutions. Do not submit an MS Word document. We are not a Windows shop and the TAs may not have access to Windows tools.