树的存储结构-----2---孩子表示法

孩子表示法

换一种完全不同的考虑方法。

由于树中每个结点可能有多棵子树,我们可以设置,让每个结点有多个指针域,其中每个指针域指向一棵子树的根节点,我们把这种方法叫做多重链表表示法。

不过,树的每个结点的度,也就是它的孩子的个数是不同的。所以可以设置两种方案来解决。

方案一

一种是指针域的个数就等于树的度,树的度是树各个结点度的最大值。
在这里插入图片描述
data:数据域;
child:指针域,用来指向该结点的孩子结点。
在这里插入图片描述
上面这棵树的度是3,所以我们的指针域的个数是3,实现如下图:
在这里插入图片描述

问题1

这种方法,对于树中各结点的度相差很大时,显然是很浪费空间的,因为有很多的结点,它的指针都是空的。

不过,如果树的各结点度相差很小时,那就意味着开辟的空间被充分的利用了,这时,存储结构的缺点反而变成了优点。

方案2

既然很多指针都可能为空,为什么不按需分配空间呢?

于是,设计方案2,使每个结点的指针域的个数等于该结点的度,我们专门取一个位置来存放结点指针域的个数,其结构如图:
在这里插入图片描述
data:数据域;
degree:度域,也就是存储该结点的孩子结点的个数。
child:指针域,用来指向该结点的孩子结点。
在这里插入图片描述
在这里插入图片描述

问题2

这种方法克服了浪费空间的缺点,对空间利用率提高了,但是由于各个结点的链表时不相同的结构,加上要维护结点的度的数值,在运算上就会带来时间上的损耗。

所以,能否有更好的方法,既可以减少空指针的浪费又能使结点结构相同。

引出最终的-----孩子表示法

我们把每个结点放到一个顺序存储结构的数组里,再对每个结点的孩子建立一个单链表来体现它们的关系,这就是孩子表示法。

具体办法,把每个结点的孩子结点排列起来,以单链表作为存储结构,则n个结点有n个孩子链表,如果该结点是叶子结点,则此单链表为空。然后,n个头指针又组成一个线性表,采用顺序存储结构,存放进一个一维数组中。
在这里插入图片描述
在这里插入图片描述

为此,设计两种结点结构:

一个是孩子链表的孩子结点:

在这里插入图片描述
child:数据域,用来存储某个结点在表头数组中的下标;
next:指针域,用来存储指向某结点的下一个孩子结点的指针。

另一个是表头数组的表头结点:

在这里插入图片描述
data:数据域,存储某结点的数据信息;
firstchild:头指针域,存储该结点的孩子链表的头指针。

优点:

这样的结构对于我们要查找某个结点的某个孩子,或者某个结点的兄弟,只需要查找这个孩子结点的单链表即可,对于遍历整棵树也是很方便的,对头结点的数组循环即可。

缺点:

我们该如何知道某个结点的双亲是谁呢?比较麻烦,需要遍历整棵树才行。

解决:

把之前讲过的双亲表示法和孩子表示法综合一下:
在这里插入图片描述
我们把这种方法又称为双亲孩子表示法。


以上是《大话数据结构》阅读笔记!
  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值