题目
输入:二叉树结点数量
结点之间相邻情况
需要求距离的两个结点编号
输出:二叉树的深度,宽度和给定两个编号之间的距离
问题所在:
1.选定一个比较好的数据结构储存题目给定的数据
2.利用这个数据结构把树的深度,宽度和给定两个结点之间的距离求出来。
一、求树的深度:
从根节点遍历整个树
记录当前深度,时刻更新最大值即可
二、求树的宽度:
设置层级概念,也就是当前节点到根节点的路程长度+1;
统计所有层级的节点数,取最大值即可。
三、给定两个结点之间的距离:
采用由下向上的方法
例如给定两个节点a,b.那么从a,b开始一直向上搜索到相遇点c
记录a到c的路程,b到c的路程。然后距离l=lac2+lbc1;
关键是如何判断某个根节点是两个节点的共同父节点呢?
方法:可以先让往上走,每到一个节点,就在数组中对应下标(下标等于路过节点的编号)记录a节点到此节点的路程;然后从b开始向上遍历,如果遇到的节点编号在数组中值不是0,那么利用当前b的路程长度和数组值进行计算再break即可。
对,还要时刻判定当前a节点是否走过了b,或者b走过了a,两个都判断一下,来确定谁在上方,谁在下方。
好,现在根据上面的思想来确定一个好的数据结构。
输出方面没有顺序可言,所以不可以一步一步构筑我们所需要的树
链式前向星?不太好,我们并不是很关心兄弟节点的情况。
对于一个确定的节点,我只需要直到他的父节点是谁,和他的子节点是谁。
好吧,我终于知道数据结构的重要意义了,对于一个二叉树问题,好的数据结构选取对于解题无疑是至关重要的。
关键是如何储存一个二叉树呢?
ok,差不多思路算是有了!
数据结构就选链式前向星
1.读取
2.深搜,并且在深搜的过程中记录所有节点的父节点
3.用循环,执行上面的思路即可
中间遇到的问题:
关于循环寻找路径上的逻辑问题
三种情况:
1.起点在终点下面
2.起点在终点上面
上面两种情况还有st或者end是否为1的情况
3.起点和终点没有直系关系
这个最好解决
向大佬学习:
树剖,树链剖分LCA,看来还是给自己省一点时间吧。哈哈,先记上,写不出来题的时候再学
放代码:
#include<stdio.h>
int lst[105]={0},lend[105]={0},father[105]={0},width[105]={0},head[105]={0};
typedef struct
{
int to,next;
}Edge;
Edge edge[105];
int max_depth=0,max_width=0,cnt=0,n=0,st=0,end=0,from=0,to=0,length=0;
void createdge(int from,int to);
void dfs(int s,int f,int sGrade);
int main()
{
//读取
scanf("%d",&n);
for(int i=0;i<n-1;i++)
{
scanf("%d %d",&from,&to);
createdge(from,to);
createdge(to,from);
}
scanf("%d %d",&st,&end);
dfs(1,0,1);
printf("%d\n",max_depth);
printf("%d\n",max_width);
//注意这个循环容易出现的逻辑问题
//我们的目的就是要避免错误逻辑现象的发生
//出错情况,就是st=1时我们的判断。应该放在整个循环的首部,因为如果没判断直接让st向上跨越,那么会出现st=0的情况,那么整个lst数组都没有值,在end寻找st的时候也找不到它了。所以判断st==1的位置应该放在整个循环的首位。
while(st!=1)
{
st=father[st];//向上跨越
length++;
lst[st]=length;
if(st==end)
{
printf("%d\n",lst[st]*2);
return 0;
}
}
length=0;
while(1)//两种情况结束,一种我向上走遇到了st,另一种公共节点不为0
{
end=father[end];
length++;
lend[end]=length;
if(lst[end]!=0)
{
printf("%d\n",lst[end]*2+lend[end]);
return 0;
}
if(end==st)
{
printf("%d\n",lend[end]);
return 0;
}
}
}
void createdge(int from,int to)
{
cnt++;
edge[cnt].next=head[from];
edge[cnt].to=to;
head[from]=cnt;
}
void dfs(int s,int f,int sGrade)
{
//记录父节点
father[s]=f;
for(int i=head[s];i;i=edge[i].next)
{
if(edge[i].to!=f)//当前节点不是父节点
{
if(sGrade+1>max_depth)
{
max_depth=sGrade+1;
}
width[sGrade+1]++;
if(width[sGrade+1]>max_width)
{
max_width=width[sGrade+1];
}
dfs(edge[i].to,s,sGrade+1);
}
}
}