Description
二叉树两个结点的距离是一个结点经过双亲结点,祖先结点等中间结点到达另一个结点经过的分支数。二叉树结点的最大距离是所有结点间距离的最大值。例如,下图所示二叉树结点最大距离是3,C和D的距离。
A
/ \
B D
\
C
二叉树用先序遍历顺序创建,#表示空树。计算二叉树结点最大距离和最大距离的两个结点。
如果有多个解,输出字典序最小的解(即第一个结点字母更小的,如果第一个字母相同,输出第二个结点字母更小的)。
Input
测试次数T
第2行之后的T行,每行为一棵二叉树先序遍历结果(#
表示空树)
Output
对每棵二叉树,输出树的结点最大距离和最大距离的结点,输出格式见样例。
Sample
INPUT | OUTPUT |
3 A## ABC##EF#G###D## ABEH###F#K### | 0: 5:D G 4:H K |
思路:
可以想到最长的距离就是叶子间的距离、根与叶子的距离。
那么我们只需要取出叶子和根组成一个有序数组(满足输出要求),然后循环计算每两个点的距离即可
距离的计算可以在每颗树中打上深度标记,然后利用这个深度标记来进行计算。
实现代码:
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
class BinaryTree;
class btnode
{
public:
char data; // 数据
int depth; // 深度
btnode *leftChild, *rightChild, *parent; // 指针
btnode() : leftChild(NULL), rightChild(NULL), parent(NULL) {}
~btnode()
{
delete leftChild;
delete rightChild;
}
};
class BinaryTree
{
private:
btnode *root = NULL; // 根
string strTree; // 建立树所用字符串
vector<btnode *> nodes; // 所有用于计算两点最大距离的结点(各叶子结点和起点)
int pos = 0; // 建立树所用字符串的指针
public:
BinaryTree() : root(NULL){};
BinaryTree(string input); // 进入从根节点进入递归
btnode *treeCreate(btnode *Pa); // 递归建树
void depthSet(btnode *t); // 设置每个结点的深度
void depthSet() { depthSet(root); }
void nodesDistance(); // 计算节点的长度
};
BinaryTree::BinaryTree(string input)
{
strTree = input;
root = treeCreate(nullptr);
pos = 0;
}
btnode *BinaryTree::treeCreate(btnode *Pa)
{
// 避免访问溢出
if (pos < strTree.length())
{
// 空节点或者到达尽头;
if (strTree.length() == pos || strTree[pos] == '#')
{
pos++;
return NULL;
}
btnode *T = new btnode();
T->data = strTree[pos++];
T->parent = Pa;
T->leftChild = treeCreate(T);
T->rightChild = treeCreate(T);
return T;
}
return NULL;
}
// 标记每层的深度
void BinaryTree::depthSet(btnode *t)
{
int level = 0, size;
queue<btnode *> qt;
qt.push(t);
while (!qt.empty())
{
size = qt.size();
for (int i = 0; i < size; i++)
{
if (qt.front()->leftChild)
qt.push(qt.front()->leftChild);
if (qt.front()->rightChild)
qt.push(qt.front()->rightChild);
// 标记每层深度
qt.front()->depth = level;
// 记录所有叶子结点与头节点
if (qt.front() == root || (!qt.front()->leftChild && !qt.front()->rightChild))
nodes.push_back(qt.front());
qt.pop();
}
level++;
}
}
void BinaryTree::nodesDistance()
{
// 对结点数组排序(满足题目所要求的顺序)
sort(nodes.begin(), nodes.end(),
[](auto a, auto b)
{
return a->data < b->data;
});
int max = 0,dis = 0; // 记录最长距离
char ans1 = ' ', ans2 = ' '; // 记录最长距离的两个结点,默认为空(有利于只有根节点的时候输出)
// 比较每两个结点的距离
for (auto it1 = nodes.begin(); it1 != nodes.end(); it1++)
{
for (auto it2 = it1+1; it2 != nodes.end(); it2++)
{
dis = 0;
btnode *p1 = *(it1); // 操作用临时结点
btnode *p2 = *(it2);
if (p1->depth < p2->depth)swap(p1, p2);
while (p1->depth > p2->depth) //先让两个临时结点去到同一层
{
p1 = p1->parent;
dis++;
}
//判断是否到达共同的祖先结点
while (p1 != p2)
{
p1 = p1->parent;
p2 = p2->parent;
dis += 2;
}
// 记录数据
if (max < dis)
{
max = dis;
ans1 = (*it1)->data;
ans2 = (*it2)->data;
}
}
}
cout << max << ":" << ans1 << " " << ans2<< endl;
}
int main()
{
int t;
string str;
cin >> t;
while (t--)
{
cin >> str;
BinaryTree bt(str);
bt.depthSet();
bt.nodesDistance();
}
return 0;
}