求二叉树中两个节点最远的距离
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>
我来说一说这个代码的好处吧。
提高了可读性,另一个优点是减少了 O(节点数目) 大小的侵入式资料,而改为使用 O(树的最大深度) 大小的栈空间。
本博文只是对二叉树中两个节点最远的距离的解法,做了粗略的概述,如有更好的解法或者不同的看法,请留言。
在开始之前,我们先想想,两个最常节点的最远距离是怎么样的?
情况一:最大距离可能一个在左子树,一个在右子树中,通过根节点;
情况二:也可能出现在左/右子树中,不经过根节点。
大体就是这样,我们要如何来解决呢?
给大家看看《编程之美》中它是如何决解的:
<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(树的最大深度) 大小的栈空间。
本博文只是对二叉树中两个节点最远的距离的解法,做了粗略的概述,如有更好的解法或者不同的看法,请留言。
相关文章推荐
- bss、data和rodata区别与联系
- TCP协议中的三次握手四次挥手问题
- Asp.net中防止用户多次登录的方法
- 第三次冲刺--软件工程
- Hi-Fi
- 线程池
- iOS申请邓白氏总结
- c写Python扩展模块
- view基础知识介绍(一)
- C#取得站点跟目录
- android之对话、单复框的使用
- 关于循环的一个有趣的事情是!
- 【ICU】【2.3】如何在2.3中编译ICU资源
- 深入解析Python中的__builtins__内建对象
- Crash 解决(2)
- Dagger2 小结
- Linux常用命令汇总-cut
- 刨根问底:什么是yum源,yum的工作原理又是什么
- 《Spring实战》学习笔记-第七章:Spring MVC进阶
- pandoc文档书写