【数据结构】十分钟带你入门树结构!


前言

一、树的定义

1.专业定义:
<1> 有且只有一个根节点。
<2> 由若干个互不相干的子树,这些子树本身也是一棵树通俗的定义。


1.通俗的定义:
<1> 树是由节点和边组成的。
<2> 每个节点只有一个父亲节点但可以有多个子节点。
<3> 有一个节点例外,该节点没有父亲节点,此节点称为根节点。

二、专业术语

1.深度
从根节点到最底层节点的层数称为深度,根节点是第一层。


2.叶子结点
没有子节点的节点


3.非终端节点
实际就是非叶子节点


4.度
最大子节点的个数称为度

三、树的分类

1.一般树
任意一个节点的子节点的个数不受限制。


2.二叉树
任意一个子节点的个数最多是二,且子节点的位置不可更改。



<1> 满二叉树:在不增加树的层数的情况下无法在多添加一个节点的二叉树就是满二叉树



在这里插入图片描述



<2> 完全二叉树:如果只是删除了满二叉树最底层最右边的连续若干个节点,这样形成的二叉树就是完全二叉树。

在这里插入图片描述



3.森林
n个互不相交的树的集合


在这里插入图片描述


四、二叉树的存储

1.连续存储(完全二叉树)



在这里插入图片描述


改造后的存储结果:
在这里插入图片描述



2.连续存储的优缺点

优点:查找某个父节点和子节点(包括判断有无子节点)速度很快。


缺点:太耗内存空间。


3.链式存储

每个节点包含三个域,两个指针域和一个数值域。其中两个指针域用来指向两个孩子节点,数值域保存节点信息。

在这里插入图片描述


在这里插入图片描述


五、森林的存储

1.存储思路
将森林转化为二叉树在进行存储
设法保证任意一个节点的:
<1> 左指针指向他的第一个孩子。
<2> 右指针指向他的下一个兄弟节点
<3> 将各个树的根节点互相看做兄弟节点。
2.例图如下

在这里插入图片描述




转换为二叉树之后的存储结构:

在这里插入图片描述


六、二叉树的遍历

1.先序遍历(先访问根节点)
先访问根节点。
再访问左子树。
最后访问右子树。

原理图:


在这里插入图片描述

例图:

在这里插入图片描述


2.中序遍历(中间访问根节点)
先访问左子树。
中间访问根节点。
最后访问右子树。

原理图:

在这里插入图片描述


例图:

在这里插入图片描述



3.后序遍历(最后访问根节点)
先访问左子树。
再访问右子树。
最后访问根节点。


原理图:
在这里插入图片描述


例图:

在这里插入图片描述


七、树应用的简单介绍


<1> 树是数据库中数据组织的一种重要形式。

<2> 操作系统父子进程本身就是一棵树。

<3> 面向对象语言类的继承关系本身就是一棵树。


八、链式二叉树三种遍历顺序详解(代码实现)

1.目标树结构


在这里插入图片描述

2.主函数

#include<stdio.h>
#include<malloc.h>
struct TreeNode {
    
    
	char data;
	struct TreeNode * pLchild; //p是指针,Lchild是左孩子 
	struct TreeNode * pRchild;
};
struct TreeNode * CreatBTree();
void FirstOrderBTree(struct TreeNode *pT);//先序函数声明 
void InFixOrderBTree(struct TreeNode *pT); //中序函数声明 
void PostOrderBTree (struct TreeNode *pT);//后序函数声明 
 
int main()
{
    
    
	struct TreeNode *pT=CreatBTree(); //定义树 
    printf("先序遍历结果为:"); 
	FirstOrderBTree(pT);//先序 
	printf("\n"); 
    printf("中序遍历结果为:"); 
	InFixOrderBTree(pT);//中序 
	printf("\n"); 
	printf("后序遍历结果为:"); 
	PostOrderBTree(pT);//后序 
	
     return 0;
	
}

3.代码构建树

struct TreeNode * CreatBTree(void)// 
{
    
    
	struct TreeNode* pA =(struct TreeNode *) malloc(sizeof(struct TreeNode));//定义A结点
	struct TreeNode* pB =(struct TreeNode *) malloc(sizeof(struct TreeNode));//定义B结点
	struct TreeNode* pC =(struct TreeNode *) malloc(sizeof(struct TreeNode));
	struct TreeNode* pD =(struct TreeNode *) malloc(sizeof(struct TreeNode));
	struct TreeNode* pE =(struct TreeNode *) malloc(sizeof(struct TreeNode));
    pA->data='A'; //指向他的数据域
    pB->data='B';
    pC->data='C';
    pD->data='D';
    pE->data='E';
    pA->pLchild=pB; //pA的左子树指向
    pA->pRchild=pC;
    pB->pLchild=pB->pRchild=NULL;//pB没有孩子结点
    pC->pLchild=pD;
    pC->pRchild=NULL;
    pD->pLchild=NULL;
    pD->pRchild=pE;
    pE->pLchild=pE->pRchild=NULL;
    return pA;
	
}




3.先序中序后序函数

先序思路分析:pT->pLchild可以表示整个左子树,则在先序遍历的时候我可以先输出根节点,然后使用递归输出我的左子树,当左子树输出完递归结束。再用同样的方法递归出右子树。

void FirstOrderBTree(struct TreeNode *pT)   //先序遍历
                                           //先访问根节点再访问左子树最后访问右子树 
{
    
    
	if(pT!=NULL)
	{
    
     
	printf("%c  ",pT->data);
	                            //pT->pLchild可以表示整个左子树 
	FirstOrderBTree(pT->pLchild);//采用递归算法遍历左子树 
	
	FirstOrderBTree(pT->pRchild);//再采用递归算法遍历右子树 
    }
		 
}



中序思路分析:先递归输出左子树,然后输出根节点,最后递归输出右子树。

void InFixOrderBTree(struct TreeNode *pT)   //中序遍历
                                           //先访问左子树再访问根节点最后访问右子树 
{
    
    
	if(pT!=NULL)
	{
    
     

	                            
	InFixOrderBTree(pT->pLchild);//先采用递归算法遍历左子树 
		printf("%c  ",pT->data);  // 然后遍历根节点 
    InFixOrderBTree(pT->pRchild);//最后采用递归算法遍历右子树 
    }
		 
}



后序思路分析:先递归输出左子树,然后递归输出右子树,最后输出根节点。

void InFixOrderBTree(struct TreeNode *pT)   //中序遍历
                                           //先访问左子树再访问根节点最后访问右子树 
{
    
    
	if(pT!=NULL)
	{
    
     

	                            
	InFixOrderBTree(pT->pLchild);//先采用递归算法遍历左子树 
		printf("%c  ",pT->data);  // 然后遍历根节点 
    InFixOrderBTree(pT->pRchild);//最后采用递归算法遍历右子树 
    }
		 
}

void PostOrderBTree (struct TreeNode *pT)   //后序遍历
                                           //先访问左子树再访问右节点最后访问根节点 
{
    
    
	if(pT!=NULL)
	{
    
     

	                            
	PostOrderBTree(pT->pLchild);//先采用递归算法遍历左子树 
	
    PostOrderBTree(pT->pRchild);//再采用递归算法遍历右子树 
    
    printf("%c  ",pT->data);  // 最后遍历根节点 
    }
		 
}




运行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_50302770/article/details/117264041