CPS 100 -- Spring 1997
Group Assignment: Trees
These problems provide practice with trees, recursion, and big-Oh
Assume the following declarations have been made
struct Tnode
{
int info;
Tnode * left,* right;
Tnode(int val, Tnode * lbranch = 0, Tnode * rbranch = 0);
};
Tnode::Tnode(int val, Tnode * lbranch, Tnode * rbranch)
: info(val),
left(lbranch),
right(rbranch)
{}
The following function returns the height of a tree (for the problems
here we're using 0 for the height of an empty tree -- in other words height
is counting nodes rather than edges).
int TreeHeight(Tnode * t)
// postcondition: returns height of tree with root t
{
if (t == 0)
{
return 0;
}
else
{
return 1 + Max(TreeHeight(t->left),TreeHeight(t->right));
}
}
where the function Max returns the largest of its two integer
parameters.
Tree Diameter
The diameter of a tree (sometimes called the width) is the number
of nodes on the longest path between two leaves in the tree. The
diagram below shows two trees each with diameter nine, the leaves that
form the ends of a longest path are shaded (note that there is more than
one path in each tree of length nine, but no path longer than nine nodes).
The diameter of a tree T
is the largest of the
following quantities:
- the diameter of T's left subtree
- the diameter of T's right subtree
- the longest path between leaves that goes through the root of T
(this can be computed from the heights of the subtrees of T)
This leads directly to the following code:
int TreeDiameter(Tnode * tree)
// postcondition: returns diameter of tree
{
if (tree != 0)
{
int leftDiameter = TreeDiameter(tree->left);
int rightDiameter = TreeDiameter(tree->right);
int leftHeight = Height(tree->left);
int rightHeight = Height(tree->right);
// longest path through root
int rootPath = leftHeight + rightHeight + 1;
return Max(leftDiameter,Max(rightDiameter,rootPath));
}
return 0;
}
Write a recurrence relation for the running time of
TreeDiameter. The solution is greater than O(n), what
is the complexity of TreeDiameter?
It's possible to calculte the diameter in O(n) time. This requires
calculating the diameter and height in a bottom up manner. Fill in
the body of the function DoDiameter so that the postconditions
are satisfied which will make the new TreeDiameter find the
diameter in O(n) time.
int TreeDiameter(Tnode * tree)
{
int height,diameter; // only need diameter, height is dummy here
DoDiameter(tree,height,diameter);
return diameter;
}
void DoDiameter(Tnode * t, int & height, int & diameter)
// postcondition: sets height to height of tree t,
// sets diameter to diameter of t
{
if (t != 0
{
int leftHeight,rightHeight;
int leftDiameter, rightDiameter;
}
}
General Trees (4 points)
A tree in which each node can have an arbitray number of children, and
in which each node stores an integer, can be
implemented using the following declarations:
struct GTnode
{
int info;
GTnode * child; // first child of node
GTnode * sibling; // sibling of node
GTnode(int val, GTnode * kid = 0, GTnode * sib = 0)
: info(val),
child(kid),
sibling(sib)
{}
};
Write the routine TreeProduct whose header is given below.
TreeProduct returns the product of all the values stored in the
nodes of t. For example, it would return
12! = 479,001,600
for the tree diagrammed below. In the tree below, the solid arrows
represent the connections using the declaration for
GTnode
given above, the dotted arrows represent the ``conceptual''
children for each node of the tree.
By definition, the value returned for an empty tree is zero.
int TreeProduct(GTnode * t)
// postcondition: returns product of all nodes in t
// returns 0 if t is empty
Search/Isomorphism (12 points)
Two binary search trees
s and t are value equal if every value in
s is in t and every value in t is in
s. The shapes of the trees don't matter, the collection of
values stored in s must be the same as the collection stored
in t for trees to be value equal.
Part A (2 points)
Consider the functions below. If both s and t have n nodes,
reason about the running time of IsValueEqual. Then
describe how to determine if two trees are value equal
in O(n) time.
bool InTree(const string & s, Tree * t)
// postcondition: returns true if s in t, otherwise returns false
{
if (t != 0)
{
if (t->info == s) return true;
return InTree(s, t->left) || InTree(s, t->right);
}
return false;
}
bool FirstInSecond(Tree * s, Tree * t)
// postcondition: returns true if all values of s are in t
// returns false otherwise
{
if (s != 0)
{
if (InTree(s->info,t))
{
return FirstInSecond(s->left,t) &&
FirstInSecond(s->right,t);
}
return false;
}
return true;
}
bool IsValueEqual(Tree * s, Tree * t)
// postcondition: returns true if s is value equal to t,
// returns false otherwise
{
return FirstInSecond(s,t) && FirstInSecond(t,s);
}
Part B
Two binary trees s and t are
equivalent if they
have the same shape; the values stored in the nodes do not affect
whether two trees are equivalent. In the diagram
below, the tree in the middle is NOT equivalent
to the other trees, but the tree on the right IS equivalent
to the tree on the left.
Write a function IsEquivalent that returns true if its two tree
parameters are equivalent and false otherwise. You must also give the
big-Oh running time of your function with a justification.
Part C
Two trees s and t are isomorphic if
s can be transformed into t by swapping left
and right children of some of the nodes of s. The values in
the nodes are NOT not important in determining
isomorphism, only the shape is important. The trees
below are isomorphic because if the children of the nodes A, B, and G
in the tree on the left are swapped, the tree on the right is obtained.
Write a function IsIsomorphic that returns true if two trees
are isomorphic. You must
give the big-Oh complexity (in the average
case) of your function with a justification.