转载自: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

这段代码有几个缺点:

  1. 算法加入了侵入式(intrusive)的资料nMaxLeft, nMaxRight
  2. 使用了全局变量 nMaxLen。每次使用要额外初始化。而且就算是不同的独立资料,也不能在多个线程使用这个函数
  3. 逻辑比较复杂,也有许多 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;
}

完整代码如下:

  1. #include <iostream>
  2. #include <stdlib.h>
  3. using namespace std;
  4. struct BinaryTreeNode
  5. {
  6. int m_nValue;
  7. struct BinaryTreeNode *m_pLeft;
  8. struct BinaryTreeNode *m_pRight;
  9. };
  10. int maxDistance(BinaryTreeNode *root, int *max);
  11. int DistanceCore(BinaryTreeNode *root,int *max);
  12. //后序遍历,用于我们建立的二叉树是否正确
  13. void Traverse( BinaryTreeNode * root);
  14. BinaryTreeNode* Construct(int *preorder, int *inorder, int lenght);
  15. BinaryTreeNode* ConstructCore(int *startPreorder, int *endPreorder, int *startInorder, int *endInorder);
  16. int InsertNodeAtMostRight(BinaryTreeNode * root, BinaryTreeNode * node);
  17. int main(int argc, char* argv[])
  18. {
  19. int preOrder[] = {5, 4, 8, 9, 6, 3, 18, 19, 2};
  20. int inOrder[] = {9, 8, 6, 3, 4, 5, 19, 18, 2};
  21. int max;
  22. //建树
  23. BinaryTreeNode *parent = Construct(preOrder, inOrder, sizeof(inOrder) / sizeof(inOrder[0]));
  24. cout << "A树的后序遍历的结果:" << endl;
  25. Traverse(parent);
  26. cout << endl;
  27. BinaryTreeNode *node1 = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
  28. BinaryTreeNode *node2 = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
  29. node1->m_nValue = 0;
  30. node1->m_pLeft = NULL;
  31. node1->m_pRight = NULL;
  32. node2->m_nValue = 0;
  33. node2->m_pLeft = NULL;
  34. node2->m_pRight = NULL;
  35. maxDistance(parent, &max);
  36. cout <<"max distance of tree's nodes : " << max << endl;
  37. InsertNodeAtMostRight(parent, node1);
  38. maxDistance(parent, &max);
  39. cout <<"max distance of tree's nodes after insert node1: " << max << endl;
  40. InsertNodeAtMostRight(parent, node2);
  41. maxDistance(parent, &max);
  42. cout <<"max distance of tree's nodes after insert node2: " << max << endl;
  43. //测试极端情况,即只有一个节点
  44. maxDistance(node2, &max);
  45. cout <<"just one node " << max << endl;
  46. //测试极端情况,即只有二个节点
  47. maxDistance(node1, &max);
  48. cout <<"just two node " << max << endl;
  49. return 0;
  50. }
  51. BinaryTreeNode* Construct(int *preorder, int *inorder, int lenght)
  52. {
  53. if (preorder == NULL || inorder == NULL || lenght <= 0)
  54. {
  55. return NULL;
  56. }
  57. return ConstructCore(preorder, preorder + lenght - 1, inorder, inorder + lenght - 1);
  58. }
  59. BinaryTreeNode* ConstructCore(int *startPreorder, int *endPreorder, int *startInorder, int *endInorder)
  60. {
  61. int rootValue = startPreorder[0];
  62. BinaryTreeNode *root = new BinaryTreeNode();
  63. root->m_nValue = rootValue;
  64. root->m_pLeft = root->m_pRight = NULL;
  65. if (startPreorder == endPreorder)
  66. {//先序遍历已经结束了,那这个时候一定是插入最后一个节点,则应该满足下面的if语句,否则输入的数据有误
  67. if (startInorder == endInorder && *startPreorder == *startInorder)
  68. {
  69. return root;
  70. }
  71. else
  72. {
  73. cout << "Invalid input" << endl;
  74. exit(-1);
  75. }
  76. }
  77. int *rootInorder = startInorder;
  78. while (rootInorder <= endInorder && *rootInorder != rootValue)
  79. {
  80. ++rootInorder;
  81. }
  82. if (rootInorder <= endInorder && *rootInorder != rootValue)
  83. {
  84. cout << "Invalid input" << endl;
  85. exit(-1);
  86. }
  87. int leftLength = rootInorder - startInorder;
  88. int *leftPreorderEnd = startPreorder + leftLength;
  89. if (leftLength > 0)
  90. {
  91. root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd, startInorder, rootInorder - 1);
  92. }
  93. if (leftLength < endPreorder - startPreorder)
  94. {
  95. root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder, rootInorder + 1, endInorder);
  96. }
  97. return root;
  98. }
  99. void Traverse( BinaryTreeNode * root)
  100. {
  101. if (root == NULL)
  102. {
  103. return;
  104. }
  105. else
  106. {
  107. Traverse(root->m_pLeft);
  108. Traverse(root->m_pRight);
  109. cout << root->m_nValue << "  ";
  110. }
  111. }
  112. int maxDistance(BinaryTreeNode *root, int *max)
  113. {
  114. //这个函数的主要功能是判断root不为空,且给max赋初值
  115. if (root == NULL || max == NULL)
  116. {
  117. return -1;
  118. }
  119. *max = 0;
  120. return DistanceCore(root, max);
  121. }
  122. int DistanceCore(BinaryTreeNode *root, int *max)
  123. {
  124. //如果节点是叶子节点,则返回0——深度
  125. if (root->m_pLeft == NULL && root->m_pRight == NULL)
  126. {
  127. return 0;
  128. }
  129. //保存左右子树的最大深度
  130. int lDistance = 0;
  131. int rDistance = 0;
  132. //左子树不为空,返回当前节点到左子树的最大深度
  133. if (root->m_pLeft != NULL)
  134. {
  135. lDistance = 1 + DistanceCore(root->m_pLeft, max);
  136. }
  137. if (root->m_pRight != NULL)
  138. {
  139. rDistance = 1 + DistanceCore(root->m_pRight, max);
  140. }
  141. //遍历到当前节点时,能获得的最大距离
  142. if (lDistance + rDistance > *max)
  143. {
  144. //保存当前获得的最大距离
  145. *max = lDistance + rDistance;
  146. }
  147. //返回左右子树中,深度较大的一个
  148. return lDistance > rDistance ? lDistance : rDistance;
  149. }
  150. //为了测试程序写的辅助函数,在树的最最右边插入一个新的节点
  151. int InsertNodeAtMostRight(BinaryTreeNode * root, BinaryTreeNode * node)
  152. {
  153. if (root == NULL || node == NULL)
  154. {
  155. return -1;
  156. }
  157. while (root->m_pRight != NULL)
  158. {
  159. root = root->m_pRight;
  160. }
  161. root->m_pRight = node;
  162. return 0;
  163. }

二叉树分析(两点最大距离)相关推荐

  1. DS二叉树—二叉树结点的最大距离

    题目描述 二叉树两个结点的距离是一个结点经过双亲结点,祖先结点等中间结点到达另一个结点经过的分支数.二叉树结点的最大距离是所有结点间距离的最大值.例如,下图所示二叉树结点最大距离是3,C和D的距离. ...

  2. 芭芭拉冲鸭~(dfs树两点最大距离)

    树上两节点的最大距离 牛客网:题目链接: 感悟: 1.dfs的再理解,对树的遍历,用深度标记到根节点的距离. 2.树两点的最大距离的求解. 题意: 给定一棵无根树,树上每个节点被染成了红色或绿色或蓝色 ...

  3. 005 周围遍历二叉树分析和代码编写

    文章目录 周围遍历分析 定位角色名字偏移 玩家名字偏移 NPC名字偏移 数据整理 代码编写 所谓的周围遍历,其实就是人物附近所有的怪物 NPC 和玩家信息,拿到了这些数据,我们就可以实时获得当前人物对 ...

  4. 二叉树任意两点间最短路径(利用栈-找公共祖先,不需要建立二叉树)

    代码: #include<bits/stdc++.h> using namespace std;int main() {int T;cin>>T;while(T--){int ...

  5. leetcode 106. 从中序与后序遍历序列构造二叉树 105. 从前序与中序遍历序列构造二叉树思考分析

    目录 1.106题目 2.参考思路:递归切割数组 3.105题目 4.同样思路的代码 1.106题目 2.参考思路:递归切割数组 代码参考:公众号:代码随想录 后序数组+中序数组 以 后序数组(左右中 ...

  6. 《程序员代码面试指南》第三章 二叉树问题 二叉树节点间的最大距离问题

    题目 二叉树节点间的最大距离问题 java代码 package com.lizhouwei.chapter3;/*** @Description:二叉树节点间的最大距离问题* @Author: liz ...

  7. 011 数据结构逆向—二叉树

    文章目录 前言 背包数据嵌套结构 背包二叉树 二叉树分析 背包数据结构分析 总结 前言 学习完了链表的数据结构,我们再通过幻想神域了解一下二叉树在游戏中的存储形式. 这一次要逆向的数据是背包中的所有物 ...

  8. 【数据结构笔记10】二叉树的先序、中序、后序遍历,中序遍历的堆栈/非递归遍历算法,层序遍历,确定一个二叉树,树的同构

    本次笔记内容: 3.3.1 先序中序后序遍历 3.3.2 中序非递归遍历 3.3.3 层序遍历 3.3.4 遍历应用例子 小白专场:题意理解及二叉树表示 小白专场:程序框架.建树及同构判别 文章目录 ...

  9. 二叉树中节点的最大的距离(编程之美3.8)

    问题来源:<编程之美>3.8 求二叉树节点的最大距离 如果把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两个节点之间的个数. 写一个程序求一 ...

最新文章

  1. linux进程间通信-XSI IPC
  2. c语言统计输入文本不同字母单词数,【C语言统计不同单词个数编写一个程序,输入一个句子,然后统计-查字典问答网...
  3. 业界丨OpenAI 发布通用人工智能研究纲领:以全人类的名义承诺
  4. 登上Science子刊,神经科学再次启发DNN设计!中科院揭秘介观自组织反向传播机制...
  5. 使用python库matplotlib绘制不同的图表
  6. C++中的RAII机制
  7. linux——ISCSI 网络磁盘共享
  8. 恢复被CVS被Override and Update后的代码
  9. hdu 2821 Pusher (dfs)
  10. 锐捷亮相GITC:请互联网企业为我点个赞!
  11. 美河LINUX 内核学习视频
  12. quartusII编译时出现Error (119013): Current license file does not support the EP4CE6F17C8 device
  13. photoshop放大缩小有什么快捷键
  14. 只有 assignment、call、increment、decrement 和 new 对象表达式可用作语句
  15. Python爬虫,爬取快看漫画每日更新模块
  16. Python报错ModuleNotFoundError: No module named ‘pyqtgraph‘
  17. Machine Learning in Action(5) SVM算法
  18. ZOJ:1203 Swordfish
  19. google play
  20. 小米RE管理器root explorer基础操作教程(转载)

热门文章

  1. Android之ViewPager使用(用美女做的背景,给你疲惫的眼睛视觉冲击)
  2. 《零基础看得懂的C语言入门教程 》——(八)了解基本数组还不是那么简单
  3. linux docker nginx,CentOS7上Docker简单安装及nginx部署
  4. linux 编译工具链,Linux工具链for TKStudio下载_Linux工具链for TKStudio官方下载-太平洋下载中心...
  5. 这些高校竟因名字太“坑爹”被误会为三本?盘点九所实力强劲但被名字耽误的大学...
  6. 为什么饮料瓶大都是圆的,牛奶盒却是方的?原因你想不到
  7. 致家长:疫情期间教育好自己的孩子,就是你最重要的事业!
  8. 去医院看病如何开开心心出来? | 今日最佳
  9. 人造流星这种生日礼物,你有过吗?现在国外有了
  10. php根据分辨率跳转,使用PHP将分辨率转换为Aspect比率