树的存储结构
双亲表示法
一组连续空间存储树的结点,同时在每个结点中附设一个指示器指示其双亲结点在链表中的位置。
//------树的双亲表存储表示------
#define MAX_TREE_SIZE 100
typedef struct PTNode{//结点结构
TElemType data;
int parent;//双亲位置域
}PTNode;
typedef struct{//树结构
PTNode nodes[MAX_TREE_SIZE];
int r,n;//根的位置和结点数
}PTree;
孩子表示法
//------树的孩子链表存储表示------
#define MAX_TREE_SIZE 100
typedef struct CTNode{//孩子结点
int child;
struct CTNode *next;
}*ChildPtr;
typedef struct{
TElemType data;
ChildPtr firstchild;//孩子链表头指针
}CTBox;
typedef struct{
CTBox nodes[MAX_TREE_SIZE];
int n,r;//结点数和根的位置
}CTree;
也可以与双亲表示法结合起来,将双亲表示和孩子链表合在一起。
孩子兄弟表示法
又称二叉树表示法,或二叉链表表示法。以二叉链表作树的存储结构。链表中结点的两个链域分别指向该结点的第一个孩子结点和下一个兄弟结点,分别命名为 firstchild 域和 nextsibing 域。
//------树的二叉链表(孩子-兄弟)存储表示------
#define MAX_TREE_SIZE 100
typedef struct CSNode{
ElemType data;
struct CSNode *firstchild, *nextsibling;
}CSNode, *CSTree;
若要访问结点 x 的第 i 个孩子,则只要先从 firstchild 域找到第 1 个孩子结点,然后沿着孩子结点的 nextsibling 域连续走 i-1 步,便可找到 x 的第 i 个孩子。
森林与二叉树的转换
森林转换成二叉树
如果 F={T1, T2, … , Tm} 是森林,则可按如下规则转换成一颗二叉树 B=(root, LB, RB)。
- 若 F 为空,即 m=0,则 B 为空树;
- 若 F 非空,即 m≠0,则 B 的根 root 即为森林中第一棵树的根 ROOT(T1);B 的左子树 LB 是从 T1 中根结点的子树森林 F1={T11, T12, … , T1m1} 转换而成的二叉树;其右子树 RB 是从森林 F’={T2, T3, … , Tm} 转换而成的二叉树。
左孩子右兄弟
二叉树转换成森林
如果 B=(root, LB, RB) 是一棵二叉树,则可按如下规则转换成森林 F={T1, T2, … , Tm}:
- 若 B 为空,则 F 为空;
- 若 B 非空,则 F 中第一棵树 T1 的根 ROOT(T1) 即为二叉树 B 的根 root;T1 中根结点的子树森林 F1 是由 B 的左子树 LB 转换而成的森林;F 中除 T1 之外其余树组成的森林 F’={T2, T3, … , T`m} 是由 B 的右子树 RB 转换而成的森林。
树和森林的遍历
树
树:
先根(次序)遍历树: 先访问树的根结点,然后依次先根遍历根的每棵子树;
后根(次序)遍历树: 先依次后根遍历每一棵子树,然后访问根结点。
森林
- 先序遍历森林
若森林非空,则可按下述规则遍历之:
(1)访问森林中第一棵树的根结点;
(2)先序遍历第一棵树中根结点的子树森林;
(3)先序遍历除去第一棵树之后剩余的树构成的森林。 - 中序遍历森林
若森林非空,则可按下述规则遍历之:
(1)中序遍历森林中第一棵树的根结点的子树森林;
(2)访问第一棵树的根结点;
(3)中序遍历除去第一棵树之后剩余的树构成的森林。
上述森林的先序和中序遍历即为其对应的二叉树的额先序和中序遍历。