题目描述
记T为一棵二叉树,树中共有n个节点。
定义根节点的深度为0,其余节点的深度为其父节点的深度加1。T的高度定义为其叶节点深度的最大值。
定义树中任意两点a和b之间的距离为其间最短简单路径的长度。T的直径定义为T中所有点对间距离的最大值。
输入一棵二叉树T,请计算它的高度和直径。
输入
输入共三行。
第一行输入n的值,表示树中结点的总个数。
第二行为树的前序遍历表示,每个节点之间用空格隔开。
第三行为树的中序遍历表示,每个节点之间也用空格隔开。
输出
输出共两行。
第一行输出树的高度。
第二行输出树的直径。
样例输入
10
0 1 9 3 8 4 2 7 5 6
3 9 8 1 2 4 0 5 7 6
样例输出
3
5
提示
分治算法可以在O(n)的时间内完成相应的计算。
算法分析
涉及到树的相关操作,立马想到分治法,设树的直径为D,树的高度为H,那么该树的直径将可以通过递归式
D
=
m
a
x
D
左子树,
D
右子树,
H
左子树
+
H
右子树
+
2
D = max{D左子树,D右子树,H左子树+H右子树+2}
D=maxD左子树,D右子树,H左子树+H右子树+2
求的。根据二叉树的前序序列和中序序列可以递归的求得树的高度,这里需仔细确定算法的basic problems,否则会发生树的高度的计算错误。该算法的时间复杂度为O(nlogn)。
#include<iostream>
using namespace std;
long tree_depth(long *A ,long *B , long start , long end, long A_pos,long &distance);//用来计算树的高度
int main(void){
long num = 0;
cin >> num;
if(num < 0){
cout << 0 <<endl;
cout << 0 << endl;
return 0;
}
long *A = new long[num];//用来存储前序序列
long *B = new long[num];//用来存储中序序列
for(long i = 0; i < num; ++i){
cin >> A[i];
}
for(long i = 0; i < num; ++i){
cin >> B[i];
}
long distance = 0;
int tree_d = tree_depth(A, B, 0, num - 1, 0, distance);
cout << tree_d <<endl;
cout << distance << endl;
delete []B;
B = NULL;
delete []A;
A = NULL;
}
long tree_depth(long * A, long * B, long start, long end, long A_pos, long & distance){
if (start > end){
distance = 0;
return -1;
}
if (start == end){
distance = 0;
return 0;
}
long root_num = A_pos;//用来存储根在中序序列位置
for(long j = start; j <= end; ++j){
if(B[j] == A[A_pos]){
root_num =j;
break;
}
}
long distance1 = distance, distance2 = distance;
long left_high = tree_depth(A, B, start, root_num - 1, A_pos+1, distance1) ;
long right_high = tree_depth(A, B, root_num + 1, end, A_pos+1+(root_num - start), distance2);
distance = distance1 > distance2 ? distance1 : distance2;
if (right_high + left_high + 2> distance)
distance = left_high + right_high + 2;
return left_high > right_high?(left_high + 1): (right_high + 1);
}