• 二叉树的最大距离


    问题定义

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

    对于任意一个节点,以该节点为根,假设这个根有k个孩子节点,那么距离最远的两个节点U与V之间的路径与这个根节点的关系有两种。

    1).若路径经过Root,则U和V属于不同子树的,且它们都是该子树中到根节点最远的节点,否则跟它们的距离最远相矛盾

    2).如果路径不经过Root,那么它们一定属于根的k个子树之一,并且它们也是该子树中相距最远的两个顶点

    因此,问题就可以转化为在字数上的解,从而能够利用动态规划来解决。

    设第K棵子树中相距最远的两个节点:Uk和Vk,其距离定义为d(Uk,Vk),那么节点Uk或Vk即为子树K到根节点Rk距离最长的节点。不失一般性,我们设Uk为子树K中道根节点Rk距离最长的节点其到根节点的距离定义为d(Uk,R)。取d(Ui,R)(1<=i<=k)中最大的两个值max1和max2,那么经过根节点R的最长路径为max1+max2+2,所以树R中相距最远的两个点的距离为:max{d(U1,V1),…, d(Uk,Vk),max1+max2+2}。

    • 情况A: 路径经过左子树的最深节点,通过根节点,再到右子树的最深节点。
    • 情况B: 路径不穿过根节点,而是左子树或右子树的最大距离路径,取其大者。

    只需要计算这两个情况的路径距离,并取其大者,就是该二叉树的最大距离。

     1 // 数据结构定义 
     2 struct NODE
     3 {
     4     NODE* pLeft; // 左子树 
     5     NODE* pRight; // 右子树 
     6     int nMaxLeft; // 左子树中的最长距离 
     7     int nMaxRight; // 右子树中的最长距离 
     8     char chValue; // 该节点的值 
     9 };
    10 int nMaxLen = 0;
    11 // 寻找树中最长的两段距离 
    12 void FindMaxLen(NODE* pRoot)
    13 {
    14     // 遍历到叶子节点,返回 
    15     if(pRoot == NULL)
    16     {
    17         return;
    18     }
    19     // 如果左子树为空,那么该节点的左边最长距离为0 
    20     if(pRoot -> pLeft == NULL)
    21     {
    22         pRoot -> nMaxLeft = 0;
    23     }
    24     // 如果右子树为空,那么该节点的右边最长距离为0 
    25     if(pRoot -> pRight == NULL)
    26     {
    27         pRoot -> nMaxRight = 0;
    28     }
    29      // 如果左子树不为空,递归寻找左子树最长距离 
    30     if(pRoot -> pLeft != NULL)
    31     {
    32         FindMaxLen(pRoot -> pLeft);
    33     }
    34     // 如果右子树不为空,递归寻找右子树最长距离 
    35     if(pRoot -> pRight != NULL)
    36     {
    37         FindMaxLen(pRoot -> pRight);
    38     }
    39     // 计算左子树最长节点距离 
    40     if(pRoot -> pLeft != NULL)
    41     {
    42         int nTempMax = 0;
    43         if(pRoot -> pLeft -> nMaxLeft > pRoot -> pLeft -> nMaxRight)
    44         {
    45             nTempMax = pRoot -> pLeft -> nMaxLeft;
    46         }
    47         else
    48         {
    49             nTempMax = pRoot -> pLeft -> nMaxRight;
    50         }
    51         pRoot -> nMaxLeft = nTempMax + 1;
    52     }
    53      // 计算右子树最长节点距离 
    54     if(pRoot -> pRight != NULL)
    55     {
    56         int nTempMax = 0;
    57         if(pRoot -> pRight -> nMaxLeft > pRoot -> pRight -> nMaxRight)
    58         {
    59             nTempMax = pRoot -> pRight -> nMaxLeft;
    60         }
    61         else
    62         {
    63             nTempMax = pRoot -> pRight -> nMaxRight;
    64         }
    65         pRoot -> nMaxRight = nTempMax + 1;
    66     }
    67     // 更新最长距离 
    68     if(pRoot -> nMaxLeft + pRoot -> nMaxRight > nMaxLen)
    69     {
    70         nMaxLen = pRoot -> nMaxLeft + pRoot -> nMaxRight;
    71     }
    72 }
  • 相关阅读:
    刚学的 activity 之间的两种(带数据)跳转
    SharePreference 把少量数据写到 文件中
    Android 使用资源
    SQLite 初步测试
    android 操作 sd 卡上的文件
    android 操作文件
    002android 布局(layout)
    Activity_liftCycle — 生命周期
    android 创建、删除 文件和文件夹 测试
    android 实现粗糙的文件浏览器
  • 原文地址:https://www.cnblogs.com/richardcpp/p/2719325.html
Copyright © 2020-2023  润新知