Maximum Distance between nodes in a binary tree

Source: Internet
Author: User
Another solution of "the beauty of programming: finding the maximum distance of a node in a binary tree"

Yesterday I spent one night writing a book review on Douban for the beauty of programming, late book reviews and thoughts-for friends who love programming. Book reviews will not be reposted here. Instead, we will introduce another solution to one of the problems in this book. This solution is short and easy to read and reduces the space complexity, or you can say that it is "beautiful.

Problem definition

If we regard a binary tree as a graph, and the line between parent and child nodes is bidirectional, we would like to define "distance" as the number of edges between two nodes. Write a program to find the distance between the two nodes with the farthest distance in a binary tree.

Solution in the book

The analysis of this problem in the book is clear, and I try to briefly describe it in my own way.

There are two possible conditions for calculating the maximum distance of a binary tree:

  • Case A: the path goes through the deepest node of the Left subtree, and then to the deepest node of the right subtree through the root node.
  • Case B: the path does not pass through the root node, but is the maximum distance path of the Left or right subtree.

You only need to calculate the Path Distance between the two conditions and obtain the largest distance of the binary tree.

I cannot think of a better analysis method.

However, the implementation of the original text is not as clear as above (the source code can be downloaded from here ):

// Define the data structure struct node {node * pleft; // left subtree node * pright; // right subtree int nmaxleft; // The longest distance int nmaxright in the left subtree; // The longest-distance char chvalue in the right subtree; // value of the node}; int nmaxlen = 0; // find the longest two segments in the tree from void findmaxlen (node * proot) {// traverse to the leaf node and return if (proot = NULL) {return ;} // If the left subtree is empty, the maximum left distance of the node is 0 if (proot-> pleft = NULL) {proot-> nmaxleft = 0 ;} // if the right subtree is empty, the maximum right distance of the node is 0 if (proot-> pright = NULL) {proot-> nmaxrig Ht = 0;} // If the left subtree is not empty, Recursively search for the longest-distance left subtree if (proot-> pleft! = NULL) {findmaxlen (proot-> pleft);} // if the right subtree is not empty, Recursively search for the right subtree at the longest distance if (proot-> pright! = NULL) {findmaxlen (proot-> pright);} // calculates the longest node distance from the left subtree to if (proot-> pleft! = NULL) {int ntempmax = 0; If (proot-> pleft-> nmaxleft> proot-> pleft-> nmaxright) {ntempmax = proot-> pleft-> nmaxleft ;} else {ntempmax = proot-> pleft-> nmaxright;} proot-> nmaxleft = ntempmax + 1;} // calculate the longest node distance from the right subtree if (proot-> pright! = NULL) {int ntempmax = 0; If (proot-> pright-> nmaxleft> proot-> pright-> nmaxright) {ntempmax = proot-> pright-> nmaxleft ;} else {ntempmax = proot-> pright-> nmaxright;} proot-> nmaxright = ntempmax + 1 ;} // update the longest-distance if (proot-> nmaxleft + proot-> nmaxright> nmaxlen) {nmaxlen = proot-> nmaxleft + proot-> nmaxright ;}}

This code has several disadvantages:

  1. The algorithm adds intrusive Data nmaxleft and nmaxright.
  2. The global variable nmaxlen is used. Additional Initialization is required for each use. In addition, this function cannot be used in multiple threads even for different independent data.
  3. The logic is complex and there are also many null-related conditional tests.
My attempt

I think the core of this problem is that a and B need different information: A needs the maximum depth of the subtree and B needs the maximum distance of the subtree. As long as the function can calculate and return both information at the same time on a node, the code can be very simple:

#include <iostream>using namespace std; struct NODE {     NODE *pLeft;    NODE *pRight;}; struct RESULT {     int nMaxDistance;    int nMaxDepth;}; RESULT GetMaximumDistance(NODE* root){     if (!root)    {        RESULT empty = { 0, -1 }; // trick: nMaxDepth is -1 and then caller will plus 1 to balance it as zero.         return empty;    }    RESULT lhs = GetMaximumDistance(root->pLeft);    RESULT rhs = GetMaximumDistance(root->pRight);    RESULT result;    result.nMaxDepth = max(lhs.nMaxDepth + 1, rhs.nMaxDepth + 1);    result.nMaxDistance = max(max(lhs.nMaxDistance, rhs.nMaxDistance), lhs.nMaxDepth + rhs.nMaxDepth + 2);    return result;}
The code for calculating the result is clear; nmaxdepth is the depth of the left and right subtree plus 1; nmaxdistance is the maximum value of A and B.

To reduce the null condition test, if the node is null when entering the function, an empty variable is returned. It is strange that empty. nmaxdepth =-1 is used to treat the nonexistent (null) subtree as the maximum depth of 0 after the caller + 1.

In addition to improving readability, another advantage of this solution is to reduce the size of intrusive Data of O (number of nodes), instead of using the stack space of O (maximum depth of the tree. This design allows the function to have no side effects at all ).

Test code

The following test code is also provided for readers (pages are printed Based on 7th times, and nodes are numbered from top to bottom, left to right ):

int main(){    // P. 241 Graph 3-12     NODE test1[9] = { 0 };    Link(test1, 0, 1, 2);    Link(test1, 1, 3, 4);    Link(test1, 2, 5, 6);    Link(test1, 3, 7, -1);    Link(test1, 5, -1, 8);    cout << "test1: " << GetMaximumDistance(&test1[0]).nMaxDistance << endl;    // P. 242 Graph 3-13 left     NODE test2[4] = { 0 };    Link(test2, 0, 1, 2);    Link(test2, 1, 3, -1);    cout << "test2: " << GetMaximumDistance(&test2[0]).nMaxDistance << endl;    // P. 242 Graph 3-13 right     NODE test3[9] = { 0 };    Link(test3, 0, -1, 1);    Link(test3, 1, 2, 3);    Link(test3, 2, 4, -1);    Link(test3, 3, 5, 6);    Link(test3, 4, 7, -1);    Link(test3, 5, -1, 8);    cout << "test3: " << GetMaximumDistance(&test3[0]).nMaxDistance << endl;    // P. 242 Graph 3-14     // Same as Graph 3-2, not test     // P. 243 Graph 3-15     NODE test4[9] = { 0 };    Link(test4, 0, 1, 2);    Link(test4, 1, 3, 4);    Link(test4, 3, 5, 6);    Link(test4, 5, 7, -1);    Link(test4, 6, -1, 8);    cout << "test4: " << GetMaximumDistance(&test4[0]).nMaxDistance << endl;    return 0;}

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.