树 --->树

树的定义

树(Tree)是N(N>=0)个结点的有限集。当N=0时成为空树,在任意一棵非空树种:

-有且仅有一个特定的成为根(Root)的结点。

-当N>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2...Tm,其中每一个集合本身又是一棵树,并且成为根的子树(SubTree)。


虽然从概念上很容易理解树,但是有两点还是需要大家注意下

-n>0时,根结点是唯一的,坚决不可能存在多个根结点。

-m>0时,子树的个数是没有限制的,但他们互相是一定不会相交的。

结点分类

上图中,每一个圈圈我们就称为树的一个结点。结点拥有的子树称为结点的度-(Degree),树的度取树内各结点的度的最大值。

-度为0的结点称为叶结点(Leaf)或终端结点。

-度不为0的结点称为分支结点或非终端结点,除根结点外,分支结点也称为内部结点。


结点间的关系

结点的子树的根称为结点的孩子(Child),相应的,该结点称为孩子的双亲(Parent),同一双亲的孩子之间互称为兄弟(Sibling)。

结点的祖先是从根到该结点所经分支上的所有结点。


其他概念

如果将树中结点的各子树看成从左至右是有次序的,不能互换的,则称该树为有序树,否则称为无序树。

森林是m(m>=0)棵互不相交的树的集合。对树种每个结点而言,其子树的集合即为森林。

结点的层次

结点的层次(Level)从根开始定一起,根为第一层,根的孩子为第二层,

其双亲在同一层的结点互为堂兄弟。

树中结点的最大层次称为树的深度(Depth)或高度。



树的存储结构

要存储树,简单的顺序存储结构和链式存储结构是不能的,不过如果充分利用它们各自的特点,完全可以间接地来实现。要考虑到双亲,孩子,兄弟之间的关系。

这里介绍三种不同的表示法:双亲表示法,孩子表示法,孩子兄弟表示法。

双亲表示法

言外之意就是以双亲作为索引的关键词的一种存储方式。

我们假设以一组连续控件存储树的结点,同事在每个结点中,附设一个指示其双亲结点在数组中位置的元素。也就是说,每个结点除了知道自己是谁之外,还要知道它的爸爸妈妈在哪里。




这样的存储结构,我们可以根据某结点的parent指针找到它的双亲结点,所用的时间复杂度是O(1),索引到parent的值为-1时,表示找到了树结点的根。

可是如果我们要知道某节点的孩子是什么?那么不好意思,请遍历整个树结构。能不能改进一下呢?

当然,我们可以这样改进下:


那如果我们又比较它们兄弟之间的关系呢?



存储结构的设计是一个非常灵活的过程,只要你愿意,你可以设计出任何你想要的结构。

一个存储结构设计的是否合理,取决于基于该存储结构的运算是否适合,是否方便,时间复杂度好不好等等。

孩子表示法

这里给出一共三种方案,第一种:根据树的度,声明足够空间存放子树指针指针的节点。


但是这种方式呢,很明显造成资源的浪费。

针对方案一的缺点,我们有了方案二:


这样我们就克服了浪费这个概念,我们从此走上了节俭的社会主义道路,但每个节点的度的值不同,初始化和维护起来难度巨大,结构动态很复杂,花费了更多的时间。

下面这一种即节省了空间又节省了时间。


这种是数组和链表的搭配构成。但是上面只能找到孩子,找不到双亲貌似还不够完善,那么合并双亲孩子表示法:


那么在最后还有一种孩子兄弟表示法,构造方式也是大同小异,不多做解释,大家可以来思考。

那么上代码来写结构:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值