编程之美——二叉树中节点间最大距离

关于递归程序:

递归程序结构包括三部分:递归出口、逻辑处理(需要处理的问题)、递归调用(衔接)。

通过递归调用将问题转化为对子问题的解决,通过回溯完成原问题的解答;

递归与数学归纳法:递归是数学归纳法在计算机程序中的体现。使用递归思想设计程序时,我们设置base case,并假设我们会获得n-1的结果,并实现n的结果。这就好像数学归纳法,我们只关注初始和衔接,而不需要关注具体的每一步。

当问题采用递归算法求解时,代码如下:

  1 #include<iostream>
  2 #include<queue>
  3 using namespace std;
  4
  5 template<class T>
  6 class binaryTree
  7 {
  8     struct node
  9     {
 10         T elem;
 11         node *left;
 12         node *right;
 13         int nMaxLeft;//左子树最长距离
 14         int nMaxRight;//右子树最长距离
 15
 16         node(const T &x,node *lt=NULL,node *rt=NULL,int nleft=0,int nright=0)
 17         :elem(x),left(lt),right(rt),nMaxLeft(nleft),nMaxRight(nright){}
 18         ~node(){}
 19     };
 20
 21     int nmaxLength=0;
 22
 23 private:
 24     node *root;
 25     void makeEmpty(node *&t);
 26     void findMaxLength(node *&t);
 27 public:
 28     binaryTree(node *t=NULL)
 29     {
 30         root=t;
 31     }
 32     void createBinaryTree();
 33     ~binaryTree()
 34     {
 35         makeEmpty(root);
 36     }
 37     int printMaxLenght()
 38     {
 39         findMaxLength(root);
 40         cout<<nmaxLength<<endl;
 41     }
 42 };
 43
 44 template<class T>
 45 void binaryTree<T>::createBinaryTree()
 46 {
 47     queue<node *>que;
 48     node *t;
 49     T value;
 50
 51     cout<<"enter root:(-1 represent NULL)"<<":";
 52     cin>>value;
 53
 54     root=new node(value);
 55     que.push(root);
 56
 57     T ldata,rdata;
 58
 59     while(!que.empty())
 60     {
 61         t=que.front();
 62         que.pop();
 63
 64         cout<<"enter left son of the node "<<t->elem<<":";
 65         cin>>ldata;
 66         cout<<"enter right son of the node "<<t->elem<<":";
 67         cin>>rdata;
 68
 69         if(ldata!=-1)
 70             que.push(t->left=new node(ldata));
 71         if(rdata!=-1)
 72             que.push(t->right=new node(rdata));
 73     }
 74     cout<<"construct complement!"<<endl;
 75 }
 76
 77 template<class T>
 78 void binaryTree<T>::makeEmpty(node *&t)
 79 {
 80     if(t->left!=NULL)
 81         makeEmpty(t->left);
 82     if(t->right!=NULL)
 83         makeEmpty(t->right);
 84     delete t;
 85 }
 86
 87 template<class T>
 88 void binaryTree<T>::findMaxLength(node *&t)
 89 {
 90     if(t==NULL)
 91         return;
 92
 93     if(t->left!=NULL)
 94         findMaxLength(t->left);
 95     if(t->right!=NULL)
 96         findMaxLength(t->right);
 97
 98     if(t->left==NULL)
 99         t->nMaxLeft=0;
100     if(t->right==NULL)
101         t->nMaxRight=0;
102
103     if(t->left!=NULL)
104     {
105         int nmax=0;
106         nmax=t->left->nMaxLeft>t->left->nMaxRight ? t->left->nMaxLeft : t->left->nMaxRight;
107         t->nMaxLeft=nmax+1;
108     }
109     if(t->right!=NULL)
110     {
111         int nmax=0;
112         nmax=t->right->nMaxLeft>t->right->nMaxRight ? t->right->nMaxLeft : t->right->nMaxRight;
113         t->nMaxRight=nmax+1;
114     }
115
116     if(t->nMaxLeft+t->nMaxRight>nmaxLength)
117         nmaxLength=t->nMaxLeft+t->nMaxRight;
118 }
119
120 int main()
121 {
122     binaryTree<int>tree;
123     tree.createBinaryTree();
124     tree.printMaxLenght();
125     return 0;
126 }

参考:http://www.cnblogs.com/miloyip/archive/2010/02/25/1673114.html,问题有更好的解法

计算一个二叉树的最大距离有两种情况:

  • 情况A: 路径经过左子树的最深节点,通过根节点,再到右子树的最深节点。
  • 情况B: 路径不穿过根节点,而是左子树或右子树的最大距离路径,取其大者。

只需要计算这两个情况的路径距离,并取其大者,就是该二叉树的最大距离;这也就是上面的递归思路;

问题的核心是情况A 及 B 需要不同的信息: A 需要子树的最大深度,B 需要子树的最大距离。只要函数能在一个节点同时计算及传回这两个信息,代码就可以很简单;

代码如下:

  1 #include<iostream>
  2 #include<queue>
  3 using namespace std;
  4
  5 struct result
  6 {
  7     int nmaxDistance;//最长距离
  8     int nmaxDepth;//最大深度
  9 };
 10
 11 template<class T>
 12 class binaryTree
 13 {
 14     struct node
 15     {
 16         T elem;
 17         node *left;
 18         node *right;
 19
 20         node(const T &x,node *lt=NULL,node *rt=NULL)
 21         :elem(x),left(lt),right(rt){}
 22         ~node(){}
 23     };
 24
 25 private:
 26     node *root;
 27     void makeEmpty(node *&t);
 28     result getMaxDistance(node *&t);
 29 public:
 30     binaryTree(node *t=NULL)
 31     {
 32         root=t;
 33     }
 34     void createBinaryTree();
 35     int printMaxLength()
 36     {
 37         cout<<getMaxDistance(root).nmaxDistance<<endl;
 38     }
 39     ~binaryTree()
 40     {
 41         makeEmpty(root);
 42     }
 43 };
 44
 45 template<class T>
 46 void binaryTree<T>::createBinaryTree()
 47 {
 48     queue<node *>que;
 49     node *t;
 50     T value;
 51
 52     cout<<"enter root:(-1 represent NULL)"<<":";
 53     cin>>value;
 54
 55     root=new node(value);
 56     que.push(root);
 57
 58     T ldata,rdata;
 59
 60     while(!que.empty())
 61     {
 62         t=que.front();
 63         que.pop();
 64
 65         cout<<"enter left son of the node "<<t->elem<<":";
 66         cin>>ldata;
 67         cout<<"enter right son of the node "<<t->elem<<":";
 68         cin>>rdata;
 69
 70         if(ldata!=-1)
 71             que.push(t->left=new node(ldata));
 72         if(rdata!=-1)
 73             que.push(t->right=new node(rdata));
 74     }
 75     cout<<"construct complement!"<<endl;
 76 }
 77
 78 template<class T>
 79 void binaryTree<T>::makeEmpty(node *&t)
 80 {
 81     if(t->left!=NULL)
 82         makeEmpty(t->left);
 83     if(t->right!=NULL)
 84         makeEmpty(t->right);
 85     delete t;
 86 }
 87
 88 template<class T>
 89 result binaryTree<T>::getMaxDistance(node *&t)
 90 {
 91     if(!t)
 92     {
 93         result empty={0,-1};
 94         return empty;
 95     }
 96
 97     result lhs=getMaxDistance(t->left);
 98     result rhs=getMaxDistance(t->right);
 99
100     result maxdistance;
101     maxdistance.nmaxDepth=max(lhs.nmaxDepth+1,rhs.nmaxDepth+1);
102     maxdistance.nmaxDistance=
103     max(max(lhs.nmaxDistance,rhs.nmaxDistance),lhs.nmaxDepth+rhs.nmaxDepth+2);
104     return maxdistance;
105 }
106
107 int main()
108 {
109     binaryTree<int>tree;
110     tree.createBinaryTree();
111     tree.printMaxLength();
112     return 0;
113 }

为了减少 NULL 的条件测试,进入函数时,如果节点为 NULL,会传回一个 empty 变量。empty.nMaxDepth = -1,目的是让调用方 +1 后,把当前的不存在的 (NULL) 子树当成最大深度为 0。

时间: 2024-10-29 19:12:35

编程之美——二叉树中节点间最大距离的相关文章

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

题目:如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两节点之间边的个数.写一个程序求一棵二叉树中相距最远的两个节点之间的距离. 分析:树上分析的很清楚,计算一个二叉树的最大距离有两个情况: 1. 路径经过左子树的最深节点,通过根节点,再到右子树的最深节点. 2. 路径不穿过根节点,而是左子树或右子树的最大距离路径,取其大者. 但是树上的代码使用了额外的节点字段,这里给出我的代码,思路是一样的: struct BinaryTree { int valu

【编程题目】求二叉树中节点的最大距离

第 11 题(树)求二叉树中节点的最大距离...如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两节点之间边的个数.写一个程序,求一棵二叉树中相距最远的两个节点之间的距离. 思路:二叉树结构中只设了左右子节点的指针. 设单个结点的深度为0. 用后序遍历,得到每个结点为根的子树的最大深度.maxdistance记录该结点(左子树深度+右子树深度 + 2)是否超过已有的最远距离,若超过更新. 关键:空指针的深度设为-1,这样避免了复杂的分类讨论. 树每个结

11求二叉树中节点的最大距离

转载请注明出处:http://www.cnblogs.com/wuzetiandaren/p/4253605.html 声明:现大部分文章为寻找问题时在网上相互转载,此博是为自己做个记录记录,方便自己也方便有类似问题的朋友,本文的思想也许有所借鉴,但源码均为本人实现,如有侵权,请发邮件表明文章和原出处地址,我一定在文章中注明.谢谢. 题目:如果我们把二叉树看成一个图,一棵树显示是一颗有向无环图,定义"距离"为两节点之间边的个数(不考虑方向).写一个程序,求一棵二叉树中相距最远的两个节点

IT公司100题-11-求二叉树中节点的最大距离

问题描述: 写程序,求一棵二叉树中相距最远的两个节点之间的距离. 10/     \6      14/   \   /   \4    8 12    16 分析: 二叉树中最远的两个节点,要么是根和一个叶子节点,要么是两个叶子节点. 代码实现: 1 // 11.cc 2 #include <iostream> 3 using namespace std; 4 5 typedef struct BSTreeNode { 6 int data; 7 BSTreeNode *left; 8 BS

11.求二叉树中节点的最大距离

如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义 " 距离 " 为两节点之间边的个数.写一个程序,求一棵二叉树中相距最远的两个节点之间的距离,求二叉树中节点的最大距离 分析: 先画几个不同形状的二叉树,从例子中可以看出,相距最远的两个节点,一定是两个叶子节点,或者是一个叶子节点到它的根节点: 根据相距最远的两个节点一定是叶子节点这个规律,我们可以进一步讨论. 对于任意一个节点,以该节点为根,假设这个根有 K 个孩子节点,那么相距最远的两 个节点 U和 V之间的路

二叉树进阶之求一棵二叉树中结点间最大距离

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6618074.html 二叉树中的结点间距离:从结点A出发到达B,每个结点只能走一次,AB路径上的结点数就是AB间距离. 由于从一个结点出发时,只有两种方向可走:向上经过父节点到达它的兄弟子树:向下到达它自己的左右子树: 对于一个结点h为根的子树:假设现在从h左子树中最深的叶结点逐层向上走,一直走到h的左儿子,现在h.left有两种选择: 一是向上经过h,然后到达h的右子树向下走到最深叶结点: 二是从h.le

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

如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两节点之间边的个数.写一个程序求一棵二叉树中相距最远的两个节点之间的距离. 解法:用递归的方法 1 // 数据结构定义 2 struct NODE 3 { 4 NODE* pLeft; // 左子树 5 NODE* pRight; // 右子树 6 int nMaxLeft; // 左子树中的最长距离 7 int nMaxRight; // 右子树中的最长距离 8 char chValue; // 该节点

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

描述:如果把二叉树看成一个图,父子节点之间的连线看成双向的,定义“距离”为两个节点之间边的个数.求二叉树中相距最远的两个节点的距离. 思路:相距最远的两个节点一定是叶子节点,且这两个叶子节点的路径有两种情况: 1. 该路径经过root节点,则两个叶子节点分属root.left和root.right为根的子树,而且是两个子树中距离root.left和root.right最远的叶子节点: 2. 该路径不经过root节点,则这两个叶子节点的root.left或root.right上: 根据以上分析,参

【算法题目】求二叉树中节点的最大距离

如果我们把二叉树视为一个图,父子节点之间的连线视为双向的,我们姑且定义为“举例”为两节点之间边的个数.写一个程序求一颗二叉树中相距最远的两个节点之间的距离(<编程之美>3.8) 思路:如果两个节点相距最远,一定是两个叶子节点,或者是一个叶子节点到它的根节点. 根据相距最远的两个节点一定是叶子节点这个规律,我们可以进一步讨论.    对于任意一个节点,以该节点为根,假设这个根youk个孩子节点,那么相距最远的两个节点U和V之间的路径与这个根节点的关系有两种情况. 1.若路径经过根Root,则U和