数据结构(C语言描述)——认识树

一,树的性质与概念

一,节点与度

首先,我们需要了解树相关的两个重要概念——节点与度

节点是指其实就是指的是树的关节,其中树的第一个节点叫做根节点

度则是衡量节点分支多寡的一个概念,若一个节点无分支,则这个节点的度为零。

以下是有关节点和度的相关概念:

树的许多概念是由树的生物结构和人类亲缘关系所结合而定义的;
节点的度 :一个节点含有的子树的个数称为该节点的度; 如上图: A 的为 6
叶节点或终端节点 :度为 0 的节点称为叶节点; 如上图: B C H I... 等节点为叶节点
非终端节点或分支节点 :度不为 0 的节点; 如上图: D E F G... 等节点为分支节点
双亲节点或父节点 :若一个节点含有子节点,则这个节点称为其子节点的父节点; 如上图: A B 的父节点;
孩子节点或子节点 :一个节点含有的子树的根节点称为该节点的子节点; 如上图: B A 的孩子节点;
兄弟节点 :具有相同父节点的节点互称为兄弟节点; 如上图: B C 是兄弟节点;
树的度 :一棵树中,最大的节点的度称为树的度; 如上图:树的度为 6;
节点的层次 :从根开始定义起,根为第 1 层,根的子节点为第 2 层,以此类推;
树的高度或深度 :树中节点的最大层次; 如上图:树的高度为 4;
堂兄弟节点 :双亲在同一层的节点互为堂兄弟;如上图: H I 互为兄弟节点;
节点的祖先 :从根到该节点所经分支上的所有节点;如上图: A 是所有节点的祖先;
子孙 :以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是 A 的子孙;
森林 :由 m m>0 )棵互不相交的树的集合称为森林;
注意:习惯上,树的高度或深度从零开始,即一个树为空树时,其高度或深度为零;

二,树的概念

接下来,我们一起了解一下树的概念:
树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。
——把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
——有一个特殊的结点,称为根结点,根节点没有前驱结点
——除根节点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……、Tm,其中每一个集合Ti(1<= i <= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继
因此,树是递归定义的。

二,树的储存方式

方法一:已知树的度,直接定义

了解了树的定义之后,我们应该怎样把树这一种数据结构通过代码实现出来呢?
那么首先,我们肯定是要先构造一个树的结构体:
    typedef int DataType;

	struct TreeNode {
	DataType* a;
    struct TreeNode* child1;//储存第一个孩子的地址
    struct TreeNode* child2;//储存第二个孩子的地址

    //.....
	
	};

如果按以上方式去定义一个树的结构体,那肯定只能是在已知树的度的前提下我们才能这样做;这样做显然局限性很大,那么如果不知道树的度,该如何去定义树的结构体呢?

方法二:利用顺序表结构定义

答案就是利用顺序表储存,实现方式如下:

    typedef int DataType;

	struct TreeNode {
	DataType* a;
	struct TreeNode** childarr;//一个结构体指针数组,用来存储子节点的地址
	int size;
	int capacity;
	};

在结构体内添加一个类似顺序表的结构,这样便能表示树了。但是上面这种实现方式任然存在一些问题:结构体指针childarr的初始容量该定义为多大?按怎样的方式进行扩容?等等。这些问题虽然可以解决,但是几乎不可避免的会导致内存空间的浪费,所以还有没有更加简约有效的实现方式?

方法三:左孩子右兄弟表示法

有!左孩子右兄弟表示法(之后实现二叉树使用的是左孩子右孩子表示法,切勿混淆)

    typedef int DataType;
	struct TreeNode {
	DataType* a;
	struct TreeNode* Firstchild;//第一个孩子的地址
	struct TreeNode* Nextbrother;//下一个兄弟的地址
	};

像这样,一个指针指向节点的第一个孩子节点的地址,一个指针指向其最近的兄弟节点的地址,就能完整的表示出树的结构。这里需要注意的是,树这一数据结构本身是没有顺序的,但是在这样的结构体定义下,同一父亲节点的子节点就有了先后顺序。

如图,按照左孩子右兄弟的实现方式,树的逻辑结构就会由左图变成右图(笔者亲绘)
这种实现方式是目前而言使用较为广泛且非常实用的一种实现方式。

方法四:双亲表示法

除了以上三种实现方式之外,还有一种比较常用的的实现树的方法——双亲表示法。这个方法常常用于一些特定的问题,用来寻找父亲节点十分便捷,具体实现如下:
    typedef int DataType;

	struct TreeNode {
	DataType* a;
	int parent;//存储父亲节点的下标
	};

上图使用双亲表示法实现可获得如下表格:

节点对应下标节点节点对应父亲节点下标
1A0
2B1
2C1
3E2
3F2
3G2

以上便是描述树这一结构的四种实现方式,接下来让我们看一看树这一结构在生活中有什么具体的应用吧!

三,树结构的应用

Linux文件管理系统

如图,是linux文件管理系统的示意图,使用的正是我们刚刚学习的树结构。不过在Windows系统中,文件管理系统则是森林结构(由多颗树组成),你可以点开你的文件资源管理器看看我说的对不对噢!

四,全文总结

本文介绍了树的相关概念和储存方式,其中不同节点之间的关系是重中之重,切勿混淆;树的四种不同的储存方式中,左孩子右兄弟表示法是最为常用的一种方法,需要牢记;

下期预告

如图,这是一棵树,但它的结构却完美满足我们下一期将要学习的满二叉树的结构(下一期内容预告:二叉树与堆)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值