首页 > 代码库 > 变形二叉树中节点的最大距离(树的最长路径)——非递归解法

变形二叉树中节点的最大距离(树的最长路径)——非递归解法

问题描述:

如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两节点之间边的个数。

 写一个程序,求一棵二叉树中相距最远的两个节点之间的距离。测试用的树:

                                  n1

                             /             \

                          n2             n3

                       /        \

                   n4          n5

                 /     \         /   \

              n6    n7    n8    n9

             /                       /

         n10                 n11

不幸的是,我一开始就把题目看错了:把“父子节点之间的连线看成是双向的”理解成为,在节点的定义中真的有指向父节点的指针。。。。

将错就错,我干脆把错误理解的题目先做出来再说。于是,为了实现非递归解法,自定义了一种奇怪的数节点struct。。。。

于是,事情变成了:我为了解决题目,改了题目要求。。。。。。。晕

其实对于原题,根据树结构,用我所定义的节点,初始化一棵变形二叉树,再用这种非递归解法求解即可,只不过初始化树还需要做些工作。这种解法也不是完全没有意义。。。。

对于原题的解法,以后再说。

算法:

题目就是求一棵树中的最长路径

对于节点t,以它为根的树的最长路径longstpath一定是下列三个数中的最大值

①t的左子树的longstpath

②t的右子树的longstpath

③t的左子树的深度+t的右子树的深度+2

                                                                               ——结论1

所以对于每个节点,有两个重要的属性:①以该节点为根的树的深度②以该节点为根的树的最大路径长度

从每个叶节点开始,自底向上进行处理。每次处理的过称为:

若该节点两个属性均已确定,将它们“告知”父节点,父节点得到所有子节点的属性后,根据结论1方可确定自己的两个属性。继续向上“报告”自己的属性。

对于没有了解到所有子节点属性的父节点,让他在每一次处理中”等待“子节点的报告,显然,需要一个队列queue存储正在等待的节点。

代码实现:

#include<iostream>
#include "Queue.h"
using namespace std;

//节点结构体
struct BinaryTreeNode
{
	BinaryTreeNode* father = NULL;//指向父节点
	BinaryTreeNode* left = NULL;
	BinaryTreeNode* right = NULL;
	int arrived = 0;//记录子树深度值到达的数目,取值为0或1或2
	int depth = 0;//以此节点为根的树的深度
	int longstpath = 0;//以此节点为根的树中的最长路径
	bool stored = false;//是否已入列等待
};

//取大值
int max2(int a, int b)
{
	if (a > b)
		return a;
	else return b;
}

//取大值
int max3(int a, int b, int c)
{
	return max2(max2(a, b), c);
}

//根据不同情况(有的节点无左/右子节点),更新longstpath
//longstpath一定是以下三数中的最大值:左子树的longstpath,右子树的longstpath,左右子树深度和+2
void SetLongstpath(BinaryTreeNode* temp)
{
	int lpath, rpath, ldepth, rdepth;
	if (temp->left)
	{
		lpath = temp->left->longstpath;   ldepth = temp->left->depth;
	}
	else lpath = ldepth = 0;
	if (temp->right)
	{
		rpath = temp->right->longstpath;   rdepth = temp->right->depth;
	}
	else rpath = rdepth = 0;
	temp->longstpath = max3(lpath, rpath, ldepth + rdepth + 2);//更新最长路径longstpath
}

int FindPath(Queue<BinaryTreeNode*> &queue)
{
	BinaryTreeNode* temp;
	while (!queue.IsEmpty())
	{
		queue.Delete(temp);
		temp->stored = false;
		if (temp->arrived == 2)//子节点都到达了,万事俱备
		{
			SetLongstpath(temp);//更新temp的Longstpath
			if (temp->father)//若不是根节点,,则上移该节点(即对父节点进行处理)
			{
				temp->father->depth = max2(temp->father->depth, temp->depth + 1);//更新父节点的深度值
				temp->father->arrived++;//到达子节点数目+1
				if (!temp->father->stored)//说明这是第一个到达的子节点,该父节点从未入列,则将其入列
				{
					queue.Add(temp->father);
					temp->father->stored = true;
				}
			}
			else//根节点,返回longstpath
				return temp->longstpath;
		}
		if (temp->arrived == 1)//有子节点还没到,更新longstpath的条件不充分,重新入列等待子节点
		{
			queue.Add(temp);
			temp->stored = true;
		}
	}
}

void main()
{
	BinaryTreeNode* n1 = new BinaryTreeNode;
	BinaryTreeNode* n2 = new BinaryTreeNode;
	BinaryTreeNode* n3 = new BinaryTreeNode;
	BinaryTreeNode* n4 = new BinaryTreeNode;
	BinaryTreeNode* n5 = new BinaryTreeNode;
	BinaryTreeNode* n6 = new BinaryTreeNode;
	BinaryTreeNode* n7 = new BinaryTreeNode;
	BinaryTreeNode* n8 = new BinaryTreeNode;
	BinaryTreeNode* n9 = new BinaryTreeNode;
	BinaryTreeNode* n10 = new BinaryTreeNode;
	BinaryTreeNode* n11 = new BinaryTreeNode;
	//构造二叉树
	n2->father = n3->father = n1;
	n4->father = n5->father = n2;
	n6->father = n7->father = n4;
	n8->father = n9->father = n5;
	n10->father = n6;
	n11->father = n9;
	n6->left = n10;
	n4->left = n6; n4->right = n7;
	n9->left = n11;
	n5->left = n8; n5->right = n9;
	n2->left = n4; n2->right = n5;
	n1->left = n2; n1->right = n3;

	n3->arrived = 2;//叶节点初始为2
	n7->arrived = 2;
	n8->arrived = 2;
	n10->arrived = 2;
	n11->arrived = 2;
	n6->arrived = 1;//但孩子节点初始为1
	n9->arrived = 1;

	Queue<BinaryTreeNode*> queue;
	queue.Add(n3);
	n3->stored = true;
	queue.Add(n7);
	n7->stored = true;
	queue.Add(n8);
	n8->stored = true;
	queue.Add(n10);
	n10->stored = true;
	queue.Add(n11);
	n11->stored = true;

	cout << "最大路径长度:" << FindPath(queue) << endl;
	system("pause");
}




变形二叉树中节点的最大距离(树的最长路径)——非递归解法