如果我们把二叉树看成一个图,
父子节点之间的连线看成是双向的,
我们姑且定义"距离"为两节点之间边的个数。
写一个程序,
父子节点之间的连线看成是双向的,
我们姑且定义"距离"为两节点之间边的个数。
写一个程序,
求一棵二叉树中相距最远的两个节点之间的距离。
解题思路:这是一道经典的树形DP的问题,两次遍历整棵树,一次从叶子到树根,求得以该点为根的树中节点到该点的最远距离,第二次从根到叶子进行遍历,因为每一个点到其它点的最远距离不一定在以该点为根的树中,可能在父节点的其它分支中,因此可以更新父节点到当前点的最远距离,然后比较每条分支的最远距离即可求得当前点的最远距离,这样便可以求出最后结果。
参考代码如下:
#include <iostream>
#include <string.h>
using namespace std;
#define maxn 0x3ffffff
int max1;
struct node
{
int num; //二叉树中该节点的值
int longest_val; //以该节点为根离子树中的最大距离
int second_val; //以该节点为根离子树中的第二大距离
int father_val; //经过该节点的父节点的最大距离
node *dp1; //用来标记是否是以该节点为根离子树中的最大距离中的子树
node *left;
node *right;
};
int max(int a,int b)
{
return a>b?a:b;
}
void newset(node *&s,int N) //建立二叉树
{
if(s==NULL)
{
node *Node=new node();
Node->longest_val=0;
Node->second_val=0;
Node->num=N;
Node->left=NULL;
Node->right=NULL;
Node->dp1=NULL;
s=Node;
}
else if(s->num<N)
{
newset(s->right,N);
}
else if(s->num>N)
{
newset(s->left,N);
}
}
void dfs1(node *&s) //进行第一次深搜,求得以该点为根的树中节点到该点的最远距离
{
if(s->left!=NULL)
{
dfs1(s->left);
node *next=s->left;
if(s->longest_val<next->longest_val+1)
{
s->longest_val=next->longest_val+1;
s->dp1=next;
}
}
if(s->right!=NULL)
{
dfs1(s->right);
node *next=s->right;
if(s->longest_val<next->longest_val+1)
{
s->longest_val=next->longest_val+1;
s->dp1=next;
}
}
if(s->left!=NULL)
{
node *next=s->left;
if(s->dp1!=next)
s->second_val=max(s->second_val,next->longest_val+1);
}
if(s->right!=NULL)
{
node *next=s->right;
if(s->dp1!=next)
s->second_val=max(s->second_val,next->longest_val+1);
}
}
void dfs2(node *&s) //第二次深搜
{
if(s->left!=NULL)
{
node *next=s->left;
if(s->dp1!=next)
next->dp=max(s->dp,s->longest_val)+1;
else
next->dp=max(s->dp,s->second_val)+1;
dfs2(next);
}
}
void find(node *&s)
{
if(s!=NULL)
{
max1=max(max1,max(s->dp,s->longest_val));
find(s->left);
find(s->right);
}
}
int main()
{
max1=-maxn;
node *root=NULL;
newset(root,10);
newset(root,6);
newset(root,14);
newset(root,4);
newset(root,8);
newset(root,12);
newset(root,16);
newset(root,50);
dfs1(root);
dfs2(root);
find(root);
cout<<max1<<endl;
return 0;
}