目录
森林: m个互不相交的森林树的集合,子树的集合称为子树的森林。
树的存储结构
双亲表示法
由于除了根节点之外的每一个节点只有唯一的双亲,所以可以用双亲表示法来存储树的节点。
在双亲表示法中,通过一组连续的存储单元来存储树的节点,每个节点有两个域:data数据域 与 parent双亲域。双亲域用来指示双亲节点的位置。
优点:1.求树的根方便 2. 求某节点的双亲方便
缺点:不容易求某个节点的孩子,需要遍历整个树的存储结构。
双亲存储的结构类型
typedef struct PTNode{
TElemType data; //数据域
int parent; //双亲的位置,根节点的双亲为-1
}PTNode; //双亲的节点类型
typedef struct {
PTNode *nodes; //初始化分配的结点数组
int r,nodeNum; //根的位置和结点数
}PTree; //树的双亲存储结构类型
孩子表示法
由于树中每个节点可能有多颗子树,所以可用多重链表,即每个节点有多个指针域,其中每个指针指向一个子树的根节点。
与双亲表示法相反,孩子表示法方便于涉及孩子的操作的实现。可以把双亲表示法和孩子表示法结合起来:双亲孩子表示法,也就是把双亲和孩子链表合在一起。
带双亲的孩子链表
typedef struct ChildNode{
int childIndex; //孩子在结点数组的位置
struct ChildNode *nextChild; //下一个孩子
}ChildNode; //孩子链表中的节点类型
typdef struct{
TElemType data; //元素值
int parent; //双亲的位置
struct ChildNode *firstChild; //孩子链表头指针
}PCTreeNode; //双亲节点的节点类型
typedef struct{
PCTreeNode *nodes; //节点数组
int nodeNum,r; //结点元素的个数,根位置
}PCTree; //树的双亲孩子存储结构类型
孩子兄弟表示法
孩子兄弟表示法以二叉链表作为树的存储结构。该存储结构中的两个链域分别指向该结点的第一个孩子和该节点的下一个兄弟节点,分别为 firstchild域 和 nextsibling域,便于将一般的树转换为二叉树进行处理。所以该表示法又称为二叉树表示法或二叉链表表示法
孩子兄弟表示法表示的节点
树的二叉链表存储
typedef struct CSNode
{
ElemType data;
struct CSNode *firstchild, *nextsibling;
} CSNode,*CSTree;
森林与二叉树的转换
森林转二叉树
树变二叉根相连
(1)把每棵树转换为二叉树。
(2)第一棵二叉树不动,从第二棵二叉树开始,依次把后一棵二叉树的根结点作为前一棵二叉树的根结点的右孩子,用线连接起来。
二叉树转为森林
去掉全部右孩线,孤立二叉再还原
(1)从根节点开始,若右孩子存在,则把与右孩子结点的连线删除。再查看分离后的二叉树,若其根节点的右孩子存在,则连线删除…。直到所有这些根节点与右孩子的连线都删除为止。
(2)将每棵分离后的二叉树转换为树。
树变二叉树
兄弟相连留长子,调整
(1)加线。在所有兄弟结点之间加一条连线。
(2)去线。树中的每个结点,只保留它与第一个孩子结点的连线,删除它与其它孩子结点之间的连线。
(3)调整
二叉树转为一般树
左孩右右连双亲,去掉原来右孩线,调整
1)加线。若某结点X的左孩子结点存在,则将这个左孩子的右孩子结点、右孩子的右孩子结点、右孩子的右孩子的右孩子结点…,都作为结点X的孩子。将结点X与这些右孩子结点用线连接起来。
(2)去线。删除原二叉树中所有结点与其右孩子结点的连线。
(3)调整。
森林的遍历
先序遍历
若森林非空:
1. 访问森林中第一棵树的根节点
2. 先序遍历第一棵树的根节点的子树森林
3. 先序遍历除去第一棵树之后剩余的树构成的森林
中序遍历
若森林非空:
1. 中序遍历森林中第一棵树的根节点的子树森林
2. 访问第一棵树的根节点
3. 中序遍历除去第一棵树之后剩余的树构成的森林