树的概述
树是一种非常常用的数据结构,树与前面介绍的线性表,栈,队列等线性结构不同,树是一种非线性结构
1.树的定义和基本术语
计算机世界里的树,是从自然界中实际的树抽象而来的,它指的是N个有父子关系的节点的有限集合。对于这个有限的节点集合而言,它满足如下条件:
当N=0时,改节点集合为空,这课树也被称为空树
在任意的非空树中,有且仅有一个根(root)节点
当N>1时,除根节点以外的其余节点可分为M个互为相交的有限集合T1,T2,...,Tm,其中的每个集合本身又是一棵树,并称其为根的子树(subtree)。
从上面定义可以发现树的递归特性:一棵树由根和若干棵子树组成,而每棵子树又由若干棵更小的子树组成。
树中任一节点可以有0或多个子节点,但只能有一个父节点。根节点是一个特例,根节点没有父节点,叶子节点没有子节点。树中每个节点既可以是其上一级节点的子节点,也可以是下一级节点的父节点,因此同一个节点既可以是父节点,也可以是子节点(类似于一个人—————他既是他儿子的父亲,又是他父亲的儿子)。
很显然,父子关系是一种非线性关系,所以树结构是非线性结构。
如果按节点是否包含子节点来分,节点可以分成以下两种:
普通节点:包含子节点的节点
叶子节点:没有子节点的节点,因此叶子节点不可作为父节点
如果按节点是否具有唯一的父节点来分,节点有可分为如下两种:
根节点:没有父节点的节点,根节点不可作为子节点
普通节点:具有唯一父节点的节点
一棵树只能有一个根节点,如果一棵树有了多个根节点,那么它已经不再是一棵树了,而是多棵树的集合,有时也被称为森林。示意图如下:
tree.PNG
与树有关的术语有如下一些:
节点:树的最基本组成单元,通常包括一个数据元素及若干指针用于指向其他节点。
节点的度:节点拥有的子树的个数被称为节点的度(degree)
树的度:树中所有节点的度的最大值就是该树的度
叶子节点:度为0的节点被称为叶子节点或终端节点
分支节点:度不为0的节点被称为分支节点或非终端节点
子节点,父节点,兄弟节点:节点的子树的根被称为该节点的子节点,而该节点称为子节点的父节点(parent).具有相同父节点的子节点之间互称为兄弟节点。
节点的层次(level):节点的层次从根开始算起,根的层次值为1,其余节点的层次值为父节点层次值加l。
树的深度(depth):树中节点的最大层次值称为树的深度或高度。
有序树与无序树:如果将树中节点的各棵子树看成从左到右是有序的(即不能互换),则称该树为有序树,否则称为无序树。
祖先节点(ancestor):从根到该节点所经分支上的所有节点
后代节点(descendant):以某节点为根的子树中任一节点都称为该节点的后代节点。
森林(forest):森林是;两颗或两颗以上互不相交的树的集合,删去一棵树的根,就得到一个森林。
树的基本操作
如果需要实现一棵树,程序不仅要以合适的方式保存该树的所有节点,还要记录节点与节点之间的父子关系。接下来,还应该为树实现如下基本操作。
初始化:通常是一个构造器,用于创建一棵空树,或者以指定节点为根来创建树。
为指定节点添加子节点
判断树是否为空
返回根节点
返回指定节点(非根节点)的父节点
返回指定节点(非叶子节点)的所有子节点
返回指定节点(非叶子节点)的第i个子节点
返回该树的深度
返回指定节点的位置
为了实现树这种数据结构,程序必须能记录节点与节点之间的父子关系,为此有一下两种选择:
父节点表示法:每个子节点都记录它的父节点。
子节点链表示法:每个非叶子节点通过一个链表来记录它所有的子节点。
父节点表示法
通过前面的介绍可以发现,树中除根节点之外的每个节点都有一个父节点。为了记录树中节点与节点之间的父子关系,可以为每个节点增加一个parent域,用以记录该节点的父节点。用如下图和如下表来表示
tree_show.PNG
数组索引
data
parent
0
A
-1
1
B
0
2
C
0
3
D
0
4
E
1
5
F
3
6
G
3
7
H
4
8
I
4
9
J
4
10
K
6
...
...
...
由此可见,只要用一个节点数组来保存树里的每个节点,并让每个节点记录其父节点在数组中的索引即可。
子节点链表表示法
父节点表示法的思想是让每个节点“记住”它的父节点的索引,父节点表示法是从子节点着手的;反过来,还有另外一种方式:让父节点“记住”它的所有子节点口在这种方式下,由于每个父节点需要记住多个子节点,因此必须采用“子节点链”表示法。示意图如下:
tree_linked.PNG
二叉树
二叉树的定义和基本概念
二叉树指的是每个节点最多只能有两个子树的有序树。通常左边的子树被称作“左子树”(left subtree),右边的子树被称为“右子树”(right subtree).由此可见,二叉树依然是树,它是一种特殊的树。
二叉树的每个节点最多只有来两颗树