孩子兄弟树实现

文章介绍了如何将树和森林转换为对应的孩子兄弟二叉树,以及这种数据结构的存储方式。定义了孩子兄弟树的节点结构,包括数据域、第一个孩子指针和下一个兄弟指针。提供了初始化、创建、获取根节点、查找节点和查找父节点等操作的C语言实现代码。
摘要由CSDN通过智能技术生成

一、定义
 树、森林与二叉树之间有一个自然的对应关系,它们之间可以相互转换,即任何一个森林或一棵树都可以唯一地对应一棵二叉树,而任一棵二叉树也能唯一地对应到一个森林或一棵树上。正是由于有这样的一一对应关系,可以把在树中处理的问题对应到二叉树中进行处理,从而把问题简单化。用来对应处理森林和树结构的二叉树叫做孩子兄弟树。

要创建孩子兄弟树首先要理解如何将树和森林转化成它们对应的二叉树结构,简单的说就是"左当孩子,右做兄弟",详细的转化过程可以阅读此篇文章:树、森林与二叉树的转换_将下列三棵树组成的森林转化为二叉树_Raise的博客-CSDN博客

下面给出两个转换过程给大家热热身:

        1、树到二叉树的转换

 

        2、森林到二叉树的转换

 二、结构
有了上述基础之后,开始介绍,孩子兄弟树的存储结构。孩子兄弟树采用孩子兄弟链存储结构是为每个结点设计3个域,即一个数据元素域、一个指向该结点的左边第一个孩子结点(长子)的指针域、一个指向该结点的下一个兄弟结点的指针域。

以下给出代码描述

//数据类型
#define ElemType char
//树结点
typedef struct TreeNode
{
    ElemType data; //数据域
    struct TreeNode *fristChild; //孩子指针
    struct TreeNode *nextSibling;  //兄弟指针
}TreeNode;

//树结构
typedef struct Tree
{
    TreeNode *root; //根结点
    ElemType refvalue; //停止标记
}Tree;


三、常用操作
初始化

//树的初始化
void InitTree(Tree *tree,ElemType ref)
{
    tree->root = NULL;
    tree->refvalue = ref;
}


创建树

//创建树:该方法提供转换后的二叉树序列来建树,实质其实就是构建二叉树
void CreateTree(Tree *tree, char *str)
{
    CreateTree(tree,tree->root,str);
}
//将树转化成二叉树来创建:str对应二叉树的先序序列
void CreateTree(Tree *tree, TreeNode *&t, char *&str)
{
    if(*str == tree->refvalue)
        t = NULL;
    else
    {
        //创建结点(根结点)
        t = (TreeNode*)malloc(sizeof(TreeNode));
        assert(t != NULL);
        t->data = *str;
        //创建孩子结点(左子树)
        CreateTree(tree,t->fristChild,++str);
        //创建兄弟结点(右子树)
        CreateTree(tree,t->nextSibling,++str);
    }
}


获取根结点

//获取树根结点
TreeNode* Root(Tree *tree)
{
    return tree->root;
}


获取第一个孩子结点

//获取第一个孩子结点
TreeNode* FirstChild(Tree *tree)
{
    return FirstChild(tree->root);
}
TreeNode* FirstChild(TreeNode *t)
{
    if(t == NULL)
        return NULL;
    return t->fristChild;
}


获取第一个兄弟结点

//获取第一个兄弟结点
TreeNode* NextSibling(Tree *tree)
{
    return NextSibling(tree->root);
}
TreeNode* NextSibling(TreeNode *t)
{
    if(t == NULL)
        return NULL;
    return t->nextSibling;
}


查找结点

//查找值为key的第一个结点
TreeNode* Find(Tree *tree, ElemType key)
{
    return Find(tree->root,key);
}
TreeNode* Find(TreeNode *t, ElemType key)
{
    if(t==NULL)
        return NULL;
    if(t->data == key)//查找根结点
        return t;
    //查找孩子结点
    TreeNode *p = Find(t->fristChild,key);
    if(p != NULL)
        return p;
    return Find(t->nextSibling,key);//查找兄弟结点
}


查找某结点的父结点

//查找某结点的父结点
TreeNode* Parent(Tree *tree, TreeNode *p)
{
    return Parent(tree->root,p);
}
TreeNode* Parent(TreeNode *t, TreeNode *p)
{
    if(t==NULL || p==NULL || p==t) //要查结点为根结点:无父结点
        return NULL;
    
    TreeNode *q = t->fristChild;
    TreeNode *parent;
    while(q!=NULL && q!=p)
    {
        parent = Parent(q,p); //先查这一层的孩子结点
        if(parent != NULL)
            return parent;
        q = q->nextSibling;//孩子结点没找到,查兄弟结点
    }
    
    if(q!=NULL && q==p)
        return t;//查找到,返回
    return NULL;
}


参考

 孩子兄弟树详解(C语言版)_兄弟孩子树_红心火柴的博客-CSDN博客

数据结构(16)树与森林_森林的孩子兄弟表示法_发量充足的小姚的博客-CSDN博客

树、森林与二叉树的转换_将下列三棵树组成的森林转化为二叉树_Raise的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值