树和森林
一、树和森林的定义和性质
1、树的定义
树是n个结点的有限集合。
树可以为空树,即结点数为零。并且任意一颗非空树有以下特点:
1. 有且仅有一个根结点;
2. 当树的结点数大于1时,其余结点可分为多个结点的有限集合,这些集合的每一个又是一棵树,因此为根结点的子树。
2、树中的相关术语
假如有一棵树如下图所示:
祖先结点:从根节点到某个节点的路径上的所有节点都是该结点的祖先结点。比如L结点对应的 从根结点的路径是:A->B->E->L,因此A,B,E都是L的祖先结点。根节点没有祖先结点,它是所有结点的祖先。
子孙结点:子孙结点和祖先结点相对应,以某个结点为根结点的子树中的结点都是该结点的子孙结点。对应上面的路径,B,E,L都是A结点的子孙结点,树中所有结点(除根节点)都是根节点的子孙结点。
结点的度:树中一个结点的子结点的个数。比如上述树中B的度是2,因为他有E,F两个子结点,A结点的度是3…
树的度:树中结点最大度数。上述树的度为3.
分支结点:度数大于0的结点。
终端结点:又称叶子结点,度为0的结点,上述树的叶子结点为F,G,H,I,J,K,L。
结点的层次:从根结点开始数,根结点的层次为1,比如L的层次为4.
结点的深度:从根节点开始自顶向下逐层累加的。
结点的高度:从叶结点开始自底向上逐层累加的。
树的高度:又称深度,是树中结点的最大层数。上述树的高度是4。
有序树:树中的结点的子树从左到右是由次序的不能交换。
无序树:树中的结点没有次序可以交换。
3、树的性质
- 树中结点数等于所有结点的度数加1;
- 度为m的树第i层上至多m^(i-1)个结点;
- 高度为h的m叉树至多有(m^h-1)/(m-1)个结点;
- 具有n个结点的m叉树的最小高度为(取上限(log_m(n(m-1)+1)))。
4、森林的定义
森林:森林是m(m>=0)棵互不相交的树的集合。
二、树的存储结构
树的存储结构包括双亲表示法,孩子表示法,孩子兄弟表示法。
1、双亲表示法
双亲表示法:采用一维连续线性表存储,为每个结点增设一个伪指针,也就是数组中的下标指示其双亲在数组中的位置。
比如下图中根结点的下标为0,其伪指针为-1。
双亲表示法的存储结构描述:
typedef int ElemType;
#define MAX_SIZE 100
typedef struct
{
ElemType data; //数据
int parent; //祖先指针
}PTNode;
typedef struct
{
PTNode nodes[MAX_SIZE];
int n; //结点数目
}PTree;
2、孩子表示法
孩子表示法:每个结点的孩子结点都用链表链接起来组成一个线性结构
孩子表示法的结构定义:
#define MAX_SIZE 100
typedef int ElemType;
typedef struct PNode
{
int son; //孩子结点的下标
struct PNode* next; //下一个孩子结点
}PNode;
typedef struct TNode
{
ElemType data;
PNode* child; //孩子结点的指针
}PTree[MAX_SIZE];
3、孩子兄弟表示法
孩子兄弟表示法:又称二叉树表示法,孩子兄弟表示法有三部分内容:结点数据,指向第一个孩子的指针和指向下一个兄弟的指针。
孩子兄弟表示法的结构定义:
typedef int ElemType;
typedef struct CNode
{
ElemType data;
struct CNode* firstChild, *nextChild;
}CNode,* CTree;
三、树的相关操作
1、树、森林和二叉树的转换
树转换为二叉树的规则是:每个节点左指针指向它的第一个孩子结点,右指针指向它的相邻的兄弟结点,故表示为“左孩子右兄弟”。
森林转化为二叉树的规则和树转换为二叉树的规则相似:先将森林中的每一棵树转化为二叉树,再将第一棵树作为转化后的二叉树的根,第一棵树的坐姿树作为转化后的二叉树的左子树,第二课二叉树作为二叉树的右子树,第三棵二叉树作为转化后的二叉树的根的右子树的右子树。
从根节点开始,若右孩子存在,则把与右孩子结点的连线删除。再查看分离后的二叉树,若其根节点的右孩子存在,则连线删除…。直到所有这些根节点与右孩子的连线都删除为止。将每棵分离后的二叉树转换为树。
2、遍历
树的遍历分为先根遍历和后根遍历。
先根遍历:若树非空,则先访问根结点,再从左到右顺序遍历根结点的每一棵子树。
后根遍历:若树非空,则先从左到右顺序遍历根结点的每一棵子树,再访问根结点。
森林的遍历分为先序遍历和中序遍历。
先序遍历:若森林为非空,则先序遍历第一棵树,在先序遍历剩下的树构成的森林。
中序遍历:若森林为非空,则中序遍历第一棵树的根节点的子树森林,再访问第一棵树的根结点,再中序遍历除去第一棵树剩余的树构成的森林。