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

    非常实用的太久没有一个二叉树,因为需要使用最近,我们觉得非常有必要巩固知识。中间涉及到一个随机算法是寻找两个节点的直接祖先。

    我记得和牙石通过,于提出了以下一个方法,网上也有非常多其它的方式实现,再次仅对自己好几个小时的工作作个记录和积累吧!

    程序是用C语言写的,个人认为假设用C#实现会更加方便。

    首先是数据结构定义:

    typedef char TElemType;
    typedef bool Status;
    
    typedef struct BiTNode{
    	TElemType data;
    	struct BiTNode * lchild, * rchild;
    }BiTNode, * BiTree;

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

    BiTNode * CreateBiTree() 
    {
    	char ch;
        BiTNode * T;
        scanf("%c",&ch);
        if(ch=='#')
    		T = 0;
        else
    	{
            T = (BiTree)malloc(sizeof(BiTNode));
            T->data = ch;
            T->lchild = CreateBiTree();
            T->rchild = CreateBiTree();
        }
        return T;
    }

    空节点的分隔符本处使用的是“#”,能够用其它字符替代。

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

    详细实现例如以下:

    //查找两个节点的近期的公共祖先节点
    BiTNode * FindNearestAncestor(BiTNode * root, BiTNode* p1, BiTNode* p2, int h1, int h2) 
    {
    	if(!p1 || !p2) return 0;
    	if (p1 == p2)
    	{
    		if (p1 == root) return root;
    		return p1;
    	}	
    	if (p1 == p2->lchild || p1 == p2->rchild)
    		return p2;
    	if (p2 == p1->lchild || p2 == p1->rchild)
    		return p1;
    	
    	if (h1 == h2)
    		return FindNearestAncestor(
    					root, 
    					GetParent(root, p1),
    					GetParent(root, p2), 
    					h1 - 1, 
    					h2 - 1);
    	else
    		return FindNearestAncestor(
    					root, 
    					h1 > h2 ? GetParent(root, p1) : p1,
    					h1 < h2 ?

    GetParent(root, p2) : p2, h1 > h2 ?

    h1 - 1 : h1, h1 < h2 ? h2 - 1 : h2); }


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

    BiTNode * GetParent(BiTNode* root, BiTNode * p)
    {
    	if(!root || p == root) return 0;
    	if(p == root->lchild || p == root->rchild)
    	{
    		return root;
    	}
    	else
    	{
    		return GetParent(root->lchild, p) == 0 ?

    GetParent(root->rchild, p) : GetParent(root->lchild, p); } }

    在主函数中调用例如以下:

    int main()
    {
    	//測试序列: abc###de##fg### 
    	printf("请输入前序序列。空节点用‘#’取代:
    ");
    	BiTree tree = CreateBiTree();
            BiTNode * node = FindNearestAncestor(   tree, 
    	      tree->rchild->lchild, 
                  tree->rchild->rchild->lchild,
    	      GetHeight(tree,tree->rchild->lchild),
    	      GetHeight(tree,tree->rchild->rchild->lchild)
    	);
    
    	printf("节点%c和节点%c的近期父节点为:%c
    ", 
    		tree->rchild->lchild->data,
    		tree->rchild->rchild->lchild->data,
    		node->data);
    	return 0;
    }

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

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

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

    abc###de##fg###

    相应的二叉树例如以下:

                    a

                 /      

              b          d
             /           /    

          c           e       f  

                              / 

                           g

    结果例如以下:


     只有这个纪录。现在,忘记之后。同时也想和大家分享。





  • 相关阅读:
    Linux常用命令2
    Linux常用命令1
    Nginx配置Kafka
    SpringBoot整合Druid
    spring boot jpa
    mybatis-plus_2
    copy data to map
    HashMap容量问题
    在SpringBoot主启动类中获取实例化的Bean
    Linux环境中Rsync增量备份文件
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5046595.html
Copyright © 2011-2022 走看看