编程之美(二)求二叉树中两节点的最大距离

来源:互联网 发布:第三方支付有哪些 知乎 编辑:程序博客网 时间:2024/06/02 02:13

一,非递归算法:



求二叉树最短距离的步骤:

最大距离有两种可能:

1.距离最大的两个结点在根结点的两侧

2.距离最大的两个结点在根结点的其中一棵子树上,然后以根结点的左孩子或右孩子为子树的根结点,递归的找这颗子树上分布在根结点两侧的距离最大的两个结点。


对二叉树进行深度遍历,先从左子树往下走,把一路走来的所有结点都压栈,一直找到最下面的叶子结点A。把这个叶子结点记录为已访问,然后弹出。回到它的上一结点root。记录root到A的距离为1。然后进入右子树。从节点B往左走,一直从左子树往下走,走到最下面的叶子结点E。然后弹出E,把E记录为已访问。回到结点D,记录D到E的距离为1.然后往右子树走,找到叶子结点F,将其压栈,然后弹出,记录叶子结点F已访问,回到D。记录D到F的距离为1.

然后计算得最大距离为E到F的距离2(即第一种情况,把D当做根结点,E和F位于其两侧,距离为2),记为maxLen=2。

计算完后,将D记录为已访问并弹出,回到结点C。先计算C到它下面左子树最远的结点的距离,因此C的node_maxLeft为2。然后算C到它右子树下面最远结点的距离,本例中C的右子树为空,因此C的node_maxright为0。然后最大值maxLen = max( maxLen, node->maxLeft + node->maxRight ) = 2;

将C记为已访问,并弹出,回到结点B。直接算B到它左子树下面最远结点的距离(因为它的左子树已经遍历过),B的node_maxLeft为  C的node_maxLetf+1  ,为3.

然后访问B的右子树,从G开始访问,一直到叶子结点I。弹出I,并将I记录为已访问,回到H,记录H到I的距离为1.H的node->maxLeft=0,node->maxRight=1.所以maxLen = max( maxLen, node->maxLeft + node->maxRight )依然为2.

将H记为已访问并弹出,回到结点G。同样可以算出G的node->maxLeft=0,G的node->maxRight=2. 则maxLen = max( maxLen, node->maxLeft + node->maxRight )为2.

将G记为已访问并弹出,回到结点B。同样可以算出B的node-maxLeft = 3.(其实在第一次回到结点B时已经算过它的值了)。node->maxRight = 3.则B树的结点的最大距离为

maxLen = max( maxLen, node->maxLeft + node->maxRight ),为6.

将B标记为已访问并弹出,这时就回到了根结点root。其实这时我们已经计算出根结点的左子树下面两个结点的最大距离,和右子树下面两个结点的最大距离。现在再计算一下根结点的左边的叶子结点到右边的叶子结点的最大距离,就可以了。

计算root到左子树的最大距离node->maxLeft为1.root到右子树的最大距离为 node->maxRight = max( node->right->maxLeft,node->right->maxRight ) + 1,为4.

则maxLen = max( maxLen, node->maxLeft + node->maxRight )依然为6.

这时得到的就是最大距离。





总结:

本例其实是采用递归的方法来解决问题。

用深度遍历。先找到左子树下的节子结点。然后返回,并在返回过程中,把每个结点做为根结点,记算它下面的所有结点的最大距离。这样一直搜索,从左子树到右子树,找到所有以该节点为树的结点的最大距离。最终返回到根结点,记算根结点下左子树的最远叶子结点到右子树的最远叶子结点的距离,跟之前的比较,得出一个最大距离,即为二叉树中结点的最大距离。


其实整个过程都是同一种递归方法。从最下面的叶子结点开始,一层层的算最大距离。最后把最大距离给输出出来。



代码如下(代码系转载):

#include <stack>#include <algorithm>#include<iostream>using namespace std;struct Node{    bool _visited;    Node* left;    Node* right;    int maxLeft;    int maxRight;    Node()    {        _visited = false;        maxLeft = 0;        maxRight = 0;        left = NULL;        right = NULL;    }};int maxLen   = 0;stack<Node*> nodeStack;void findMaxLen( Node* root ){    Node* node;    if ( root == NULL )     {        return ;    }    nodeStack.push( root );    while( !nodeStack.empty())    {        node = nodeStack.top();        if ( node->left == NULL && node->right == NULL )//左孩子为空 且 右孩子为空        {            nodeStack.pop();            node->_visited = true;            continue;        }        if ( node->left )  //左孩子不为空        {            if ( !node->left->_visited ) //左孩子不为空 且 未访问,将左孩子压栈            {                nodeStack.push( node->left ) ;            }                        else //左孩子不为空,但是已访问            {                node->maxLeft = max( node->left->maxLeft,node->left->maxRight ) + 1;            }        }        if ( ( !node->left || node->left->_visited ) && node->right ) //(左孩子为空 或者 左孩子已访问) 且右孩子不为空        {            if ( !node->right->_visited )//右孩子未访问,将右孩子压栈            {                nodeStack.push( node->right ) ;            }                        else //右孩子已访问            {                node->maxRight = max( node->right->maxLeft,node->right->maxRight ) + 1;            }        }        if (( !node->left || node->left->_visited ) && ( !node->right || node->right->_visited ))//(左孩子为空 或者 左孩子已访问)且        {                                                                                        // (右孩子为空 或者 右孩子已访问)            maxLen = max( maxLen, node->maxLeft + node->maxRight );            node->_visited = true;            nodeStack.pop();            //弹出栈顶元素        }    }}int main(){    Node *tmp ;    Node* root = new Node();    //tmp = new Node();//建立一个二叉树    //root->left = tmp ;    //tmp = new Node();    //root->right = tmp;    //tmp = new Node();    //root->right->right = tmp;    //tmp = new Node();    //root->right->right->right = tmp;    //tmp = new Node();    //root->right->right->right->left = tmp;tmp = new Node();//建立一个二叉树    root->left = tmp ;tmp = new Node();root->right = tmp;tmp = new Node();root->right->left = tmp;tmp = new Node();root->right->left->left = tmp;tmp = new Node();root->right->left->left->left = tmp;tmp = new Node();root->right->left->left->right = tmp;tmp = new Node();root->right->right = tmp;tmp = new Node();root->right->right->right = tmp;tmp = new Node();root->right->right->right->right = tmp;    findMaxLen( root );    cout << maxLen << endl;system("pause");    return 0;}


原创粉丝点击