孩子兄弟树详解(C语言版)

  

文章目录

  • 一、定义
  • 二、结构
  • 三、常用操作
  • 结语
  • 附录


一、定义

        树、森林与二叉树之间有一个自然的对应关系,它们之间可以相互转换,即任何一个森林或一棵树都可以唯一地对应一棵二叉树,而任一棵二叉树也能唯一地对应到一个森林或一棵树上。正是由于有这样的一一对应关系,可以把在树中处理的问题对应到二叉树中进行处理,从而把问题简单化。用来对应处理森林和树结构的二叉树叫做孩子兄弟树。
        要创建孩子兄弟树首先要理解如何将树和森林转化成它们对应的二叉树结构,简单的说就是"左当孩子,右做兄弟",详细的转化过程可以阅读此篇文章:树、森林与二叉树相互转化原理图
        怎么样,理解如何实现森林、树到二叉树的转换了吗?真棒,这么快就掌握了!!!
        下面给出两个转换过程给大家热热身:

        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语言版)

相关文章