树以及二叉树的概念及其基本操作

数据结构中不仅有线性结构,还有较为复杂的树形结构,今天就来学习下树形结构吧。

文章目录

      • 1.树的概念
      • 2.树的相关概念
      • 3.树的表示
          • 3.1 孩子兄弟表示法
      • 4.树的应用
    • 二叉树
      • 1.二叉树的基本概念
      • 2.特殊的二叉树
      • 3.二叉树的性质
      • 4.二叉树的存储结构
        • 4.1二叉树的顺序结构
        • 4.2二叉树的链式结构
    • 总结

1.树的概念

树作为树形结构的扛把子(不就只有这一个树形结构吗 ),是一个由N个有限节点组成的一个具有层次关系的集合
其中树的第一个节点称为根节点,并且根节点没有前驱,而其他节点都被分为M个不同集合,而每一个集合都是一个和树结构类似的子树,而这些子树的根节点只有一个前驱,有0个和多个后续,并且树是递归定义的。

相信大家看到这里肯定是一脸懵逼,树的第一个节点是根节点,那么其他M个不同集合是什么,子树又是什么,子树的根节点又是什么?

欸,且别急,心急吃不了热豆腐(被打
我一一为大家解答。
我们先来看下一个经典的树长什么样的。
树以及二叉树的概念及其基本操作_第1张图片
这棵树的A节点就是根节点,它的下面有三个子树,BCD,在这张图中,我们先将这棵树分为两个部分,A节点以及它的子树BCD;

B子树:包括BEF三个节点;
C子树:包括CGK三个节点;
D子树:包括DHIJL五个节点;

所谓子树的根节点就是子树的第一个节点,比如上面,B子树的根节点就是B节点,而B子树又有两个子树,E和F,E又是E子树的根节点,F又是F子树的根节点,并且我们可以发现,B子树和C子树或者D子树的后续子节点的个数不相同,这就是每个子树有N个后续(N>=0),N不一定相同。

那么为什么说树是递归定义的呢?

依旧拿上面的图解释一下,我们想要创建A树,我们第一步肯定是要创建A这个节点,创建好A节点后,我们就需要再创建B子树,而创建B子树我们在创建B节点后又需要创建E和F两个子树,依次类推,我们依次建立节点,实现A树。
树以及二叉树的概念及其基本操作_第2张图片

2.树的相关概念

在树里面有许多特别的概念,这里通过这张图来一一解释。
树以及二叉树的概念及其基本操作_第3张图片

节点的度一个节点所含有的子树的个数为该节点的度,如上图A的度为3,B的度为2。
叶节点:度为0的节点,如上图的K,L等是叶节点。
分治节点:度不为0的节点,如上图的B,C,D等。
双亲节点:若一个节点含有子节点,则该节点为其子节点的双亲节点,如A是B,C,D的双亲节点。
子节点:一个节点含有的子树的根节点称为该节点的子节点,如B是A的子节点。
**兄弟节点:具有相同父亲节点的节点称为兄弟节点,**如E,F是一对兄弟节点。
树的度:树中最大的节点的度称为树的度,如该树的度是3。
节点的层次:从根开始定义,根为第一层,其子节点为第二层,依次类推,如上图A在第一层,BCD在第二层,EFGHIJ在第三层,KL在第四层。
树的高度和深度:树中节点的最大层次,如该树高度为四。
堂兄弟节点:双亲在同一层的节点互为堂兄弟,如上图中E和G互为堂兄弟。
节点的祖先:从根节点到该节点所经历的所以节点,如上图中K的祖先有G,C,A。
节点的子孙:以某节点为根的子树上的任意节点都是该节点的子孙,如所以节点都是A的子孙。
森林:有m(m>0)棵互不相交的树的集合称为森林

3.树的表示

了解了树的基本概念,我们来聊聊树的表示。
假设我们需要这样一颗树:

树以及二叉树的概念及其基本操作_第4张图片
如果我们写一个结构体,那我们可能会这样写:

typedef struct TreeNode{
	int data;
	struct TreeNode* T1;
	struct TreeNode* T2;
	struct TreeNode* T3;
}Node;

用这个结构体确实能够满足我们的要求,实现出这棵树,但是我们回过头看看树的定义;
在这里插入图片描述
树的定义是说树可以有多个后续,可没规定只有三个后续啊,那么我们该怎么办呢?
实际上,有一个大佬想出了一个办法,那就是孩子兄弟表示法

3.1 孩子兄弟表示法

先来看看孩子兄弟表示法的代码,再来细细说明其精妙之处;

struct Node
{
	int data;
	struct Node* firstchild;
	struct Node* nextbro;
};

大家乍眼一看,肯定是满头问号:你这怎么才两个指针?怎么比刚才还少,怎么实现树嘛!你给我去spa!
在这里插入图片描述

欸,大家且莫急,听我细细说来。
这个结构体十分简单,首先,第一个指针firstchild是指向下一层的第一个节点,拿之前的图来说
树以及二叉树的概念及其基本操作_第5张图片
这里A在第一层,BCD在第二层,而A的firstchild应该指向B,而非其它位置,而B的nextbro指针则指向同一层的C节点,D的nextbro则指向NULL,因为这一层只有它们三个节点,而其他节点也是如此,用图表示应该是这样:
树以及二叉树的概念及其基本操作_第6张图片

由于本人偷懒 篇幅限制,图并未画全,但是大家应该给能够明白孩子兄弟表示法是怎么一回事了。

4.树的应用

大家也许对树现在有了一定的理解,那么树用在哪里呢?

想必看到这里的大家都是用过电脑的吧(废话),那么我们一定见识过文件夹,文件夹就是一个树的结构;
树以及二叉树的概念及其基本操作_第7张图片
就拿本人的u盘来说,我们将此电脑视作根节点,此电脑下面有三个子节点,C,D,F盘,其中各自每一个盘都有自己的文件夹,用孩子兄弟法来说,F盘的firstchild指针就指向第一个文件夹,而第一个文件夹则指向同一层的其他文件夹,依次类推,组成一个具有层次感的结构。

二叉树

1.二叉树的基本概念

在了解树的基本概念后,我们再来了解二叉树的基本概念。

二叉树,其实就是树的一种特殊的形态,只不过这个树只有两个指针。

struct Tree{
	int data;
	struct Tree* lchild;
	struct Tree* rchild;
};

这就是一个基本的二叉树结构体。

大家乍眼一看,是不是感觉很熟悉?
是的,这个和孩子兄弟表示法的结构是一样的,都是只有两个指针,但是为什么这个表示二叉树,而那个表示树呢?

因为指针名字不一样

因为它们指针的用法不一样,孩子兄弟表示法的child指向下一层节点的第一个节点,bro指向同一层的下一个节点,而二叉树两个指针都指向下一层的节点。

树以及二叉树的概念及其基本操作_第8张图片
就比如这样,这就是一个经典的二叉树。
而根据左右节点,二叉树又有左右之分,比如上图中的根节点有左右两个子树,而左右两课子树又分别有左右两个子树。

2.特殊的二叉树

二叉树中有一种特殊的二叉树,叫完全二叉树。

何谓完全二叉树,就是除了最后一层,所有层数的节点都是满的,而且最后一层应该是从左至右依次有节点,这里我画一张图方便更好理解。
树以及二叉树的概念及其基本操作_第9张图片
看上图,这就是一个经典的完全二叉树,所谓这一层满节点,就是指在高度为h的那一层,应该有
2(h-1)个节点
,比如第一层就有20个节点,也就是一个节点,第二层有21个节点,也就是一个节点,而完全二叉树关键在于最后一层,需要从左至右依次有节点才行,比如上图中,只有第三层的第一个节点有左右节点,其他则没有。
树以及二叉树的概念及其基本操作_第10张图片
而这样,第三层第二个节点没有左节点却有右节点,这就不是完全二叉树了。

而完全二叉树中又有一种特殊的树叫满二叉树。所谓满二叉树,是说高度为h的树,有2h-1个节点,且每一层的节点都是2h-1个。
比如这样的:
树以及二叉树的概念及其基本操作_第11张图片

3.二叉树的性质

当我们了解二叉树的一些东西后,我们需要了解到,二叉树的一些特殊性质。

  1. 规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2(i-1) 个结点.
  2. 规定根节点的层数为1,则深度为h的二叉树的最大结点数是 2h-1.
  3. 对任何一棵二叉树, 如果度为0其叶结点个数为n0 , 度为2的分支结点个数为n2 ,则有 n0=n2 +1
  4. 若规定根节点的层数为1,具有n个结点的满二叉树的深度,h= log2(n+1). ( 是log以2
    为底,n+1为对数)
  5. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对于序号为i的结点有:
    5.1. 若i>0,i位置节点的双亲序号:(i-1)/2;i=0,i为根节点编号,无双亲节点
    5.2. 若2i+1=n否则无左孩子
    5.3. 若2i+2=n否则无右孩子

上面有一个经典的一句话是规定根节点层数为1,这是因为根据习惯不同,有的人规定根节点层数为0,有点规定为1,而所有关于二叉树节点,高度的计算都要通过层数计算,若是从第0层开始算,那么上面的公式又不会适用了,需要注意。

4.二叉树的存储结构

二叉树也有两种结构,一个是顺序结构,一个是链式结构 。

4.1二叉树的顺序结构

顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

4.2二叉树的链式结构

链式结构实际上就是用链表进行存储,通常由左右指针分别指向左孩子和右孩子所在地址,并且递归进行下去,直到孩子为NULL返回。
并且链式存储又分为前序,中序和后序进行存储,不过那都是在下一篇博客才能更加详细的了解了。

总结

树和二叉树作为数据结构的一个重点,需要对递归有深入的了解,希望看到这里的各位能够仔细思考二叉树递归创建应该如何创建,以便更好的自主学习。

你可能感兴趣的:(笔记,c语言笔记,算法,数据结构,算法,c语言)