目录
题目描述:
二叉树两个结点的距离是一个结点经过双亲结点,祖先结点等中间结点到达另一个结点经过的分支数。二叉树结点的最大距离是所有结点间距离的最大值。例如,下图所示二叉树结点最大距离是3,C和D的距离。
二叉树用先序遍历顺序创建,#表示空树。计算二叉树结点最大距离和最大距离的两个结点(假设二叉树中取最大距离的两个结点唯一)。
输入
测试次数T
第2行之后的T行,每行为一棵二叉树先序遍历结果(#表示空树)
输出
对每棵二叉树,输出树的结点最大距离和最大距离的结点,输出格式见样例。
输入样例:
3
A##
ABC##EF#G###D##
ABEH###F#K###
输出样例:
0:
5:G D
4:H K
思路:
题目求的是任意2个结点间的距离的最大值,很容易能想到距离最远的2个结点必然是叶子结点,即最深的结点,而所求的这2个结点存在两种情况:路径经过根结点与不经过根结点。而无论是哪一种情况,所求2个结点都在以某一结点为根结点的树上,而这2个结点的距离则是这个树的左右子树深度(或高度)和。
所以问题就等同于:计算每个结点的左右子树的深度和,并保存左右子树最深层的值,最后取深度和的最大值及与之对应的左右最深层的值
代码:
#include <iostream>
#include <string>
using namespace std;
class BiTreeNode {
public:
char data; //数据域
BiTreeNode* leftChild, * rightChild; //左右子树指针
BiTreeNode() :leftChild(NULL), rightChild(NULL) {}
~BiTreeNode() {}
};
class BiTree {
private:
BiTreeNode* root; //根结点指针
string sTree; //建树字符串
int pos; //标识建树字符串的当前字符位置
int maxdis; //最大距离
int deep; //保存子树深度
int leftdeep, rightdeep;//保存左右子树深度
char c; //最深层的字符
char leftc,leftc_temp, rightc,rightc_temp; //左右子树最深层字符
BiTreeNode* CreateTree();//建树私有函数
void getdeep(BiTreeNode* t,int i);//私有函数,求以t为根节点的子树的深度,i用来保存当前结点深度
void getleftdeep(BiTreeNode* t);//求左深度
void getrightdeep(BiTreeNode* t);//求右深度
void getmax(BiTreeNode* t); //私有函数,求最大距离的递归函数
public:
BiTree() :root(NULL) { }
void Create(string vArray); //建树公有接口,参数是特定的先序遍历字符串
void getmaxdis();//求最大距离并输出
};
//函数的实现
void BiTree::Create(string vArray)
{
pos = 0;
sTree.assign(vArray); //把参数保存到内部字符串
root = CreateTree(); //建树成功后root指向根结点
}
BiTreeNode* BiTree::CreateTree()//建树私有函数,先序遍历,递归建树
{
BiTreeNode* t = NULL;
if (sTree[pos] != '#')
{
t = new BiTreeNode();
t->data = sTree[pos];
pos++;
t->leftChild = CreateTree();
t->rightChild = CreateTree();
}
else
pos++;
return t;
}
void BiTree::getmaxdis()//求最大距离并输出
{
maxdis = 0;
getmax(root);
cout << maxdis << ':';
if (maxdis)
cout << leftc <<' '<< rightc;
cout << endl;
}
void BiTree::getmax(BiTreeNode* t)//计算以t结点为根结点的树的左右深度之和
{
if (t != NULL)
{
deep = 0;
getleftdeep(t); //计算左子树的深度
deep = 0;
getrightdeep(t); //计算右子树的深度
if (maxdis < leftdeep + rightdeep)//如果目前保存的距离最大值小于这次求得的新树最大值,对其修改
{
maxdis = leftdeep + rightdeep;
leftc = leftc_temp;
rightc = rightc_temp;
}//maxdis为最终所求最大距离,leftc和rightc为最终最大距离对应的2个结点,leftc_temp和rightc_trmp为当前新树(小树)的最大距离对应的结点
//遍历出每个结点作根结点所对应的树
getmax(t->leftChild);
getmax(t->rightChild);
}
}
void BiTree::getdeep(BiTreeNode* t,int i)//私有函数,求以t为根节点的子树的深度,i用来保存当前结点深度
{
if (t != NULL)
{
i++;
if (t->leftChild == NULL && t->rightChild == NULL)
{
if (deep < i)
{
deep = i;
c = t->data;//最深层的字符
}
}
getdeep(t->leftChild, i);
getdeep(t->rightChild, i);
}
}
void BiTree::getleftdeep(BiTreeNode* t)//求左深度
{
if (t->leftChild == NULL)//左子树空则左子树深度为0
{
leftdeep = 0;
leftc_temp = t->data;
return;
}
t = t->leftChild;
getdeep(t, 0);//求左子树深度
leftdeep = deep;
leftc_temp = c;
}
void BiTree::getrightdeep(BiTreeNode* t)//求右深度
{
if (t->rightChild == NULL)//右子树空则右深度为0
{
rightdeep = 0;
rightc_temp = t->data;
return;
}
t = t->rightChild;
getdeep(t, 0);//求右子树深度
rightdeep = deep;
rightc_temp = c;
}
int main()
{
int t;
string vArray;
cin >> t;
while (t--)
{
cin >> vArray;
BiTree myTree;
myTree.Create(vArray);
myTree. getmaxdis();
}
return 0;
}
前言:
这篇文章算是我的学习笔记,是我在学《数据结构(C语言版)》遇到的值得记录的题目,记录下来方便我随时翻看以复习反思。
总结:
刚遇到这题的时候可把我难住了,当时用递归从底层开始求出最大距离但又保存不了对应的结点值,现在用的是直接从上往下求深度并保存对应的值。代码可以试试求深度函数返回一个值(深度或者对应的字符),应该能改善一些代码?
有无大佬有更简单的方法啊,捞捞~