zoukankan      html  css  js  c++  java
  • 二叉树——查找两个任意节点的最近祖先

    很久没有用过二叉树了,最近由于需要用到了,发现很多知识需要巩固了,中间涉及到一个算法就是找任意两个节点的最近祖先。通过本人回顾和演算,最终提出了下面一个方法,网上也有很多其他的方式实现,再次仅对自己好几个小时的工作作个记录和积累吧! 程序是用C语言写的,个人觉得如果用C#实现会更加方便。

    首先是数据结构定义:

    1. typedef char TElemType;  
    2. typedef bool Status;  
    3.   
    4. typedef struct BiTNode{  
    5.     TElemType data;  
    6.     struct BiTNode * lchild, * rchild;  
    7. }BiTNode, * BiTree;  

    其次是建树,用树的定义,以先序序列递归方式建立。

    1. BiTNode * CreateBiTree()   
    2. {  
    3.     char ch;  
    4.     BiTNode * T;  
    5.     scanf("%c",&ch);  
    6.     if(ch=='#')  
    7.         T = 0;  
    8.     else  
    9.     {  
    10.         T = (BiTree)malloc(sizeof(BiTNode));  
    11.         T->data = ch;  
    12.         T->lchild = CreateBiTree();  
    13.         T->rchild = CreateBiTree();  
    14.     }  
    15.     return T;  
    16. }  


    空节点的分隔符本处使用的是“#”,可以用其他字符替代。

    查找最近祖先的基本算法是递归,对每个节点先判断是否有直接关联,都没有就分别获得各自的直系父节点,递归调用时需要通过两个节点的深度来判断下一次调用时用哪个使用父节点。具体实现如下:

    1. //查找两个节点的最近的公共祖先节点  
    2. BiTNode * FindNearestAncestor(BiTNode * root, BiTNode* p1, BiTNode* p2, int h1, int h2)   
    3. {  
    4.     if(!p1 || !p2) return 0;  
    5.     if (p1 == p2)  
    6.     {  
    7.         if (p1 == root) return root;  
    8.         return p1;  
    9.     }     
    10.     if (p1 == p2->lchild || p1 == p2->rchild)  
    11.         return p2;  
    12.     if (p2 == p1->lchild || p2 == p1->rchild)  
    13.         return p1;  
    14.       
    15.     if (h1 == h2)  
    16.         return FindNearestAncestor(  
    17.                     root,   
    18.                     GetParent(root, p1),  
    19.                     GetParent(root, p2),   
    20.                     h1 - 1,   
    21.                     h2 - 1);  
    22.     else  
    23.         return FindNearestAncestor(  
    24.                     root,   
    25.                     h1 > h2 ? GetParent(root, p1) : p1,  
    26.                     h1 < h2 ? GetParent(root, p2) : p2,  
    27.                     h1 > h2 ? h1 - 1 : h1,   
    28.                     h1 < h2 ? h2 - 1 : h2);  
    29. }  


    其中GetParent是获取以root为树根的树中p节点的直系父节点,定义如下:

    1. BiTNode * GetParent(BiTNode* root, BiTNode * p)  
    2. {  
    3.     if(!root || p == root) return 0;  
    4.     if(p == root->lchild || p == root->rchild)  
    5.     {  
    6.         return root;  
    7.     }  
    8.     else  
    9.     {  
    10.         return GetParent(root->lchild, p) == 0 ?  
    11.                GetParent(root->rchild, p) : GetParent(root->lchild, p);  
    12.     }  
    13. }  

    在主函数中调用如下:

    [csharp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
     
    1. int main()  
    2. {  
    3.     //测试序列: abc###de##fg###   
    4.     printf("请输入前序序列,空节点用‘#’代替: ");  
    5.     BiTree tree = CreateBiTree();  
    6.         BiTNode * node = FindNearestAncestor(   tree,   
    7.           tree->rchild->lchild,   
    8.               tree->rchild->rchild->lchild,  
    9.           GetHeight(tree,tree->rchild->lchild),  
    10.           GetHeight(tree,tree->rchild->rchild->lchild)  
    11.     );  
    12.   
    13.     printf("节点%c和节点%c的最近父节点为:%c ",   
    14.         tree->rchild->lchild->data,  
    15.         tree->rchild->rchild->lchild->data,  
    16.         node->data);  
    17.     return 0;  
    18. }  


    上述使用了GetHeight函数,用来获取给定树中节点p的高度,这个函数的实现耗费了较多时间,主要是以前都是获取树的高度,很少获取指定节点的高度,其实现如下:

    1. //查找节点p的高度,注意与单纯只计算树的高度不同   
    2. int GetHeight(BiTNode* root, BiTNode * p, int h = 1)  
    3. {  
    4.     if (!root) return 0;  
    5.     if (p == root->lchild || p == root->rchild) return h + 1;  
    6.     return  GetHeight(root->lchild, p, h+1) == 0 ?   
    7.             GetHeight(root->rchild, p, h+1) : GetHeight(root->lchild, p, h+1);  
    8. }  


    上述测试使用的先序序列为

    abc###de##fg###

    对应的二叉树如下:

                    a

                 /      

              b          d
             /           /    

          c           e       f  

                              / 

                           g

    结果如下:

     仅此记录,供以后忘记了查阅,同时也希望和大家分享。

  • 相关阅读:
    ArcGIS for Android示例解析之高亮要素-----HighlightFeatures
    ArcGIS Runtime for Android开发教程V2.0(8)基础篇-----地图事件
    ArcGIS for Android示例解析之空间查询-----QueryTask
    ArcGIS for Android地图控件的5大常见操作
    ArcGIS Runtime for Android开发教程V2.0(4)基础篇---MapView
    ArcGIS for Android 中MapView的地图背景设置
    使用Arcglobe 10与3dmax建立三维城市
    使用PowerDesigner建立数据库模型
    一步一步学Remoting系列文章
    App集成支付宝
  • 原文地址:https://www.cnblogs.com/oshyn/p/3695035.html
Copyright © 2011-2022 走看看