zoukankan      html  css  js  c++  java
  • 变形二叉树中节点的最大距离(树的最长路径)——非递归解法

    问题描写叙述:

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

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

                                      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");
    }




  • 相关阅读:
    AE开发 入门教程
    工作空间工厂 打开文件例子
    Delphi IDE使用的一些主要技巧
    动画演示 Delphi 2007 IDE 功能[2]
    Delphi的类与继承
    属性的自动完成
    DELPHI中函数、过程变量的声明与应用
    Delphi回车键切换焦点
    delphi 窗体的创建和释放
    delphi assigned函数的用法
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5387463.html
Copyright © 2011-2022 走看看