树的定义
树(tree)是n(n>=0)个节点的有限集.n=0时为空树.在任意一颗非空树中:
(1) 有且仅有一个特定的称为根(root)的节点;
(2)当n>1时,其余节点可分为m(m>0)个互不相交的有限集 t1 t2…tm,其中每一个集合是一个子树,称为又根的子树.
注意 根的结点是唯一的.不可能存在多个根结点
子树的个数没有限制,但是它们一定是互不相交的.
结点的分类
(1)根结点
没有双亲的结点
(2)内部结点 :
度不为0的结点且有双亲
(3)叶子结点或终端结点
度为0的结点
度
结点拥有的子树称为结点的度(degree)
树的度:是树内各结点的度的最大值.
树的概念
结点的层次(level)
树中结点的最大层次称为树的深度(depth)或高度.
森林(forest)
是m(m>=0)棵互不相交的树的集合
树的存储结构
(1) 双亲表示法
在每个结点中,设一个指示器指示双亲结点到链表中的位置.
数据域 | 指针域 |
---|---|
data | parent |
优缺点
很容易找到它的双亲结点.时间复杂度是O(1), parent是-1表示找到了树结点的根.
找结点的孩子比较困难,需要遍历整个结构才可以改进的数据结构
下标 data parent fristchild rightsib 0 A -1 -1 -1 1 B 0 3 2 2 C 0 4 -1 … … … … … 可以解决找结点孩子的问题和找兄弟之间的关系了
存储结构的设计是一个非常灵活的过程.一个存储结构设计得是否合理,取决于基于该存储结构的运算是否合适,是否方便,时间复杂度好不好等.
(2) 孩子表示法
把每个结点的孩子排列起来,一单链表的形式存储,则n个结点有n个孩子链表,如果是叶子结点,则此链表为空.然后n个头指针又组成一个线性表,采用顺序存储结构,存放进一个一维数组中
下标 | data | firstchild | child | next | child | next |
---|---|---|---|---|---|---|
0 | a | ——> | 1 | ——> | 2 | ^ |
1 | b | ——> | 3 | ^ | ||
2 | c | ——> | 4 | ——> | 5 | ^ |
链表孩子的结点
child next 其中 child是数据域,来存储某个结点在表头数组中的下标
next是指针域,指向某个结点的下一个孩子结点的指针.表头数组的表头结点
data firstchild data是数据域,firstchild是头指针域,存储该结点的孩子链表的头指针.
优缺点:
要查找某个结点的某个孩子,或者找某个结点的兄弟,只需查找到这个结点的孩子单链表即可.
遍历这棵树也很方便,对头结点的数组循环即可
超找某个结点的双亲是谁,比较麻烦,需要遍历整棵树才可以.
(3) 孩子兄弟表示法
任意一棵树,它的结点的第一个孩子如果存在就是唯一的,它的兄弟如果存在也是唯一的.因此,我们设置两个指针,分别指向该结点的第一个孩子和此节点的右兄弟.
data firstchild rightsib 其中data是数据域,firstchild为指针域,存储该结点的第一个孩子结点的存储地址,rightsib是指针域,存储该结点的右兄弟结点的存储地址.
优缺点:
查找某个结点的某个孩子非常方便,只需要通过firstchild找到此结点的长子,然后再通过长子结点的rightsib找到它的二弟,一直下去,便可找到具体的孩子.
查找某个结点的双亲是有问题的,可以通过添加一个parent指针域来解决.