我们前面就说过,树是一种“一对多”的逻辑结构。那啥是树呢?树是n(n>=0)个结点的有限集,n=0时为空树。
在任意一颗非空树中:
1、有且仅有一个根结点,根结点是唯一的!!!
2、n>1时,其余结点可分为m个互不相交的有限集T1,T2,T3·····Tm,其中每一个集合本身又是一棵树,并且称为根的子树。子树绝对不相交!!!
一、基本概念
1、度与结点
结点的度:结点拥有的子树数,例:A的度为2,B的度为1,C的度为2,D,E,F的度为0
树的度:树内各结点度的最大值
叶子结点(终端结点):度为0的结点,即没有子树的结点,例:D,E,F
分支结点(非终端结点):度不为0的结点,例:A,B,C
内部结点:除根结点外的分支结点,例:B,C
2、孩子,双亲,兄弟,堂兄弟,祖先
结点的子树的根称为结点的孩子(child),该结点称为孩子的双亲(parent)(注意:不是父亲,不是母亲,是双亲!!),同一双亲的孩子之间互称为兄弟(sibling),双亲在同一层的结点互为堂兄弟。结点的祖先是从根到该结点所经分支上所有结点。
例:B,C是A的孩子,A是B,C的双亲,B,C互为兄弟,D,E互为堂兄弟,A,B是D的祖先
3、层次
从根开始,根为第1层,根的孩子为第2层····
4、深度/高度
树中结点的最大层次
5、有序树与无序树
如果将树中结点的各子树看成从左至右是有次序的,不能互换的,则称该树为有序树,否则称为无序树
6、森林
m棵互不相交的树的集合。对树中每个结点而言,其子树的集合即为森林。
二、树的存储结构
树不像线性表这样简单的结构,需要考虑双亲,孩子,兄弟之间的关系,因此简单的顺序存储与链式存储是不能存储树的,下面介绍三种融合顺序存储与链式存储的特点的表示法:双亲表示法,孩子表示法,双亲孩子表示法。
1、双亲表示法(数组)
双亲表示法,顾名思义,就是以双亲作为索引的关键词的一种存储方式。
以一组连续空间存储树的结点,同时在每个结点中,附设一个指示结点双亲在数组中所处位置的元素。简单来说,就是每个结点既要包含自己的信息,又要知道双亲在何处。这里注意,根结点的parent值设为-1
//结点定义
typedef struct PTNode
{
ElemType data;
int parent;
}
//树定义
typedef struct PTree
{
PTNode nodes[MAX_TREE_SIZE];
int r;//根的位置
int n;//结点数目
}
通过双亲表示法,我们可以根据某结点内含的parent位置信息很快找到双亲结点,时间复杂度为O(1);但是如果要想找到某结点的孩子则需要遍历整个树结构。
2、孩子表示法(数组+链表)
我们通过一个例子来介绍这种方法。
3、双亲孩子表示法
双亲孩子表示法=双亲表示法+孩子表示法
即在孩子表示法存放结点的数组中加一列存放各个结点的双亲位置
//定义孩子结点
typedef struct CTNode
{
int child;
struct CTNode *next;
}*ChildPtr;
//定义表头结构
typedef struct
{
ElemType data;
int parent;//存放双亲下标
ChildPtr firstchild;//指向第一个孩子
}CTBox;
BY ZJQ