您的位置:首页 > 其它

求二叉树中两个节点最远的距离

2016-06-21 17:03 615 查看
一说到二叉树,就有很多题目,今天在编程之美中看到了二叉树中两个节点最远的距离。所以给想借机写一篇博客。

在开始之前,我们先想想,两个最常节点的最远距离是怎么样的?

情况一:最大距离可能一个在左子树,一个在右子树中,通过根节点;



情况二:也可能出现在左/右子树中,不经过根节点。



大体就是这样,我们要如何来解决呢?

给大家看看《编程之美》中它是如何决解的:

<span style="font-size:24px;">// 数据结构定义
struct NODE
{
NODE* pLeft; // 左子树
NODE* pRight; // 右子树
int nMaxLeft; // 左子树中的最长距离
int nMaxRight; // 右子树中的最长距离
char chValue; // 该节点的值
};

int nMaxLen = 0;

// 寻找树中最长的两段距离
void FindMaxLen(NODE* pRoot)
{
// 遍历到叶子节点,返回
if(pRoot == NULL)
{
return;
}

// 如果左子树为空,那么该节点的左边最长距离为0
if(pRoot -> pLeft == NULL)
{
pRoot -> nMaxLeft = 0;
}

// 如果右子树为空,那么该节点的右边最长距离为0
if(pRoot -> pRight == NULL)
{
pRoot -> nMaxRight = 0;
}

// 如果左子树不为空,递归寻找左子树最长距离
if(pRoot -> pLeft != NULL)
{
FindMaxLen(pRoot -> pLeft);
}

// 如果右子树不为空,递归寻找右子树最长距离
if(pRoot -> pRight != NULL)
{
FindMaxLen(pRoot -> pRight);
}

// 计算左子树最长节点距离
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;
}

// 计算右子树最长节点距离
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;
}

// 更新最长距离
if(pRoot -> nMaxLeft + pRoot -> nMaxRight > nMaxLen)
{
nMaxLen = pRoot -> nMaxLeft + pRoot -> nMaxRight;
}
}</span>

这段代码有几个缺点:

1.算法加入了侵入式(intrusive)的资料nMaxLeft, nMaxRight

2.使用了全局变量 nMaxLen。每次使用要额外初始化。而且就算是不同的独立资料,也不能在多个线程使用这个函数

3.逻辑比较复杂,也有许多 NULL 相关的条件测试。

而,我想了想,写出了这样的代码:
<span style="font-size:24px;">void _FindMaxDis(BSTreeNode *pNode, int &deepth, int &maxdis) //这里的两个数,我都用的是引用,读者知道为什么?
{
if (pNode==NULL)
{
deepth=0;maxdis=0;
return;
} </span>
<span style="font-size:24px;">    int l_deepth=0,r_deepth=0;
int l_maxdis=0,r_maxdis=0;

if (pNode->m_pleft)
FindMaxDis(pNode->m_pleft,l_deepth,l_maxdis);
if (pNode->m_pright)
FindMaxDis(pNode->m_pright,r_deepth,r_maxdis);

deepth = (l_deepth > r_deepth ? l_deepth : r_deepth) + 1;

maxdis = l_maxdis > r_maxdis ? l_maxdis : r_maxdis ;

maxdis = (l_deepth+r_deepth) > maxdis ? (l_deepth+r_deepth) : maxdis;

}</span>
<span style="font-size:24px;">
int FindMaxDis(BSTreeNode *pNode)
{
int deepth, maxdis;
_FindMaxDis(pNode,deepth,maxdis);

return maxdis;
}  </span>
其实做做这个题,大体思路都是一致的。但是,我们要考虑很多。在这个方面,推荐读者去看看《代码大全》
我来说一说这个代码的好处吧。

提高了可读性,另一个优点是减少了 O(节点数目) 大小的侵入式资料,而改为使用 O(树的最大深度) 大小的栈空间。

本博文只是对二叉树中两个节点最远的距离的解法,做了粗略的概述,如有更好的解法或者不同的看法,请留言。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息