题目描述
二叉树两个结点的距离是一个结点经过双亲结点,祖先结点等中间结点到达另一个结点经过的分支数。二叉树结点的最大距离是所有结点间距离的最大值。例如,下图所示二叉树结点最大距离是3,C和D的距离。
二叉树用先序遍历顺序创建,#表示空树。计算二叉树结点最大距离和最大距离的两个结点(假设二叉树中取最大距离的两个结点唯一)。
输入
测试次数T
第2行之后的T行,每行为一棵二叉树先序遍历结果(#表示空树)
输出
对每棵二叉树,输出树的结点最大距离和最大距离的结点,输出格式见样例。
输入样例1
4
A##
ABC##EF#G###D##
ABEH###F#K###
AB###
输出样例1
0:
5:G D
4:H K
1:B A
以下是思路
以图一二叉树为例,该树节点的最大距离的路径应该为:G-F-E-B-A-D。而且可知这两节点肯定是叶子节点。如果节点数小于等于2倒比较简单,max为0不存在;为1一个为叶子节点另一个为根节点;为2则先输出左子树节点再输出右子树节点(根据先序遍历的顺序)。但如果有3个以上的叶子节点就比较麻烦;如果是从叶子节点开始往回找公共父亲节点的话又不方便实现。想到这里就应该要想到多半要用递归来做这题了。
首先来看两种情况,图一的最长路径经过根节点,而图二的最长路径不经过根节点。
那到底该咋做捏?首先我们可以先序遍历这颗二叉树,在遍历的过程中对每一个节点计算其左子树和右子树深度之和(均取最大值),并记录最深的左右子树节点。简单来说,在先序遍历时,把每一个节点都当作一个新的根节点,然后去计算其左右子树最深的位置之和。
以图一为例,假设现在在A节点。对其左右左右子树遍历可知最深的地方是G和D节点。而对于图二来说A右子树为空,那么就以先序遍历的顺序看看B节点的左右子树,发现最深的位置是H和K节点。
那么首先是建树,这题一没给权值二不用父亲节点,那包含基本的成员就行。但由于对于每个节点都要计算左右深度,并且过程分为先序遍历->查找左右子树深度,那么应该添加对应的成员和函数。所以代码如下
class Node
{
public:
Node* left, * right;
char data;
int left_len = 0;
int right_len = 0;
Node() { left = right = NULL;data = '-'; }
};
class Tree
{
private:
string str;
int pos;
public:
Node* root;
int max = 0;
Tree(string s) { str = s;pos = 0;root = create(); }
Node* create();
int depthoftree(Node* end, int& maxdepth, int curdepth, Node* tmp);
void pre(Node* end, int& max, Node* A, Node* B);
};
首先是查找深度,以该节点为根节点,对其左右子树不断查找,寻找最深的位置。那么应当用递归实现先序遍历,得到当前节点左右子树的深度,并与这棵树当前的最大深度进行比较。那么代码如下
int Tree::depthoftree(Node* end, int& maxdepth, int curdepth, Node* tmp)
{
if (end == NULL)
{
return -1;
}
depthoftree(end->left, maxdepth, curdepth + 1, tmp);
depthoftree(end->right, maxdepth, curdepth + 1, tmp);
if (curdepth > maxdepth)
{
maxdepth = curdepth;
tmp->data = end->data;
}
return maxdepth;
}
最后是先序遍历,保存每次最深的两个节点和最大深度,并先序遍历该树直至遍历完成。‘
void Tree::pre(Node* end, int& max, Node* A, Node* B)
{
if (end)
{
int d1 = -1, d2 = -1;
Node* tmp1 = new Node();
Node* tmp2 = new Node();
int curmax = depthoftree(end->left, d1, 0, tmp1) + depthoftree(end->right, d2, 0, tmp2) +2;
if (curmax > max)
{
A->data = tmp1->data;
B->data = tmp2->data;
max = curmax;
}
pre(end->left, max, A, B);
pre(end->right, max, A, B);
}
}
以下是代码
#include <iostream>
using namespace std;
class Node
{
public:
Node* left, * right;
char data;
int left_len = 0;
int right_len = 0;
Node() { left = right = NULL;data = '-'; }
};
class Tree
{
private:
string str;
int pos;
public:
Node* root;
int max = 0;
Tree(string s) { str = s;pos = 0;root = create(); }
Node* create();
int depthoftree(Node* end, int& maxdepth, int curdepth, Node* tmp);
void pre(Node* end, int& max, Node* A, Node* B);
};
Node* Tree::create()
{
char tmp = str[pos];
pos++;
if (tmp == '#')
{
return NULL;
}
else
{
Node* node = new Node();
node->data = tmp;
node->left = create();
node->right = create();
return node;
}
}
int Tree::depthoftree(Node* end, int& maxdepth, int curdepth, Node* tmp)
{
if (end == NULL)
{
return -1;
}
depthoftree(end->left, maxdepth, curdepth + 1, tmp);
depthoftree(end->right, maxdepth, curdepth + 1, tmp);
if (curdepth > maxdepth)
{
maxdepth = curdepth;
tmp->data = end->data;
}
return maxdepth;
}
void Tree::pre(Node* end, int& max, Node* A, Node* B)
{
if (end)
{
int d1 = -1, d2 = -1;
Node* tmp1 = new Node();
Node* tmp2 = new Node();
int curmax = depthoftree(end->left, d1, 0, tmp1) + depthoftree(end->right, d2, 0, tmp2) +2;
if (curmax > max)
{
A->data = tmp1->data;
B->data = tmp2->data;
max = curmax;
}
pre(end->left, max, A, B);
pre(end->right, max, A, B);
}
}
int main()
{
int t;
cin >> t;
while (t--)
{
string str;
cin >> str;
Tree tree(str);
int max = 0;
Node* A = new Node();
Node* B = new Node();
tree.pre(tree.root, max, A, B);
cout << max << ":";
if (max == 1)
{
cout << A->data << " " << tree.root->data;
}
else if (max > 1)
{
cout << A->data << " " << B->data;
}
cout << endl;
}
}