I have to find the maximum value in a binary tree. This is how I did it iteratively:
int maxValue(Node* node)
{
if (node == nullptr)
throw "BT is empty";
int max = node->data;
for (Node* left = node; left != nullptr; left = left->left)
{
if (left->data > max)
max = left->data;
}
for (Node* right = node; right != nullptr; right = right->right)
{
if (right->data > max)
max = right->data;
}
return max;
}
I don't know if this is the best way to do it. How can this be improved? Is there a recursive solution?
3 Answers 3
Trees are often most useful when they're sorted. If the tree is sorted, you can just descend into the right side of the tree.
Since we're assuming an unsorted tree, we have to search the whole thing. Let's build this up by cases. First assume that the current node has the largest value:
int maxValue(Node *node)
{
if (node == nullptr)
throw "BT is empty";
max = node->data;
return max;
}
Nice, but not likely. We can do better. What if the largest value is in the left side of the tree?
int maxValue(Node *node)
{
if (node == nullptr)
throw "BT is empty";
max = node->data;
if(node->left != nullptr) {
int leftMax = maxValue(node->left);
if(max < leftMax)
max = leftMax;
}
return max;
}
Great! Now we have a function that will check its left side for larger values, all the way down the left side. But what if the largest value is on the right of some node? We'd better cover that case too:
int maxValue(Node *node)
{
if (node == nullptr)
throw "BT is empty";
int max = node->data;
if(node->left != nullptr) {
int leftMax = maxValue(node->left);
if(max < leftMax)
max = leftMax;
}
if(node->right != nullptr) {
int rightMax = maxValue(node->right);
if(max < rightMax)
max = rightMax;
}
return max;
}
Now since we only have to check for NULL that will throw on the first node we can optimize slightly:
int maxValue(Node *node)
{
if (node == nullptr)
throw "BT is empty";
return maxValueNonNull(node, node->data);
}
int maxValueNonNull(Node* node, int currentMax)
{
if (node == NULL)
{ return currentMax;
}
currentMax = currentMax > node->data ? currentMax : node->data;
int leftMax = maxValueNonNull(node->left, currentMax);
int rightMax = maxValueNonNull(node->right, currentMax);
return leftMax > rightMax ? leftMax : rightMax;
}
That should do it.
-
1\$\begingroup\$ I'm not sure that I follow Loki Astari's edit -- it replaces a null check on each recursive call with a null check on each recursive call, and it adds unnecessary information to the call stack (currentMax). And on the leaf nodes it extends the call one level deeper than the original. Since I don't know the site's conventions I'll leave the edit, but wanted to add my thoughts on it. \$\endgroup\$GargantuChet– GargantuChet2014年12月05日 16:41:04 +00:00Commented Dec 5, 2014 at 16:41
-
\$\begingroup\$ What do you mean by "it replaces a null check on each recursive call with a null check on each recursive call"? Also, I'm not sure how
currentMaxis unnecessary information, it's the same asmaxin your original example (btw you didn't definemaxanywhere in your example). \$\endgroup\$user6607– user66072014年12月16日 16:37:06 +00:00Commented Dec 16, 2014 at 16:37 -
\$\begingroup\$ Thanks -- fixed the missing declaration, as it was unintentional. And I'm wrong, as either way the variable would be on the stack (local variable vs. argument to call), so it's probably a wash there. \$\endgroup\$GargantuChet– GargantuChet2014年12月16日 21:05:45 +00:00Commented Dec 16, 2014 at 21:05
-
\$\begingroup\$ Wow, I really did overlook the point of the edit. It keeps one null check per node -- but my original code would check twice. Loki Astari's edit reduces the number of null checks. On a largish tree, it's pretty certain that the branch prediction will cause "if (node == nullptr)" to settle on "false" as a default path pretty quickly. But it's still a valid alternate approach, to eliminate the extra check altogether. \$\endgroup\$GargantuChet– GargantuChet2014年12月16日 21:12:11 +00:00Commented Dec 16, 2014 at 21:12
-
\$\begingroup\$ Please note that N nodes have 2N pointers to children nodes, so a half of
leftandrightpointers are NULL. Clearly, all those pointers must be tested, whether we test fornode == NULLinside the function or forleftandrightbeing NULL before diving into the recursion. However, testing before the call saves us N of 2N calls at the expense of additionalif()instruction. \$\endgroup\$CiaPan– CiaPan2017年01月18日 19:40:55 +00:00Commented Jan 18, 2017 at 19:40
With most issues already mentioned, here is a simpler version of the code mentioned by GargantuChet. A recursive call to return the maximum value in a binary tree.
int getMax(Node* root){
if(root==NULL){
return Integer.MIN_VALUE; // the minimum value so that it does not affect the calculation
}
// return the maximum of the data of the current node ,its left child and its right child.
return Math.max(root->data, Math.max(getMax(root->left), getMax(root->right)));
}
-
\$\begingroup\$ Nice. It doesn't properly handle the case where root = null, although you could easily just say that the behavior of
getMax(null)is undefined. \$\endgroup\$GargantuChet– GargantuChet2017年01月19日 00:26:49 +00:00Commented Jan 19, 2017 at 0:26
why do you search left side of the tree, no need just one for loop enough since you are searching for Max number.
-
2\$\begingroup\$ Can you expand this into a more complete answer by explaining why it is not necessary to search the left side, and maybe showing an example of what the new code would look like? \$\endgroup\$Cody Gray– Cody Gray2017年01月18日 17:59:36 +00:00Commented Jan 18, 2017 at 17:59
-
\$\begingroup\$ @CodyGray I suppose Seham Ali assumed you have a BST, in which case the maximum value is stored in the rightmost node of a tree. \$\endgroup\$CiaPan– CiaPan2017年01月18日 19:20:40 +00:00Commented Jan 18, 2017 at 19:20
-
\$\begingroup\$ The point was to improve the answer, @cia. I personally know how a binary search tree works, but it isn't from reading this answer. \$\endgroup\$Cody Gray– Cody Gray2017年01月18日 19:21:55 +00:00Commented Jan 18, 2017 at 19:21
-
\$\begingroup\$ @CodyGray Oh, really...? \$\endgroup\$CiaPan– CiaPan2017年01月18日 20:19:39 +00:00Commented Jan 18, 2017 at 20:19
maxis initiallyINT_MAX, and if thedatafield is an int, it's not possible for the value ofdatato be more thanmaxalready is.) \$\endgroup\$node->left->right. Also, the answer isn't really a review of the code, but rather a description of DFS applied to finding the maximum value in a tree (that's really why I ask). \$\endgroup\$