二叉树分析(两点最大距离)
转载自:http://blog.csdn.net/lalor/article/details/7626678 http://blog.csdn.net/lalor/article/details/7618120
把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两节点之间边的个数。写一个程序求一棵二叉树中相距最远的两个节点之间的距离。
书上的解法
书中对这个问题的分析是很清楚的,我尝试用自己的方式简短覆述。
计算一个二叉树的最大距离有两个情况:
- 情况A: 路径经过左子树的最深节点,通过根节点,再到右子树的最深节点。
- 情况B: 路径不穿过根节点,而是左子树或右子树的最大距离路径,取其大者。
只需要计算这两个情况的路径距离,并取其大者,就是该二叉树的最大距离。
代码参考编程之美,或者http://www.cnblogs.com/miloyip/archive/2010/02/25/1673114.html
这段代码有几个缺点:
- 算法加入了侵入式(intrusive)的资料nMaxLeft, nMaxRight
- 使用了全局变量 nMaxLen。每次使用要额外初始化。而且就算是不同的独立资料,也不能在多个线程使用这个函数
- 逻辑比较复杂,也有许多 NULL 相关的条件测试。
在看到这题的时候,我没有马上看答案,而是自己思考了一会,得出如下思路,最后跟http://www.cnblogs.com/miloyip/archive/2010/02/25/1673114.html的思路基本一样,只是实现上略有不同。
这个问题的核心是,情况A 及 B 需要不同的信息: A 需要子树的最大深度,B 需要子树的最大距离。只要函数能在一个节点同时计算及传回这两个信息,我是通过一个整形指针保存树中的局部最大距离。然后通过返回值,分别树的最大深度,如果左右子树的最大深度相加大于当前树的最大距离,则更新最大距离,最后返回左右子树中较大的深度,这样可以轻易求得它们父亲的最大深度。(关于建树部分,可以参考http://blog.csdn.net/lalor/article/details/7618120)
代码核心:
int DistanceCore(BinaryTreeNode *root, int *max)
{
//如果节点是叶子节点,则返回0——深度
if (root->m_pLeft == NULL && root->m_pRight == NULL)
{
return 0;
}
//保存左右子树的最大深度
int lDistance = 0;
int rDistance = 0;
//左子树不为空,返回当前节点到左子树的最大深度
if (root->m_pLeft != NULL)
{
lDistance = 1 + DistanceCore(root->m_pLeft, max);
}
if (root->m_pRight != NULL)
{
rDistance = 1 + DistanceCore(root->m_pRight, max);
}
//遍历到当前节点时,能获得的最大距离
if (lDistance + rDistance > *max)
{
//保存当前获得的最大距离
*max = lDistance + rDistance;
}
//返回左右子树中,深度较大的一个
return lDistance > rDistance ? lDistance : rDistance;
}
完整代码如下:
- #include <iostream>
- #include <stdlib.h>
- using namespace std;
- struct BinaryTreeNode
- {
- int m_nValue;
- struct BinaryTreeNode *m_pLeft;
- struct BinaryTreeNode *m_pRight;
- };
- int maxDistance(BinaryTreeNode *root, int *max);
- int DistanceCore(BinaryTreeNode *root,int *max);
- //后序遍历,用于我们建立的二叉树是否正确
- void Traverse( BinaryTreeNode * root);
- BinaryTreeNode* Construct(int *preorder, int *inorder, int lenght);
- BinaryTreeNode* ConstructCore(int *startPreorder, int *endPreorder, int *startInorder, int *endInorder);
- int InsertNodeAtMostRight(BinaryTreeNode * root, BinaryTreeNode * node);
- int main(int argc, char* argv[])
- {
- int preOrder[] = {5, 4, 8, 9, 6, 3, 18, 19, 2};
- int inOrder[] = {9, 8, 6, 3, 4, 5, 19, 18, 2};
- int max;
- //建树
- BinaryTreeNode *parent = Construct(preOrder, inOrder, sizeof(inOrder) / sizeof(inOrder[0]));
- cout << "A树的后序遍历的结果:" << endl;
- Traverse(parent);
- cout << endl;
- BinaryTreeNode *node1 = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
- BinaryTreeNode *node2 = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
- node1->m_nValue = 0;
- node1->m_pLeft = NULL;
- node1->m_pRight = NULL;
- node2->m_nValue = 0;
- node2->m_pLeft = NULL;
- node2->m_pRight = NULL;
- maxDistance(parent, &max);
- cout <<"max distance of tree's nodes : " << max << endl;
- InsertNodeAtMostRight(parent, node1);
- maxDistance(parent, &max);
- cout <<"max distance of tree's nodes after insert node1: " << max << endl;
- InsertNodeAtMostRight(parent, node2);
- maxDistance(parent, &max);
- cout <<"max distance of tree's nodes after insert node2: " << max << endl;
- //测试极端情况,即只有一个节点
- maxDistance(node2, &max);
- cout <<"just one node " << max << endl;
- //测试极端情况,即只有二个节点
- maxDistance(node1, &max);
- cout <<"just two node " << max << endl;
- return 0;
- }
- BinaryTreeNode* Construct(int *preorder, int *inorder, int lenght)
- {
- if (preorder == NULL || inorder == NULL || lenght <= 0)
- {
- return NULL;
- }
- return ConstructCore(preorder, preorder + lenght - 1, inorder, inorder + lenght - 1);
- }
- BinaryTreeNode* ConstructCore(int *startPreorder, int *endPreorder, int *startInorder, int *endInorder)
- {
- int rootValue = startPreorder[0];
- BinaryTreeNode *root = new BinaryTreeNode();
- root->m_nValue = rootValue;
- root->m_pLeft = root->m_pRight = NULL;
- if (startPreorder == endPreorder)
- {//先序遍历已经结束了,那这个时候一定是插入最后一个节点,则应该满足下面的if语句,否则输入的数据有误
- if (startInorder == endInorder && *startPreorder == *startInorder)
- {
- return root;
- }
- else
- {
- cout << "Invalid input" << endl;
- exit(-1);
- }
- }
- int *rootInorder = startInorder;
- while (rootInorder <= endInorder && *rootInorder != rootValue)
- {
- ++rootInorder;
- }
- if (rootInorder <= endInorder && *rootInorder != rootValue)
- {
- cout << "Invalid input" << endl;
- exit(-1);
- }
- int leftLength = rootInorder - startInorder;
- int *leftPreorderEnd = startPreorder + leftLength;
- if (leftLength > 0)
- {
- root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd, startInorder, rootInorder - 1);
- }
- if (leftLength < endPreorder - startPreorder)
- {
- root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder, rootInorder + 1, endInorder);
- }
- return root;
- }
- void Traverse( BinaryTreeNode * root)
- {
- if (root == NULL)
- {
- return;
- }
- else
- {
- Traverse(root->m_pLeft);
- Traverse(root->m_pRight);
- cout << root->m_nValue << " ";
- }
- }
- int maxDistance(BinaryTreeNode *root, int *max)
- {
- //这个函数的主要功能是判断root不为空,且给max赋初值
- if (root == NULL || max == NULL)
- {
- return -1;
- }
- *max = 0;
- return DistanceCore(root, max);
- }
- int DistanceCore(BinaryTreeNode *root, int *max)
- {
- //如果节点是叶子节点,则返回0——深度
- if (root->m_pLeft == NULL && root->m_pRight == NULL)
- {
- return 0;
- }
- //保存左右子树的最大深度
- int lDistance = 0;
- int rDistance = 0;
- //左子树不为空,返回当前节点到左子树的最大深度
- if (root->m_pLeft != NULL)
- {
- lDistance = 1 + DistanceCore(root->m_pLeft, max);
- }
- if (root->m_pRight != NULL)
- {
- rDistance = 1 + DistanceCore(root->m_pRight, max);
- }
- //遍历到当前节点时,能获得的最大距离
- if (lDistance + rDistance > *max)
- {
- //保存当前获得的最大距离
- *max = lDistance + rDistance;
- }
- //返回左右子树中,深度较大的一个
- return lDistance > rDistance ? lDistance : rDistance;
- }
- //为了测试程序写的辅助函数,在树的最最右边插入一个新的节点
- int InsertNodeAtMostRight(BinaryTreeNode * root, BinaryTreeNode * node)
- {
- if (root == NULL || node == NULL)
- {
- return -1;
- }
- while (root->m_pRight != NULL)
- {
- root = root->m_pRight;
- }
- root->m_pRight = node;
- return 0;
- }
二叉树分析(两点最大距离)相关推荐
- DS二叉树—二叉树结点的最大距离
题目描述 二叉树两个结点的距离是一个结点经过双亲结点,祖先结点等中间结点到达另一个结点经过的分支数.二叉树结点的最大距离是所有结点间距离的最大值.例如,下图所示二叉树结点最大距离是3,C和D的距离. ...
- 芭芭拉冲鸭~(dfs树两点最大距离)
树上两节点的最大距离 牛客网:题目链接: 感悟: 1.dfs的再理解,对树的遍历,用深度标记到根节点的距离. 2.树两点的最大距离的求解. 题意: 给定一棵无根树,树上每个节点被染成了红色或绿色或蓝色 ...
- 005 周围遍历二叉树分析和代码编写
文章目录 周围遍历分析 定位角色名字偏移 玩家名字偏移 NPC名字偏移 数据整理 代码编写 所谓的周围遍历,其实就是人物附近所有的怪物 NPC 和玩家信息,拿到了这些数据,我们就可以实时获得当前人物对 ...
- 二叉树任意两点间最短路径(利用栈-找公共祖先,不需要建立二叉树)
代码: #include<bits/stdc++.h> using namespace std;int main() {int T;cin>>T;while(T--){int ...
- leetcode 106. 从中序与后序遍历序列构造二叉树 105. 从前序与中序遍历序列构造二叉树思考分析
目录 1.106题目 2.参考思路:递归切割数组 3.105题目 4.同样思路的代码 1.106题目 2.参考思路:递归切割数组 代码参考:公众号:代码随想录 后序数组+中序数组 以 后序数组(左右中 ...
- 《程序员代码面试指南》第三章 二叉树问题 二叉树节点间的最大距离问题
题目 二叉树节点间的最大距离问题 java代码 package com.lizhouwei.chapter3;/*** @Description:二叉树节点间的最大距离问题* @Author: liz ...
- 011 数据结构逆向—二叉树
文章目录 前言 背包数据嵌套结构 背包二叉树 二叉树分析 背包数据结构分析 总结 前言 学习完了链表的数据结构,我们再通过幻想神域了解一下二叉树在游戏中的存储形式. 这一次要逆向的数据是背包中的所有物 ...
- 【数据结构笔记10】二叉树的先序、中序、后序遍历,中序遍历的堆栈/非递归遍历算法,层序遍历,确定一个二叉树,树的同构
本次笔记内容: 3.3.1 先序中序后序遍历 3.3.2 中序非递归遍历 3.3.3 层序遍历 3.3.4 遍历应用例子 小白专场:题意理解及二叉树表示 小白专场:程序框架.建树及同构判别 文章目录 ...
- 二叉树中节点的最大的距离(编程之美3.8)
问题来源:<编程之美>3.8 求二叉树节点的最大距离 如果把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两个节点之间的个数. 写一个程序求一 ...
最新文章
- linux进程间通信-XSI IPC
- c语言统计输入文本不同字母单词数,【C语言统计不同单词个数编写一个程序,输入一个句子,然后统计-查字典问答网...
- 业界丨OpenAI 发布通用人工智能研究纲领:以全人类的名义承诺
- 登上Science子刊,神经科学再次启发DNN设计!中科院揭秘介观自组织反向传播机制...
- 使用python库matplotlib绘制不同的图表
- C++中的RAII机制
- linux——ISCSI 网络磁盘共享
- 恢复被CVS被Override and Update后的代码
- hdu 2821 Pusher (dfs)
- 锐捷亮相GITC:请互联网企业为我点个赞!
- 美河LINUX 内核学习视频
- quartusII编译时出现Error (119013): Current license file does not support the EP4CE6F17C8 device
- photoshop放大缩小有什么快捷键
- 只有 assignment、call、increment、decrement 和 new 对象表达式可用作语句
- Python爬虫,爬取快看漫画每日更新模块
- Python报错ModuleNotFoundError: No module named ‘pyqtgraph‘
- Machine Learning in Action(5) SVM算法
- ZOJ:1203 Swordfish
- google play
- 小米RE管理器root explorer基础操作教程(转载)
热门文章
- Android之ViewPager使用(用美女做的背景,给你疲惫的眼睛视觉冲击)
- 《零基础看得懂的C语言入门教程 》——(八)了解基本数组还不是那么简单
- linux docker nginx,CentOS7上Docker简单安装及nginx部署
- linux 编译工具链,Linux工具链for TKStudio下载_Linux工具链for TKStudio官方下载-太平洋下载中心...
- 这些高校竟因名字太“坑爹”被误会为三本?盘点九所实力强劲但被名字耽误的大学...
- 为什么饮料瓶大都是圆的,牛奶盒却是方的?原因你想不到
- 致家长:疫情期间教育好自己的孩子,就是你最重要的事业!
- 去医院看病如何开开心心出来? | 今日最佳
- 人造流星这种生日礼物,你有过吗?现在国外有了
- php根据分辨率跳转,使用PHP将分辨率转换为Aspect比率