《大话数据结构》笔记--树

文章目录

    • 树的相关定义
      • 深度(高度)
    • 树的存储结构
      • 双亲表示法
      • 孩子表示法
        • 方法1
        • 方法2
      • 孩子兄弟表示法

树的相关定义

定义:树是n(n>=0)个结点的有限集。n=0称为空树。在任意一颗非空树中:

1)有且仅有一个特定的称为根的结点
2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集 T 1 , T 2 , . . . , T m T_1, T_2, ..., T_m T1,T2,...,Tm, 其中每一个集合本身又是一颗树,并称为根的子树。

结点拥有的子树数称为结点的, 度为0的结点称为叶结点或终端结点;度不为0的结点称为非终端结点或分支结点,树的度是树内结点的度的最大值。

深度(高度)

树中结点的最大层次称为树的深度或高度
《大话数据结构》笔记--树_第1张图片
注意两者度和深度概念的区别,在上图中,度为3,而深度为4

树的存储结构

充分利用顺序存储和链式存储结构的特点,实现对树的存储结构的表示,以下介绍三种表示方法

双亲表示法

假设以一组连续空间存储树的结点,同时在每个结点中,附设一个指示器指示其双亲结点在数组中的位置,也就是,每个结点除了知道自己是谁之外,还知道它的双亲在哪里。

data parent

其中data是数据域,存储结点的数据信息,parent是指针域,存储该结点的双亲在数组的下标
《大话数据结构》笔记--树_第2张图片
根据上图,可以得到如下的存储结构,其中约定根结点的位置域设置为-1

下标 data parent
0 A -1
1 B 0
2 C 0
3 D 0
4 E 1
5 F 1
6 G 2
7 H 3
8 I 3
9 J 3
10 K 4
11 L 4
12 M 7

以上的存储结构,我们可以很快地根据结点找出对应的双亲的结点,时间复杂度为O(1),但是如果想知道结点的孩子呢?我们需要遍历整个结构。怎么改进呢?通过增加一个结点最左边孩子的域,先称为长子域,约定没有孩子的结点,这个长子域设为-1,那么有

下标 data parent firstchild
0 A -1 1
1 B 0 4
2 C 0 6
3 D 0 7
4 E 1 10
5 F 1 -1
6 G 2 -1
7 H 3 12
8 I 3 -1
9 J 3 -1
10 K 4 -1
11 L 4 -1
12 M 7 -1

以上的结构解决了含有0或1个孩子的结点找孩子的问题。如果更关注兄弟间的关系,双亲表示法可以增加一个右兄弟关系,即每一个结点如果存在右兄弟,则记录下右兄弟的下标。

孩子表示法

方法1

多重链表表示法:每个结点有多个指针域,其中每个指针指向一颗子树的根结点

data child1 child2 childd

其中data是数据域。child1到childd是指针域,用来指向该结点的孩子结点。
《大话数据结构》笔记--树_第3张图片
对于上图来说,树的度是3,所以指针域的个数是3,实现如下图:
《大话数据结构》笔记--树_第4张图片
缺点:对于树中各结点的度相差很大时,造成空间浪费

方法2

每个结点指针域的个数等于该结点的度,专门取一个位置来存储结点指针域的个数
在这里插入图片描述
其中data为数据域,degree为度域,也就是存储结点的孩子结点的个数, child1到childd为指针域,指向该结点的各个孩子的结点
《大话数据结构》笔记--树_第5张图片
优点:克服了浪费空间的缺点,对空间利用率较高
缺点:各个结点的链表是不相同的结构,加上要维护结点的度的数值,时间复杂度较高
孩子表示法:把每个结点的孩子结点排列起来,以单链表作为存储结构,则n个结点有n个孩子链表,如果是叶子结点则此单链表为空。然后n个头指针作为一个线性表,采用顺序存储结构,存放进一个一维数组,实现如下图:
《大话数据结构》笔记--树_第6张图片

孩子兄弟表示法

任意一棵树,它的结点的第一个孩子如果存在就是唯一的,它的右兄弟如果存在也是唯一的。,因此,我们设置两个指针,分别指向该结点的第一个孩子和此结点的右兄弟。
在这里插入图片描述
《大话数据结构》笔记--树_第7张图片

你可能感兴趣的:(数据结构与算法)